View.java revision 956f340aacc7d8fc2d10f776551f13fde2d8d3ab
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.content.ClipData;
32import android.content.Context;
33import android.content.Intent;
34import android.content.res.ColorStateList;
35import android.content.res.Configuration;
36import android.content.res.Resources;
37import android.content.res.TypedArray;
38import android.graphics.Bitmap;
39import android.graphics.Canvas;
40import android.graphics.Insets;
41import android.graphics.Interpolator;
42import android.graphics.LinearGradient;
43import android.graphics.Matrix;
44import android.graphics.Outline;
45import android.graphics.Paint;
46import android.graphics.PixelFormat;
47import android.graphics.Point;
48import android.graphics.PorterDuff;
49import android.graphics.PorterDuffXfermode;
50import android.graphics.Rect;
51import android.graphics.RectF;
52import android.graphics.Region;
53import android.graphics.Shader;
54import android.graphics.drawable.ColorDrawable;
55import android.graphics.drawable.Drawable;
56import android.hardware.display.DisplayManagerGlobal;
57import android.os.Bundle;
58import android.os.Handler;
59import android.os.IBinder;
60import android.os.Parcel;
61import android.os.Parcelable;
62import android.os.RemoteException;
63import android.os.SystemClock;
64import android.os.SystemProperties;
65import android.os.Trace;
66import android.text.TextUtils;
67import android.util.AttributeSet;
68import android.util.FloatProperty;
69import android.util.LayoutDirection;
70import android.util.Log;
71import android.util.LongSparseLongArray;
72import android.util.Pools.SynchronizedPool;
73import android.util.Property;
74import android.util.SparseArray;
75import android.util.StateSet;
76import android.util.SuperNotCalledException;
77import android.util.TypedValue;
78import android.view.ContextMenu.ContextMenuInfo;
79import android.view.AccessibilityIterators.TextSegmentIterator;
80import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
81import android.view.AccessibilityIterators.WordTextSegmentIterator;
82import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
83import android.view.accessibility.AccessibilityEvent;
84import android.view.accessibility.AccessibilityEventSource;
85import android.view.accessibility.AccessibilityManager;
86import android.view.accessibility.AccessibilityNodeInfo;
87import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
88import android.view.accessibility.AccessibilityNodeProvider;
89import android.view.animation.Animation;
90import android.view.animation.AnimationUtils;
91import android.view.animation.Transformation;
92import android.view.inputmethod.EditorInfo;
93import android.view.inputmethod.InputConnection;
94import android.view.inputmethod.InputMethodManager;
95import android.widget.Checkable;
96import android.widget.ScrollBarDrawable;
97
98import static android.os.Build.VERSION_CODES.*;
99import static java.lang.Math.max;
100
101import com.android.internal.R;
102import com.android.internal.util.Predicate;
103import com.android.internal.view.menu.MenuBuilder;
104import com.google.android.collect.Lists;
105import com.google.android.collect.Maps;
106
107import java.lang.annotation.Retention;
108import java.lang.annotation.RetentionPolicy;
109import java.lang.ref.WeakReference;
110import java.lang.reflect.Field;
111import java.lang.reflect.InvocationTargetException;
112import java.lang.reflect.Method;
113import java.lang.reflect.Modifier;
114import java.util.ArrayList;
115import java.util.Arrays;
116import java.util.Collections;
117import java.util.HashMap;
118import java.util.List;
119import java.util.Locale;
120import java.util.Map;
121import java.util.concurrent.CopyOnWriteArrayList;
122import java.util.concurrent.atomic.AtomicInteger;
123
124/**
125 * <p>
126 * This class represents the basic building block for user interface components. A View
127 * occupies a rectangular area on the screen and is responsible for drawing and
128 * event handling. View is the base class for <em>widgets</em>, which are
129 * used to create interactive UI components (buttons, text fields, etc.). The
130 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
131 * are invisible containers that hold other Views (or other ViewGroups) and define
132 * their layout properties.
133 * </p>
134 *
135 * <div class="special reference">
136 * <h3>Developer Guides</h3>
137 * <p>For information about using this class to develop your application's user interface,
138 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
139 * </div>
140 *
141 * <a name="Using"></a>
142 * <h3>Using Views</h3>
143 * <p>
144 * All of the views in a window are arranged in a single tree. You can add views
145 * either from code or by specifying a tree of views in one or more XML layout
146 * files. There are many specialized subclasses of views that act as controls or
147 * are capable of displaying text, images, or other content.
148 * </p>
149 * <p>
150 * Once you have created a tree of views, there are typically a few types of
151 * common operations you may wish to perform:
152 * <ul>
153 * <li><strong>Set properties:</strong> for example setting the text of a
154 * {@link android.widget.TextView}. The available properties and the methods
155 * that set them will vary among the different subclasses of views. Note that
156 * properties that are known at build time can be set in the XML layout
157 * files.</li>
158 * <li><strong>Set focus:</strong> The framework will handled moving focus in
159 * response to user input. To force focus to a specific view, call
160 * {@link #requestFocus}.</li>
161 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
162 * that will be notified when something interesting happens to the view. For
163 * example, all views will let you set a listener to be notified when the view
164 * gains or loses focus. You can register such a listener using
165 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
166 * Other view subclasses offer more specialized listeners. For example, a Button
167 * exposes a listener to notify clients when the button is clicked.</li>
168 * <li><strong>Set visibility:</strong> You can hide or show views using
169 * {@link #setVisibility(int)}.</li>
170 * </ul>
171 * </p>
172 * <p><em>
173 * Note: The Android framework is responsible for measuring, laying out and
174 * drawing views. You should not call methods that perform these actions on
175 * views yourself unless you are actually implementing a
176 * {@link android.view.ViewGroup}.
177 * </em></p>
178 *
179 * <a name="Lifecycle"></a>
180 * <h3>Implementing a Custom View</h3>
181 *
182 * <p>
183 * To implement a custom view, you will usually begin by providing overrides for
184 * some of the standard methods that the framework calls on all views. You do
185 * not need to override all of these methods. In fact, you can start by just
186 * overriding {@link #onDraw(android.graphics.Canvas)}.
187 * <table border="2" width="85%" align="center" cellpadding="5">
188 *     <thead>
189 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
190 *     </thead>
191 *
192 *     <tbody>
193 *     <tr>
194 *         <td rowspan="2">Creation</td>
195 *         <td>Constructors</td>
196 *         <td>There is a form of the constructor that are called when the view
197 *         is created from code and a form that is called when the view is
198 *         inflated from a layout file. The second form should parse and apply
199 *         any attributes defined in the layout file.
200 *         </td>
201 *     </tr>
202 *     <tr>
203 *         <td><code>{@link #onFinishInflate()}</code></td>
204 *         <td>Called after a view and all of its children has been inflated
205 *         from XML.</td>
206 *     </tr>
207 *
208 *     <tr>
209 *         <td rowspan="3">Layout</td>
210 *         <td><code>{@link #onMeasure(int, int)}</code></td>
211 *         <td>Called to determine the size requirements for this view and all
212 *         of its children.
213 *         </td>
214 *     </tr>
215 *     <tr>
216 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
217 *         <td>Called when this view should assign a size and position to all
218 *         of its children.
219 *         </td>
220 *     </tr>
221 *     <tr>
222 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
223 *         <td>Called when the size of this view has changed.
224 *         </td>
225 *     </tr>
226 *
227 *     <tr>
228 *         <td>Drawing</td>
229 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
230 *         <td>Called when the view should render its content.
231 *         </td>
232 *     </tr>
233 *
234 *     <tr>
235 *         <td rowspan="4">Event processing</td>
236 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
237 *         <td>Called when a new hardware key event occurs.
238 *         </td>
239 *     </tr>
240 *     <tr>
241 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
242 *         <td>Called when a hardware key up event occurs.
243 *         </td>
244 *     </tr>
245 *     <tr>
246 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
247 *         <td>Called when a trackball motion event occurs.
248 *         </td>
249 *     </tr>
250 *     <tr>
251 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
252 *         <td>Called when a touch screen motion event occurs.
253 *         </td>
254 *     </tr>
255 *
256 *     <tr>
257 *         <td rowspan="2">Focus</td>
258 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
259 *         <td>Called when the view gains or loses focus.
260 *         </td>
261 *     </tr>
262 *
263 *     <tr>
264 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
265 *         <td>Called when the window containing the view gains or loses focus.
266 *         </td>
267 *     </tr>
268 *
269 *     <tr>
270 *         <td rowspan="3">Attaching</td>
271 *         <td><code>{@link #onAttachedToWindow()}</code></td>
272 *         <td>Called when the view is attached to a window.
273 *         </td>
274 *     </tr>
275 *
276 *     <tr>
277 *         <td><code>{@link #onDetachedFromWindow}</code></td>
278 *         <td>Called when the view is detached from its window.
279 *         </td>
280 *     </tr>
281 *
282 *     <tr>
283 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
284 *         <td>Called when the visibility of the window containing the view
285 *         has changed.
286 *         </td>
287 *     </tr>
288 *     </tbody>
289 *
290 * </table>
291 * </p>
292 *
293 * <a name="IDs"></a>
294 * <h3>IDs</h3>
295 * Views may have an integer id associated with them. These ids are typically
296 * assigned in the layout XML files, and are used to find specific views within
297 * the view tree. A common pattern is to:
298 * <ul>
299 * <li>Define a Button in the layout file and assign it a unique ID.
300 * <pre>
301 * &lt;Button
302 *     android:id="@+id/my_button"
303 *     android:layout_width="wrap_content"
304 *     android:layout_height="wrap_content"
305 *     android:text="@string/my_button_text"/&gt;
306 * </pre></li>
307 * <li>From the onCreate method of an Activity, find the Button
308 * <pre class="prettyprint">
309 *      Button myButton = (Button) findViewById(R.id.my_button);
310 * </pre></li>
311 * </ul>
312 * <p>
313 * View IDs need not be unique throughout the tree, but it is good practice to
314 * ensure that they are at least unique within the part of the tree you are
315 * searching.
316 * </p>
317 *
318 * <a name="Position"></a>
319 * <h3>Position</h3>
320 * <p>
321 * The geometry of a view is that of a rectangle. A view has a location,
322 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
323 * two dimensions, expressed as a width and a height. The unit for location
324 * and dimensions is the pixel.
325 * </p>
326 *
327 * <p>
328 * It is possible to retrieve the location of a view by invoking the methods
329 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
330 * coordinate of the rectangle representing the view. The latter returns the
331 * top, or Y, coordinate of the rectangle representing the view. These methods
332 * both return the location of the view relative to its parent. For instance,
333 * when getLeft() returns 20, that means the view is located 20 pixels to the
334 * right of the left edge of its direct parent.
335 * </p>
336 *
337 * <p>
338 * In addition, several convenience methods are offered to avoid unnecessary
339 * computations, namely {@link #getRight()} and {@link #getBottom()}.
340 * These methods return the coordinates of the right and bottom edges of the
341 * rectangle representing the view. For instance, calling {@link #getRight()}
342 * is similar to the following computation: <code>getLeft() + getWidth()</code>
343 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
344 * </p>
345 *
346 * <a name="SizePaddingMargins"></a>
347 * <h3>Size, padding and margins</h3>
348 * <p>
349 * The size of a view is expressed with a width and a height. A view actually
350 * possess two pairs of width and height values.
351 * </p>
352 *
353 * <p>
354 * The first pair is known as <em>measured width</em> and
355 * <em>measured height</em>. These dimensions define how big a view wants to be
356 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
357 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
358 * and {@link #getMeasuredHeight()}.
359 * </p>
360 *
361 * <p>
362 * The second pair is simply known as <em>width</em> and <em>height</em>, or
363 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
364 * dimensions define the actual size of the view on screen, at drawing time and
365 * after layout. These values may, but do not have to, be different from the
366 * measured width and height. The width and height can be obtained by calling
367 * {@link #getWidth()} and {@link #getHeight()}.
368 * </p>
369 *
370 * <p>
371 * To measure its dimensions, a view takes into account its padding. The padding
372 * is expressed in pixels for the left, top, right and bottom parts of the view.
373 * Padding can be used to offset the content of the view by a specific amount of
374 * pixels. For instance, a left padding of 2 will push the view's content by
375 * 2 pixels to the right of the left edge. Padding can be set using the
376 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
377 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
378 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
379 * {@link #getPaddingEnd()}.
380 * </p>
381 *
382 * <p>
383 * Even though a view can define a padding, it does not provide any support for
384 * margins. However, view groups provide such a support. Refer to
385 * {@link android.view.ViewGroup} and
386 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
387 * </p>
388 *
389 * <a name="Layout"></a>
390 * <h3>Layout</h3>
391 * <p>
392 * Layout is a two pass process: a measure pass and a layout pass. The measuring
393 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
394 * of the view tree. Each view pushes dimension specifications down the tree
395 * during the recursion. At the end of the measure pass, every view has stored
396 * its measurements. The second pass happens in
397 * {@link #layout(int,int,int,int)} and is also top-down. During
398 * this pass each parent is responsible for positioning all of its children
399 * using the sizes computed in the measure pass.
400 * </p>
401 *
402 * <p>
403 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
404 * {@link #getMeasuredHeight()} values must be set, along with those for all of
405 * that view's descendants. A view's measured width and measured height values
406 * must respect the constraints imposed by the view's parents. This guarantees
407 * that at the end of the measure pass, all parents accept all of their
408 * children's measurements. A parent view may call measure() more than once on
409 * its children. For example, the parent may measure each child once with
410 * unspecified dimensions to find out how big they want to be, then call
411 * measure() on them again with actual numbers if the sum of all the children's
412 * unconstrained sizes is too big or too small.
413 * </p>
414 *
415 * <p>
416 * The measure pass uses two classes to communicate dimensions. The
417 * {@link MeasureSpec} class is used by views to tell their parents how they
418 * want to be measured and positioned. The base LayoutParams class just
419 * describes how big the view wants to be for both width and height. For each
420 * dimension, it can specify one of:
421 * <ul>
422 * <li> an exact number
423 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
424 * (minus padding)
425 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
426 * enclose its content (plus padding).
427 * </ul>
428 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
429 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
430 * an X and Y value.
431 * </p>
432 *
433 * <p>
434 * MeasureSpecs are used to push requirements down the tree from parent to
435 * child. A MeasureSpec can be in one of three modes:
436 * <ul>
437 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
438 * of a child view. For example, a LinearLayout may call measure() on its child
439 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
440 * tall the child view wants to be given a width of 240 pixels.
441 * <li>EXACTLY: This is used by the parent to impose an exact size on the
442 * child. The child must use this size, and guarantee that all of its
443 * descendants will fit within this size.
444 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
445 * child. The child must guarantee that it and all of its descendants will fit
446 * within this size.
447 * </ul>
448 * </p>
449 *
450 * <p>
451 * To initiate a layout, call {@link #requestLayout}. This method is typically
452 * called by a view on itself when it believes that is can no longer fit within
453 * its current bounds.
454 * </p>
455 *
456 * <a name="Drawing"></a>
457 * <h3>Drawing</h3>
458 * <p>
459 * Drawing is handled by walking the tree and recording the drawing commands of
460 * any View that needs to update. After this, the drawing commands of the
461 * entire tree are issued to screen, clipped to the newly damaged area.
462 * </p>
463 *
464 * <p>
465 * The tree is largely recorded and drawn in order, with parents drawn before
466 * (i.e., behind) their children, with siblings drawn in the order they appear
467 * in the tree. If you set a background drawable for a View, then the View will
468 * draw it before calling back to its <code>onDraw()</code> method. The child
469 * drawing order can be overridden with
470 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
471 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
472 * </p>
473 *
474 * <p>
475 * To force a view to draw, call {@link #invalidate()}.
476 * </p>
477 *
478 * <a name="EventHandlingThreading"></a>
479 * <h3>Event Handling and Threading</h3>
480 * <p>
481 * The basic cycle of a view is as follows:
482 * <ol>
483 * <li>An event comes in and is dispatched to the appropriate view. The view
484 * handles the event and notifies any listeners.</li>
485 * <li>If in the course of processing the event, the view's bounds may need
486 * to be changed, the view will call {@link #requestLayout()}.</li>
487 * <li>Similarly, if in the course of processing the event the view's appearance
488 * may need to be changed, the view will call {@link #invalidate()}.</li>
489 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
490 * the framework will take care of measuring, laying out, and drawing the tree
491 * as appropriate.</li>
492 * </ol>
493 * </p>
494 *
495 * <p><em>Note: The entire view tree is single threaded. You must always be on
496 * the UI thread when calling any method on any view.</em>
497 * If you are doing work on other threads and want to update the state of a view
498 * from that thread, you should use a {@link Handler}.
499 * </p>
500 *
501 * <a name="FocusHandling"></a>
502 * <h3>Focus Handling</h3>
503 * <p>
504 * The framework will handle routine focus movement in response to user input.
505 * This includes changing the focus as views are removed or hidden, or as new
506 * views become available. Views indicate their willingness to take focus
507 * through the {@link #isFocusable} method. To change whether a view can take
508 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
509 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
510 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
511 * </p>
512 * <p>
513 * Focus movement is based on an algorithm which finds the nearest neighbor in a
514 * given direction. In rare cases, the default algorithm may not match the
515 * intended behavior of the developer. In these situations, you can provide
516 * explicit overrides by using these XML attributes in the layout file:
517 * <pre>
518 * nextFocusDown
519 * nextFocusLeft
520 * nextFocusRight
521 * nextFocusUp
522 * </pre>
523 * </p>
524 *
525 *
526 * <p>
527 * To get a particular view to take focus, call {@link #requestFocus()}.
528 * </p>
529 *
530 * <a name="TouchMode"></a>
531 * <h3>Touch Mode</h3>
532 * <p>
533 * When a user is navigating a user interface via directional keys such as a D-pad, it is
534 * necessary to give focus to actionable items such as buttons so the user can see
535 * what will take input.  If the device has touch capabilities, however, and the user
536 * begins interacting with the interface by touching it, it is no longer necessary to
537 * always highlight, or give focus to, a particular view.  This motivates a mode
538 * for interaction named 'touch mode'.
539 * </p>
540 * <p>
541 * For a touch capable device, once the user touches the screen, the device
542 * will enter touch mode.  From this point onward, only views for which
543 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
544 * Other views that are touchable, like buttons, will not take focus when touched; they will
545 * only fire the on click listeners.
546 * </p>
547 * <p>
548 * Any time a user hits a directional key, such as a D-pad direction, the view device will
549 * exit touch mode, and find a view to take focus, so that the user may resume interacting
550 * with the user interface without touching the screen again.
551 * </p>
552 * <p>
553 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
554 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
555 * </p>
556 *
557 * <a name="Scrolling"></a>
558 * <h3>Scrolling</h3>
559 * <p>
560 * The framework provides basic support for views that wish to internally
561 * scroll their content. This includes keeping track of the X and Y scroll
562 * offset as well as mechanisms for drawing scrollbars. See
563 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
564 * {@link #awakenScrollBars()} for more details.
565 * </p>
566 *
567 * <a name="Tags"></a>
568 * <h3>Tags</h3>
569 * <p>
570 * Unlike IDs, tags are not used to identify views. Tags are essentially an
571 * extra piece of information that can be associated with a view. They are most
572 * often used as a convenience to store data related to views in the views
573 * themselves rather than by putting them in a separate structure.
574 * </p>
575 *
576 * <a name="Properties"></a>
577 * <h3>Properties</h3>
578 * <p>
579 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
580 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
581 * available both in the {@link Property} form as well as in similarly-named setter/getter
582 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
583 * be used to set persistent state associated with these rendering-related properties on the view.
584 * The properties and methods can also be used in conjunction with
585 * {@link android.animation.Animator Animator}-based animations, described more in the
586 * <a href="#Animation">Animation</a> section.
587 * </p>
588 *
589 * <a name="Animation"></a>
590 * <h3>Animation</h3>
591 * <p>
592 * Starting with Android 3.0, the preferred way of animating views is to use the
593 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
594 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
595 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
596 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
597 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
598 * makes animating these View properties particularly easy and efficient.
599 * </p>
600 * <p>
601 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
602 * You can attach an {@link Animation} object to a view using
603 * {@link #setAnimation(Animation)} or
604 * {@link #startAnimation(Animation)}. The animation can alter the scale,
605 * rotation, translation and alpha of a view over time. If the animation is
606 * attached to a view that has children, the animation will affect the entire
607 * subtree rooted by that node. When an animation is started, the framework will
608 * take care of redrawing the appropriate views until the animation completes.
609 * </p>
610 *
611 * <a name="Security"></a>
612 * <h3>Security</h3>
613 * <p>
614 * Sometimes it is essential that an application be able to verify that an action
615 * is being performed with the full knowledge and consent of the user, such as
616 * granting a permission request, making a purchase or clicking on an advertisement.
617 * Unfortunately, a malicious application could try to spoof the user into
618 * performing these actions, unaware, by concealing the intended purpose of the view.
619 * As a remedy, the framework offers a touch filtering mechanism that can be used to
620 * improve the security of views that provide access to sensitive functionality.
621 * </p><p>
622 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
623 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
624 * will discard touches that are received whenever the view's window is obscured by
625 * another visible window.  As a result, the view will not receive touches whenever a
626 * toast, dialog or other window appears above the view's window.
627 * </p><p>
628 * For more fine-grained control over security, consider overriding the
629 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
630 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
631 * </p>
632 *
633 * @attr ref android.R.styleable#View_alpha
634 * @attr ref android.R.styleable#View_assistBlocked
635 * @attr ref android.R.styleable#View_background
636 * @attr ref android.R.styleable#View_clickable
637 * @attr ref android.R.styleable#View_contentDescription
638 * @attr ref android.R.styleable#View_drawingCacheQuality
639 * @attr ref android.R.styleable#View_duplicateParentState
640 * @attr ref android.R.styleable#View_id
641 * @attr ref android.R.styleable#View_requiresFadingEdge
642 * @attr ref android.R.styleable#View_fadeScrollbars
643 * @attr ref android.R.styleable#View_fadingEdgeLength
644 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
645 * @attr ref android.R.styleable#View_fitsSystemWindows
646 * @attr ref android.R.styleable#View_isScrollContainer
647 * @attr ref android.R.styleable#View_focusable
648 * @attr ref android.R.styleable#View_focusableInTouchMode
649 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
650 * @attr ref android.R.styleable#View_keepScreenOn
651 * @attr ref android.R.styleable#View_layerType
652 * @attr ref android.R.styleable#View_layoutDirection
653 * @attr ref android.R.styleable#View_longClickable
654 * @attr ref android.R.styleable#View_minHeight
655 * @attr ref android.R.styleable#View_minWidth
656 * @attr ref android.R.styleable#View_nextFocusDown
657 * @attr ref android.R.styleable#View_nextFocusLeft
658 * @attr ref android.R.styleable#View_nextFocusRight
659 * @attr ref android.R.styleable#View_nextFocusUp
660 * @attr ref android.R.styleable#View_onClick
661 * @attr ref android.R.styleable#View_padding
662 * @attr ref android.R.styleable#View_paddingBottom
663 * @attr ref android.R.styleable#View_paddingLeft
664 * @attr ref android.R.styleable#View_paddingRight
665 * @attr ref android.R.styleable#View_paddingTop
666 * @attr ref android.R.styleable#View_paddingStart
667 * @attr ref android.R.styleable#View_paddingEnd
668 * @attr ref android.R.styleable#View_saveEnabled
669 * @attr ref android.R.styleable#View_rotation
670 * @attr ref android.R.styleable#View_rotationX
671 * @attr ref android.R.styleable#View_rotationY
672 * @attr ref android.R.styleable#View_scaleX
673 * @attr ref android.R.styleable#View_scaleY
674 * @attr ref android.R.styleable#View_scrollX
675 * @attr ref android.R.styleable#View_scrollY
676 * @attr ref android.R.styleable#View_scrollbarSize
677 * @attr ref android.R.styleable#View_scrollbarStyle
678 * @attr ref android.R.styleable#View_scrollbars
679 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
680 * @attr ref android.R.styleable#View_scrollbarFadeDuration
681 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
682 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
683 * @attr ref android.R.styleable#View_scrollbarThumbVertical
684 * @attr ref android.R.styleable#View_scrollbarTrackVertical
685 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
686 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
687 * @attr ref android.R.styleable#View_stateListAnimator
688 * @attr ref android.R.styleable#View_transitionName
689 * @attr ref android.R.styleable#View_soundEffectsEnabled
690 * @attr ref android.R.styleable#View_tag
691 * @attr ref android.R.styleable#View_textAlignment
692 * @attr ref android.R.styleable#View_textDirection
693 * @attr ref android.R.styleable#View_transformPivotX
694 * @attr ref android.R.styleable#View_transformPivotY
695 * @attr ref android.R.styleable#View_translationX
696 * @attr ref android.R.styleable#View_translationY
697 * @attr ref android.R.styleable#View_translationZ
698 * @attr ref android.R.styleable#View_visibility
699 *
700 * @see android.view.ViewGroup
701 */
702public class View implements Drawable.Callback, KeyEvent.Callback,
703        AccessibilityEventSource {
704    private static final boolean DBG = false;
705
706    /**
707     * The logging tag used by this class with android.util.Log.
708     */
709    protected static final String VIEW_LOG_TAG = "View";
710
711    /**
712     * When set to true, apps will draw debugging information about their layouts.
713     *
714     * @hide
715     */
716    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
717
718    /**
719     * When set to true, this view will save its attribute data.
720     *
721     * @hide
722     */
723    public static boolean mDebugViewAttributes = false;
724
725    /**
726     * Used to mark a View that has no ID.
727     */
728    public static final int NO_ID = -1;
729
730    /**
731     * Signals that compatibility booleans have been initialized according to
732     * target SDK versions.
733     */
734    private static boolean sCompatibilityDone = false;
735
736    /**
737     * Use the old (broken) way of building MeasureSpecs.
738     */
739    private static boolean sUseBrokenMakeMeasureSpec = false;
740
741    /**
742     * Ignore any optimizations using the measure cache.
743     */
744    private static boolean sIgnoreMeasureCache = false;
745
746    /**
747     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
748     * calling setFlags.
749     */
750    private static final int NOT_FOCUSABLE = 0x00000000;
751
752    /**
753     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
754     * setFlags.
755     */
756    private static final int FOCUSABLE = 0x00000001;
757
758    /**
759     * Mask for use with setFlags indicating bits used for focus.
760     */
761    private static final int FOCUSABLE_MASK = 0x00000001;
762
763    /**
764     * This view will adjust its padding to fit sytem windows (e.g. status bar)
765     */
766    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
767
768    /** @hide */
769    @IntDef({VISIBLE, INVISIBLE, GONE})
770    @Retention(RetentionPolicy.SOURCE)
771    public @interface Visibility {}
772
773    /**
774     * This view is visible.
775     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
776     * android:visibility}.
777     */
778    public static final int VISIBLE = 0x00000000;
779
780    /**
781     * This view is invisible, but it still takes up space for layout purposes.
782     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
783     * android:visibility}.
784     */
785    public static final int INVISIBLE = 0x00000004;
786
787    /**
788     * This view is invisible, and it doesn't take any space for layout
789     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
790     * android:visibility}.
791     */
792    public static final int GONE = 0x00000008;
793
794    /**
795     * Mask for use with setFlags indicating bits used for visibility.
796     * {@hide}
797     */
798    static final int VISIBILITY_MASK = 0x0000000C;
799
800    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
801
802    /**
803     * This view is enabled. Interpretation varies by subclass.
804     * Use with ENABLED_MASK when calling setFlags.
805     * {@hide}
806     */
807    static final int ENABLED = 0x00000000;
808
809    /**
810     * This view is disabled. Interpretation varies by subclass.
811     * Use with ENABLED_MASK when calling setFlags.
812     * {@hide}
813     */
814    static final int DISABLED = 0x00000020;
815
816   /**
817    * Mask for use with setFlags indicating bits used for indicating whether
818    * this view is enabled
819    * {@hide}
820    */
821    static final int ENABLED_MASK = 0x00000020;
822
823    /**
824     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
825     * called and further optimizations will be performed. It is okay to have
826     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
827     * {@hide}
828     */
829    static final int WILL_NOT_DRAW = 0x00000080;
830
831    /**
832     * Mask for use with setFlags indicating bits used for indicating whether
833     * this view is will draw
834     * {@hide}
835     */
836    static final int DRAW_MASK = 0x00000080;
837
838    /**
839     * <p>This view doesn't show scrollbars.</p>
840     * {@hide}
841     */
842    static final int SCROLLBARS_NONE = 0x00000000;
843
844    /**
845     * <p>This view shows horizontal scrollbars.</p>
846     * {@hide}
847     */
848    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
849
850    /**
851     * <p>This view shows vertical scrollbars.</p>
852     * {@hide}
853     */
854    static final int SCROLLBARS_VERTICAL = 0x00000200;
855
856    /**
857     * <p>Mask for use with setFlags indicating bits used for indicating which
858     * scrollbars are enabled.</p>
859     * {@hide}
860     */
861    static final int SCROLLBARS_MASK = 0x00000300;
862
863    /**
864     * Indicates that the view should filter touches when its window is obscured.
865     * Refer to the class comments for more information about this security feature.
866     * {@hide}
867     */
868    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
869
870    /**
871     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
872     * that they are optional and should be skipped if the window has
873     * requested system UI flags that ignore those insets for layout.
874     */
875    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
876
877    /**
878     * <p>This view doesn't show fading edges.</p>
879     * {@hide}
880     */
881    static final int FADING_EDGE_NONE = 0x00000000;
882
883    /**
884     * <p>This view shows horizontal fading edges.</p>
885     * {@hide}
886     */
887    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
888
889    /**
890     * <p>This view shows vertical fading edges.</p>
891     * {@hide}
892     */
893    static final int FADING_EDGE_VERTICAL = 0x00002000;
894
895    /**
896     * <p>Mask for use with setFlags indicating bits used for indicating which
897     * fading edges are enabled.</p>
898     * {@hide}
899     */
900    static final int FADING_EDGE_MASK = 0x00003000;
901
902    /**
903     * <p>Indicates this view can be clicked. When clickable, a View reacts
904     * to clicks by notifying the OnClickListener.<p>
905     * {@hide}
906     */
907    static final int CLICKABLE = 0x00004000;
908
909    /**
910     * <p>Indicates this view is caching its drawing into a bitmap.</p>
911     * {@hide}
912     */
913    static final int DRAWING_CACHE_ENABLED = 0x00008000;
914
915    /**
916     * <p>Indicates that no icicle should be saved for this view.<p>
917     * {@hide}
918     */
919    static final int SAVE_DISABLED = 0x000010000;
920
921    /**
922     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
923     * property.</p>
924     * {@hide}
925     */
926    static final int SAVE_DISABLED_MASK = 0x000010000;
927
928    /**
929     * <p>Indicates that no drawing cache should ever be created for this view.<p>
930     * {@hide}
931     */
932    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
933
934    /**
935     * <p>Indicates this view can take / keep focus when int touch mode.</p>
936     * {@hide}
937     */
938    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
939
940    /** @hide */
941    @Retention(RetentionPolicy.SOURCE)
942    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
943    public @interface DrawingCacheQuality {}
944
945    /**
946     * <p>Enables low quality mode for the drawing cache.</p>
947     */
948    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
949
950    /**
951     * <p>Enables high quality mode for the drawing cache.</p>
952     */
953    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
954
955    /**
956     * <p>Enables automatic quality mode for the drawing cache.</p>
957     */
958    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
959
960    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
961            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
962    };
963
964    /**
965     * <p>Mask for use with setFlags indicating bits used for the cache
966     * quality property.</p>
967     * {@hide}
968     */
969    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
970
971    /**
972     * <p>
973     * Indicates this view can be long clicked. When long clickable, a View
974     * reacts to long clicks by notifying the OnLongClickListener or showing a
975     * context menu.
976     * </p>
977     * {@hide}
978     */
979    static final int LONG_CLICKABLE = 0x00200000;
980
981    /**
982     * <p>Indicates that this view gets its drawable states from its direct parent
983     * and ignores its original internal states.</p>
984     *
985     * @hide
986     */
987    static final int DUPLICATE_PARENT_STATE = 0x00400000;
988
989    /** @hide */
990    @IntDef({
991        SCROLLBARS_INSIDE_OVERLAY,
992        SCROLLBARS_INSIDE_INSET,
993        SCROLLBARS_OUTSIDE_OVERLAY,
994        SCROLLBARS_OUTSIDE_INSET
995    })
996    @Retention(RetentionPolicy.SOURCE)
997    public @interface ScrollBarStyle {}
998
999    /**
1000     * The scrollbar style to display the scrollbars inside the content area,
1001     * without increasing the padding. The scrollbars will be overlaid with
1002     * translucency on the view's content.
1003     */
1004    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1005
1006    /**
1007     * The scrollbar style to display the scrollbars inside the padded area,
1008     * increasing the padding of the view. The scrollbars will not overlap the
1009     * content area of the view.
1010     */
1011    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1012
1013    /**
1014     * The scrollbar style to display the scrollbars at the edge of the view,
1015     * without increasing the padding. The scrollbars will be overlaid with
1016     * translucency.
1017     */
1018    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1019
1020    /**
1021     * The scrollbar style to display the scrollbars at the edge of the view,
1022     * increasing the padding of the view. The scrollbars will only overlap the
1023     * background, if any.
1024     */
1025    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1026
1027    /**
1028     * Mask to check if the scrollbar style is overlay or inset.
1029     * {@hide}
1030     */
1031    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1032
1033    /**
1034     * Mask to check if the scrollbar style is inside or outside.
1035     * {@hide}
1036     */
1037    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1038
1039    /**
1040     * Mask for scrollbar style.
1041     * {@hide}
1042     */
1043    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1044
1045    /**
1046     * View flag indicating that the screen should remain on while the
1047     * window containing this view is visible to the user.  This effectively
1048     * takes care of automatically setting the WindowManager's
1049     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1050     */
1051    public static final int KEEP_SCREEN_ON = 0x04000000;
1052
1053    /**
1054     * View flag indicating whether this view should have sound effects enabled
1055     * for events such as clicking and touching.
1056     */
1057    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1058
1059    /**
1060     * View flag indicating whether this view should have haptic feedback
1061     * enabled for events such as long presses.
1062     */
1063    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1064
1065    /**
1066     * <p>Indicates that the view hierarchy should stop saving state when
1067     * it reaches this view.  If state saving is initiated immediately at
1068     * the view, it will be allowed.
1069     * {@hide}
1070     */
1071    static final int PARENT_SAVE_DISABLED = 0x20000000;
1072
1073    /**
1074     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1075     * {@hide}
1076     */
1077    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1078
1079    /** @hide */
1080    @IntDef(flag = true,
1081            value = {
1082                FOCUSABLES_ALL,
1083                FOCUSABLES_TOUCH_MODE
1084            })
1085    @Retention(RetentionPolicy.SOURCE)
1086    public @interface FocusableMode {}
1087
1088    /**
1089     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1090     * should add all focusable Views regardless if they are focusable in touch mode.
1091     */
1092    public static final int FOCUSABLES_ALL = 0x00000000;
1093
1094    /**
1095     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1096     * should add only Views focusable in touch mode.
1097     */
1098    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1099
1100    /** @hide */
1101    @IntDef({
1102            FOCUS_BACKWARD,
1103            FOCUS_FORWARD,
1104            FOCUS_LEFT,
1105            FOCUS_UP,
1106            FOCUS_RIGHT,
1107            FOCUS_DOWN
1108    })
1109    @Retention(RetentionPolicy.SOURCE)
1110    public @interface FocusDirection {}
1111
1112    /** @hide */
1113    @IntDef({
1114            FOCUS_LEFT,
1115            FOCUS_UP,
1116            FOCUS_RIGHT,
1117            FOCUS_DOWN
1118    })
1119    @Retention(RetentionPolicy.SOURCE)
1120    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1121
1122    /**
1123     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1124     * item.
1125     */
1126    public static final int FOCUS_BACKWARD = 0x00000001;
1127
1128    /**
1129     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1130     * item.
1131     */
1132    public static final int FOCUS_FORWARD = 0x00000002;
1133
1134    /**
1135     * Use with {@link #focusSearch(int)}. Move focus to the left.
1136     */
1137    public static final int FOCUS_LEFT = 0x00000011;
1138
1139    /**
1140     * Use with {@link #focusSearch(int)}. Move focus up.
1141     */
1142    public static final int FOCUS_UP = 0x00000021;
1143
1144    /**
1145     * Use with {@link #focusSearch(int)}. Move focus to the right.
1146     */
1147    public static final int FOCUS_RIGHT = 0x00000042;
1148
1149    /**
1150     * Use with {@link #focusSearch(int)}. Move focus down.
1151     */
1152    public static final int FOCUS_DOWN = 0x00000082;
1153
1154    /**
1155     * Bits of {@link #getMeasuredWidthAndState()} and
1156     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1157     */
1158    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1159
1160    /**
1161     * Bits of {@link #getMeasuredWidthAndState()} and
1162     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1163     */
1164    public static final int MEASURED_STATE_MASK = 0xff000000;
1165
1166    /**
1167     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1168     * for functions that combine both width and height into a single int,
1169     * such as {@link #getMeasuredState()} and the childState argument of
1170     * {@link #resolveSizeAndState(int, int, int)}.
1171     */
1172    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1173
1174    /**
1175     * Bit of {@link #getMeasuredWidthAndState()} and
1176     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1177     * is smaller that the space the view would like to have.
1178     */
1179    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1180
1181    /**
1182     * Base View state sets
1183     */
1184    // Singles
1185    /**
1186     * Indicates the view has no states set. States are used with
1187     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1188     * view depending on its state.
1189     *
1190     * @see android.graphics.drawable.Drawable
1191     * @see #getDrawableState()
1192     */
1193    protected static final int[] EMPTY_STATE_SET;
1194    /**
1195     * Indicates the view is enabled. States are used with
1196     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1197     * view depending on its state.
1198     *
1199     * @see android.graphics.drawable.Drawable
1200     * @see #getDrawableState()
1201     */
1202    protected static final int[] ENABLED_STATE_SET;
1203    /**
1204     * Indicates the view is focused. States are used with
1205     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1206     * view depending on its state.
1207     *
1208     * @see android.graphics.drawable.Drawable
1209     * @see #getDrawableState()
1210     */
1211    protected static final int[] FOCUSED_STATE_SET;
1212    /**
1213     * Indicates the view is selected. States are used with
1214     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1215     * view depending on its state.
1216     *
1217     * @see android.graphics.drawable.Drawable
1218     * @see #getDrawableState()
1219     */
1220    protected static final int[] SELECTED_STATE_SET;
1221    /**
1222     * Indicates the view is pressed. States are used with
1223     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1224     * view depending on its state.
1225     *
1226     * @see android.graphics.drawable.Drawable
1227     * @see #getDrawableState()
1228     */
1229    protected static final int[] PRESSED_STATE_SET;
1230    /**
1231     * Indicates the view's window has focus. States are used with
1232     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1233     * view depending on its state.
1234     *
1235     * @see android.graphics.drawable.Drawable
1236     * @see #getDrawableState()
1237     */
1238    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1239    // Doubles
1240    /**
1241     * Indicates the view is enabled and has the focus.
1242     *
1243     * @see #ENABLED_STATE_SET
1244     * @see #FOCUSED_STATE_SET
1245     */
1246    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1247    /**
1248     * Indicates the view is enabled and selected.
1249     *
1250     * @see #ENABLED_STATE_SET
1251     * @see #SELECTED_STATE_SET
1252     */
1253    protected static final int[] ENABLED_SELECTED_STATE_SET;
1254    /**
1255     * Indicates the view is enabled and that its window has focus.
1256     *
1257     * @see #ENABLED_STATE_SET
1258     * @see #WINDOW_FOCUSED_STATE_SET
1259     */
1260    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1261    /**
1262     * Indicates the view is focused and selected.
1263     *
1264     * @see #FOCUSED_STATE_SET
1265     * @see #SELECTED_STATE_SET
1266     */
1267    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1268    /**
1269     * Indicates the view has the focus and that its window has the focus.
1270     *
1271     * @see #FOCUSED_STATE_SET
1272     * @see #WINDOW_FOCUSED_STATE_SET
1273     */
1274    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1275    /**
1276     * Indicates the view is selected and that its window has the focus.
1277     *
1278     * @see #SELECTED_STATE_SET
1279     * @see #WINDOW_FOCUSED_STATE_SET
1280     */
1281    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1282    // Triples
1283    /**
1284     * Indicates the view is enabled, focused and selected.
1285     *
1286     * @see #ENABLED_STATE_SET
1287     * @see #FOCUSED_STATE_SET
1288     * @see #SELECTED_STATE_SET
1289     */
1290    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1291    /**
1292     * Indicates the view is enabled, focused and its window has the focus.
1293     *
1294     * @see #ENABLED_STATE_SET
1295     * @see #FOCUSED_STATE_SET
1296     * @see #WINDOW_FOCUSED_STATE_SET
1297     */
1298    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1299    /**
1300     * Indicates the view is enabled, selected and its window has the focus.
1301     *
1302     * @see #ENABLED_STATE_SET
1303     * @see #SELECTED_STATE_SET
1304     * @see #WINDOW_FOCUSED_STATE_SET
1305     */
1306    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1307    /**
1308     * Indicates the view is focused, selected and its window has the focus.
1309     *
1310     * @see #FOCUSED_STATE_SET
1311     * @see #SELECTED_STATE_SET
1312     * @see #WINDOW_FOCUSED_STATE_SET
1313     */
1314    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1315    /**
1316     * Indicates the view is enabled, focused, selected and its window
1317     * has the focus.
1318     *
1319     * @see #ENABLED_STATE_SET
1320     * @see #FOCUSED_STATE_SET
1321     * @see #SELECTED_STATE_SET
1322     * @see #WINDOW_FOCUSED_STATE_SET
1323     */
1324    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1325    /**
1326     * Indicates the view is pressed and its window has the focus.
1327     *
1328     * @see #PRESSED_STATE_SET
1329     * @see #WINDOW_FOCUSED_STATE_SET
1330     */
1331    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1332    /**
1333     * Indicates the view is pressed and selected.
1334     *
1335     * @see #PRESSED_STATE_SET
1336     * @see #SELECTED_STATE_SET
1337     */
1338    protected static final int[] PRESSED_SELECTED_STATE_SET;
1339    /**
1340     * Indicates the view is pressed, selected and its window has the focus.
1341     *
1342     * @see #PRESSED_STATE_SET
1343     * @see #SELECTED_STATE_SET
1344     * @see #WINDOW_FOCUSED_STATE_SET
1345     */
1346    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1347    /**
1348     * Indicates the view is pressed and focused.
1349     *
1350     * @see #PRESSED_STATE_SET
1351     * @see #FOCUSED_STATE_SET
1352     */
1353    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1354    /**
1355     * Indicates the view is pressed, focused and its window has the focus.
1356     *
1357     * @see #PRESSED_STATE_SET
1358     * @see #FOCUSED_STATE_SET
1359     * @see #WINDOW_FOCUSED_STATE_SET
1360     */
1361    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1362    /**
1363     * Indicates the view is pressed, focused and selected.
1364     *
1365     * @see #PRESSED_STATE_SET
1366     * @see #SELECTED_STATE_SET
1367     * @see #FOCUSED_STATE_SET
1368     */
1369    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1370    /**
1371     * Indicates the view is pressed, focused, selected and its window has the focus.
1372     *
1373     * @see #PRESSED_STATE_SET
1374     * @see #FOCUSED_STATE_SET
1375     * @see #SELECTED_STATE_SET
1376     * @see #WINDOW_FOCUSED_STATE_SET
1377     */
1378    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1379    /**
1380     * Indicates the view is pressed and enabled.
1381     *
1382     * @see #PRESSED_STATE_SET
1383     * @see #ENABLED_STATE_SET
1384     */
1385    protected static final int[] PRESSED_ENABLED_STATE_SET;
1386    /**
1387     * Indicates the view is pressed, enabled and its window has the focus.
1388     *
1389     * @see #PRESSED_STATE_SET
1390     * @see #ENABLED_STATE_SET
1391     * @see #WINDOW_FOCUSED_STATE_SET
1392     */
1393    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1394    /**
1395     * Indicates the view is pressed, enabled and selected.
1396     *
1397     * @see #PRESSED_STATE_SET
1398     * @see #ENABLED_STATE_SET
1399     * @see #SELECTED_STATE_SET
1400     */
1401    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1402    /**
1403     * Indicates the view is pressed, enabled, selected and its window has the
1404     * focus.
1405     *
1406     * @see #PRESSED_STATE_SET
1407     * @see #ENABLED_STATE_SET
1408     * @see #SELECTED_STATE_SET
1409     * @see #WINDOW_FOCUSED_STATE_SET
1410     */
1411    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1412    /**
1413     * Indicates the view is pressed, enabled and focused.
1414     *
1415     * @see #PRESSED_STATE_SET
1416     * @see #ENABLED_STATE_SET
1417     * @see #FOCUSED_STATE_SET
1418     */
1419    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1420    /**
1421     * Indicates the view is pressed, enabled, focused and its window has the
1422     * focus.
1423     *
1424     * @see #PRESSED_STATE_SET
1425     * @see #ENABLED_STATE_SET
1426     * @see #FOCUSED_STATE_SET
1427     * @see #WINDOW_FOCUSED_STATE_SET
1428     */
1429    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1430    /**
1431     * Indicates the view is pressed, enabled, focused and selected.
1432     *
1433     * @see #PRESSED_STATE_SET
1434     * @see #ENABLED_STATE_SET
1435     * @see #SELECTED_STATE_SET
1436     * @see #FOCUSED_STATE_SET
1437     */
1438    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1439    /**
1440     * Indicates the view is pressed, enabled, focused, selected and its window
1441     * has the focus.
1442     *
1443     * @see #PRESSED_STATE_SET
1444     * @see #ENABLED_STATE_SET
1445     * @see #SELECTED_STATE_SET
1446     * @see #FOCUSED_STATE_SET
1447     * @see #WINDOW_FOCUSED_STATE_SET
1448     */
1449    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1450
1451    static {
1452        EMPTY_STATE_SET = StateSet.get(0);
1453
1454        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1455
1456        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1457        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1458                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1459
1460        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1461        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1462                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1463        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1464                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1465        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1466                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1467                        | StateSet.VIEW_STATE_FOCUSED);
1468
1469        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1470        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1471                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1472        ENABLED_SELECTED_STATE_SET = StateSet.get(
1473                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1474        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1475                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1476                        | StateSet.VIEW_STATE_ENABLED);
1477        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1478                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1479        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1480                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1481                        | StateSet.VIEW_STATE_ENABLED);
1482        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1483                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1484                        | StateSet.VIEW_STATE_ENABLED);
1485        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1486                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1487                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1488
1489        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1490        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1491                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1492        PRESSED_SELECTED_STATE_SET = StateSet.get(
1493                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1494        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1495                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1496                        | StateSet.VIEW_STATE_PRESSED);
1497        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1498                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1499        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1500                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1501                        | StateSet.VIEW_STATE_PRESSED);
1502        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1503                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1504                        | StateSet.VIEW_STATE_PRESSED);
1505        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1506                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1507                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1508        PRESSED_ENABLED_STATE_SET = StateSet.get(
1509                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1510        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1511                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1512                        | StateSet.VIEW_STATE_PRESSED);
1513        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1514                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1515                        | StateSet.VIEW_STATE_PRESSED);
1516        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1517                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1518                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1519        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1520                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1521                        | StateSet.VIEW_STATE_PRESSED);
1522        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1523                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1524                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1525        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1526                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1527                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1528        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1529                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1530                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1531                        | StateSet.VIEW_STATE_PRESSED);
1532    }
1533
1534    /**
1535     * Accessibility event types that are dispatched for text population.
1536     */
1537    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1538            AccessibilityEvent.TYPE_VIEW_CLICKED
1539            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1540            | AccessibilityEvent.TYPE_VIEW_SELECTED
1541            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1542            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1543            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1544            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1545            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1546            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1547            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1548            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1549
1550    /**
1551     * Temporary Rect currently for use in setBackground().  This will probably
1552     * be extended in the future to hold our own class with more than just
1553     * a Rect. :)
1554     */
1555    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1556
1557    /**
1558     * Map used to store views' tags.
1559     */
1560    private SparseArray<Object> mKeyedTags;
1561
1562    /**
1563     * The next available accessibility id.
1564     */
1565    private static int sNextAccessibilityViewId;
1566
1567    /**
1568     * The animation currently associated with this view.
1569     * @hide
1570     */
1571    protected Animation mCurrentAnimation = null;
1572
1573    /**
1574     * Width as measured during measure pass.
1575     * {@hide}
1576     */
1577    @ViewDebug.ExportedProperty(category = "measurement")
1578    int mMeasuredWidth;
1579
1580    /**
1581     * Height as measured during measure pass.
1582     * {@hide}
1583     */
1584    @ViewDebug.ExportedProperty(category = "measurement")
1585    int mMeasuredHeight;
1586
1587    /**
1588     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1589     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1590     * its display list. This flag, used only when hw accelerated, allows us to clear the
1591     * flag while retaining this information until it's needed (at getDisplayList() time and
1592     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1593     *
1594     * {@hide}
1595     */
1596    boolean mRecreateDisplayList = false;
1597
1598    /**
1599     * The view's identifier.
1600     * {@hide}
1601     *
1602     * @see #setId(int)
1603     * @see #getId()
1604     */
1605    @IdRes
1606    @ViewDebug.ExportedProperty(resolveId = true)
1607    int mID = NO_ID;
1608
1609    /**
1610     * The stable ID of this view for accessibility purposes.
1611     */
1612    int mAccessibilityViewId = NO_ID;
1613
1614    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1615
1616    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1617
1618    /**
1619     * The view's tag.
1620     * {@hide}
1621     *
1622     * @see #setTag(Object)
1623     * @see #getTag()
1624     */
1625    protected Object mTag = null;
1626
1627    // for mPrivateFlags:
1628    /** {@hide} */
1629    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1630    /** {@hide} */
1631    static final int PFLAG_FOCUSED                     = 0x00000002;
1632    /** {@hide} */
1633    static final int PFLAG_SELECTED                    = 0x00000004;
1634    /** {@hide} */
1635    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1636    /** {@hide} */
1637    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1638    /** {@hide} */
1639    static final int PFLAG_DRAWN                       = 0x00000020;
1640    /**
1641     * When this flag is set, this view is running an animation on behalf of its
1642     * children and should therefore not cancel invalidate requests, even if they
1643     * lie outside of this view's bounds.
1644     *
1645     * {@hide}
1646     */
1647    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1648    /** {@hide} */
1649    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1650    /** {@hide} */
1651    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1652    /** {@hide} */
1653    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1654    /** {@hide} */
1655    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1656    /** {@hide} */
1657    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1658    /** {@hide} */
1659    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1660    /** {@hide} */
1661    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1662
1663    private static final int PFLAG_PRESSED             = 0x00004000;
1664
1665    /** {@hide} */
1666    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1667    /**
1668     * Flag used to indicate that this view should be drawn once more (and only once
1669     * more) after its animation has completed.
1670     * {@hide}
1671     */
1672    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1673
1674    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1675
1676    /**
1677     * Indicates that the View returned true when onSetAlpha() was called and that
1678     * the alpha must be restored.
1679     * {@hide}
1680     */
1681    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1682
1683    /**
1684     * Set by {@link #setScrollContainer(boolean)}.
1685     */
1686    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1687
1688    /**
1689     * Set by {@link #setScrollContainer(boolean)}.
1690     */
1691    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1692
1693    /**
1694     * View flag indicating whether this view was invalidated (fully or partially.)
1695     *
1696     * @hide
1697     */
1698    static final int PFLAG_DIRTY                       = 0x00200000;
1699
1700    /**
1701     * View flag indicating whether this view was invalidated by an opaque
1702     * invalidate request.
1703     *
1704     * @hide
1705     */
1706    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1707
1708    /**
1709     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1710     *
1711     * @hide
1712     */
1713    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1714
1715    /**
1716     * Indicates whether the background is opaque.
1717     *
1718     * @hide
1719     */
1720    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1721
1722    /**
1723     * Indicates whether the scrollbars are opaque.
1724     *
1725     * @hide
1726     */
1727    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1728
1729    /**
1730     * Indicates whether the view is opaque.
1731     *
1732     * @hide
1733     */
1734    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1735
1736    /**
1737     * Indicates a prepressed state;
1738     * the short time between ACTION_DOWN and recognizing
1739     * a 'real' press. Prepressed is used to recognize quick taps
1740     * even when they are shorter than ViewConfiguration.getTapTimeout().
1741     *
1742     * @hide
1743     */
1744    private static final int PFLAG_PREPRESSED          = 0x02000000;
1745
1746    /**
1747     * Indicates whether the view is temporarily detached.
1748     *
1749     * @hide
1750     */
1751    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1752
1753    /**
1754     * Indicates that we should awaken scroll bars once attached
1755     *
1756     * @hide
1757     */
1758    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1759
1760    /**
1761     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1762     * @hide
1763     */
1764    private static final int PFLAG_HOVERED             = 0x10000000;
1765
1766    /**
1767     * no longer needed, should be reused
1768     */
1769    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1770
1771    /** {@hide} */
1772    static final int PFLAG_ACTIVATED                   = 0x40000000;
1773
1774    /**
1775     * Indicates that this view was specifically invalidated, not just dirtied because some
1776     * child view was invalidated. The flag is used to determine when we need to recreate
1777     * a view's display list (as opposed to just returning a reference to its existing
1778     * display list).
1779     *
1780     * @hide
1781     */
1782    static final int PFLAG_INVALIDATED                 = 0x80000000;
1783
1784    /**
1785     * Masks for mPrivateFlags2, as generated by dumpFlags():
1786     *
1787     * |-------|-------|-------|-------|
1788     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1789     *                                1  PFLAG2_DRAG_HOVERED
1790     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1791     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1792     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1793     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1794     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1795     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1796     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1797     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1798     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1799     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1800     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1801     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1802     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1803     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1804     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1805     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1806     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1807     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1808     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1809     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1810     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1811     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1812     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1813     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1814     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1815     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1816     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1817     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1818     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1819     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1820     *    1                              PFLAG2_PADDING_RESOLVED
1821     *   1                               PFLAG2_DRAWABLE_RESOLVED
1822     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1823     * |-------|-------|-------|-------|
1824     */
1825
1826    /**
1827     * Indicates that this view has reported that it can accept the current drag's content.
1828     * Cleared when the drag operation concludes.
1829     * @hide
1830     */
1831    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1832
1833    /**
1834     * Indicates that this view is currently directly under the drag location in a
1835     * drag-and-drop operation involving content that it can accept.  Cleared when
1836     * the drag exits the view, or when the drag operation concludes.
1837     * @hide
1838     */
1839    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1840
1841    /** @hide */
1842    @IntDef({
1843        LAYOUT_DIRECTION_LTR,
1844        LAYOUT_DIRECTION_RTL,
1845        LAYOUT_DIRECTION_INHERIT,
1846        LAYOUT_DIRECTION_LOCALE
1847    })
1848    @Retention(RetentionPolicy.SOURCE)
1849    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1850    public @interface LayoutDir {}
1851
1852    /** @hide */
1853    @IntDef({
1854        LAYOUT_DIRECTION_LTR,
1855        LAYOUT_DIRECTION_RTL
1856    })
1857    @Retention(RetentionPolicy.SOURCE)
1858    public @interface ResolvedLayoutDir {}
1859
1860    /**
1861     * Horizontal layout direction of this view is from Left to Right.
1862     * Use with {@link #setLayoutDirection}.
1863     */
1864    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1865
1866    /**
1867     * Horizontal layout direction of this view is from Right to Left.
1868     * Use with {@link #setLayoutDirection}.
1869     */
1870    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1871
1872    /**
1873     * Horizontal layout direction of this view is inherited from its parent.
1874     * Use with {@link #setLayoutDirection}.
1875     */
1876    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1877
1878    /**
1879     * Horizontal layout direction of this view is from deduced from the default language
1880     * script for the locale. Use with {@link #setLayoutDirection}.
1881     */
1882    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1883
1884    /**
1885     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1886     * @hide
1887     */
1888    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1889
1890    /**
1891     * Mask for use with private flags indicating bits used for horizontal layout direction.
1892     * @hide
1893     */
1894    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1895
1896    /**
1897     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1898     * right-to-left direction.
1899     * @hide
1900     */
1901    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1902
1903    /**
1904     * Indicates whether the view horizontal layout direction has been resolved.
1905     * @hide
1906     */
1907    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1908
1909    /**
1910     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1911     * @hide
1912     */
1913    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1914            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1915
1916    /*
1917     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1918     * flag value.
1919     * @hide
1920     */
1921    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1922            LAYOUT_DIRECTION_LTR,
1923            LAYOUT_DIRECTION_RTL,
1924            LAYOUT_DIRECTION_INHERIT,
1925            LAYOUT_DIRECTION_LOCALE
1926    };
1927
1928    /**
1929     * Default horizontal layout direction.
1930     */
1931    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1932
1933    /**
1934     * Default horizontal layout direction.
1935     * @hide
1936     */
1937    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1938
1939    /**
1940     * Text direction is inherited through {@link ViewGroup}
1941     */
1942    public static final int TEXT_DIRECTION_INHERIT = 0;
1943
1944    /**
1945     * Text direction is using "first strong algorithm". The first strong directional character
1946     * determines the paragraph direction. If there is no strong directional character, the
1947     * paragraph direction is the view's resolved layout direction.
1948     */
1949    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1950
1951    /**
1952     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1953     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1954     * If there are neither, the paragraph direction is the view's resolved layout direction.
1955     */
1956    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1957
1958    /**
1959     * Text direction is forced to LTR.
1960     */
1961    public static final int TEXT_DIRECTION_LTR = 3;
1962
1963    /**
1964     * Text direction is forced to RTL.
1965     */
1966    public static final int TEXT_DIRECTION_RTL = 4;
1967
1968    /**
1969     * Text direction is coming from the system Locale.
1970     */
1971    public static final int TEXT_DIRECTION_LOCALE = 5;
1972
1973    /**
1974     * Text direction is using "first strong algorithm". The first strong directional character
1975     * determines the paragraph direction. If there is no strong directional character, the
1976     * paragraph direction is LTR.
1977     */
1978    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
1979
1980    /**
1981     * Text direction is using "first strong algorithm". The first strong directional character
1982     * determines the paragraph direction. If there is no strong directional character, the
1983     * paragraph direction is RTL.
1984     */
1985    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
1986
1987    /**
1988     * Default text direction is inherited
1989     */
1990    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1991
1992    /**
1993     * Default resolved text direction
1994     * @hide
1995     */
1996    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
1997
1998    /**
1999     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2000     * @hide
2001     */
2002    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2003
2004    /**
2005     * Mask for use with private flags indicating bits used for text direction.
2006     * @hide
2007     */
2008    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2009            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2010
2011    /**
2012     * Array of text direction flags for mapping attribute "textDirection" to correct
2013     * flag value.
2014     * @hide
2015     */
2016    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2017            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2018            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2019            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2020            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2021            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2022            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2023            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2024            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2025    };
2026
2027    /**
2028     * Indicates whether the view text direction has been resolved.
2029     * @hide
2030     */
2031    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2032            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2033
2034    /**
2035     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2036     * @hide
2037     */
2038    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2039
2040    /**
2041     * Mask for use with private flags indicating bits used for resolved text direction.
2042     * @hide
2043     */
2044    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2045            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2046
2047    /**
2048     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2049     * @hide
2050     */
2051    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2052            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2053
2054    /** @hide */
2055    @IntDef({
2056        TEXT_ALIGNMENT_INHERIT,
2057        TEXT_ALIGNMENT_GRAVITY,
2058        TEXT_ALIGNMENT_CENTER,
2059        TEXT_ALIGNMENT_TEXT_START,
2060        TEXT_ALIGNMENT_TEXT_END,
2061        TEXT_ALIGNMENT_VIEW_START,
2062        TEXT_ALIGNMENT_VIEW_END
2063    })
2064    @Retention(RetentionPolicy.SOURCE)
2065    public @interface TextAlignment {}
2066
2067    /**
2068     * Default text alignment. The text alignment of this View is inherited from its parent.
2069     * Use with {@link #setTextAlignment(int)}
2070     */
2071    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2072
2073    /**
2074     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2075     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2076     *
2077     * Use with {@link #setTextAlignment(int)}
2078     */
2079    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2080
2081    /**
2082     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2083     *
2084     * Use with {@link #setTextAlignment(int)}
2085     */
2086    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2087
2088    /**
2089     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2090     *
2091     * Use with {@link #setTextAlignment(int)}
2092     */
2093    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2094
2095    /**
2096     * Center the paragraph, e.g. ALIGN_CENTER.
2097     *
2098     * Use with {@link #setTextAlignment(int)}
2099     */
2100    public static final int TEXT_ALIGNMENT_CENTER = 4;
2101
2102    /**
2103     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2104     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2105     *
2106     * Use with {@link #setTextAlignment(int)}
2107     */
2108    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2109
2110    /**
2111     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2112     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2113     *
2114     * Use with {@link #setTextAlignment(int)}
2115     */
2116    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2117
2118    /**
2119     * Default text alignment is inherited
2120     */
2121    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2122
2123    /**
2124     * Default resolved text alignment
2125     * @hide
2126     */
2127    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2128
2129    /**
2130      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2131      * @hide
2132      */
2133    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2134
2135    /**
2136      * Mask for use with private flags indicating bits used for text alignment.
2137      * @hide
2138      */
2139    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2140
2141    /**
2142     * Array of text direction flags for mapping attribute "textAlignment" to correct
2143     * flag value.
2144     * @hide
2145     */
2146    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2147            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2148            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2149            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2150            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2151            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2152            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2153            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2154    };
2155
2156    /**
2157     * Indicates whether the view text alignment has been resolved.
2158     * @hide
2159     */
2160    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2161
2162    /**
2163     * Bit shift to get the resolved text alignment.
2164     * @hide
2165     */
2166    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2167
2168    /**
2169     * Mask for use with private flags indicating bits used for text alignment.
2170     * @hide
2171     */
2172    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2173            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2174
2175    /**
2176     * Indicates whether if the view text alignment has been resolved to gravity
2177     */
2178    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2179            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2180
2181    // Accessiblity constants for mPrivateFlags2
2182
2183    /**
2184     * Shift for the bits in {@link #mPrivateFlags2} related to the
2185     * "importantForAccessibility" attribute.
2186     */
2187    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2188
2189    /**
2190     * Automatically determine whether a view is important for accessibility.
2191     */
2192    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2193
2194    /**
2195     * The view is important for accessibility.
2196     */
2197    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2198
2199    /**
2200     * The view is not important for accessibility.
2201     */
2202    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2203
2204    /**
2205     * The view is not important for accessibility, nor are any of its
2206     * descendant views.
2207     */
2208    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2209
2210    /**
2211     * The default whether the view is important for accessibility.
2212     */
2213    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2214
2215    /**
2216     * Mask for obtainig the bits which specify how to determine
2217     * whether a view is important for accessibility.
2218     */
2219    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2220        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2221        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2222        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2223
2224    /**
2225     * Shift for the bits in {@link #mPrivateFlags2} related to the
2226     * "accessibilityLiveRegion" attribute.
2227     */
2228    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2229
2230    /**
2231     * Live region mode specifying that accessibility services should not
2232     * automatically announce changes to this view. This is the default live
2233     * region mode for most views.
2234     * <p>
2235     * Use with {@link #setAccessibilityLiveRegion(int)}.
2236     */
2237    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2238
2239    /**
2240     * Live region mode specifying that accessibility services should announce
2241     * changes to this view.
2242     * <p>
2243     * Use with {@link #setAccessibilityLiveRegion(int)}.
2244     */
2245    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2246
2247    /**
2248     * Live region mode specifying that accessibility services should interrupt
2249     * ongoing speech to immediately announce changes to this view.
2250     * <p>
2251     * Use with {@link #setAccessibilityLiveRegion(int)}.
2252     */
2253    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2254
2255    /**
2256     * The default whether the view is important for accessibility.
2257     */
2258    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2259
2260    /**
2261     * Mask for obtaining the bits which specify a view's accessibility live
2262     * region mode.
2263     */
2264    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2265            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2266            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2267
2268    /**
2269     * Flag indicating whether a view has accessibility focus.
2270     */
2271    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2272
2273    /**
2274     * Flag whether the accessibility state of the subtree rooted at this view changed.
2275     */
2276    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2277
2278    /**
2279     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2280     * is used to check whether later changes to the view's transform should invalidate the
2281     * view to force the quickReject test to run again.
2282     */
2283    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2284
2285    /**
2286     * Flag indicating that start/end padding has been resolved into left/right padding
2287     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2288     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2289     * during measurement. In some special cases this is required such as when an adapter-based
2290     * view measures prospective children without attaching them to a window.
2291     */
2292    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2293
2294    /**
2295     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2296     */
2297    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2298
2299    /**
2300     * Indicates that the view is tracking some sort of transient state
2301     * that the app should not need to be aware of, but that the framework
2302     * should take special care to preserve.
2303     */
2304    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2305
2306    /**
2307     * Group of bits indicating that RTL properties resolution is done.
2308     */
2309    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2310            PFLAG2_TEXT_DIRECTION_RESOLVED |
2311            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2312            PFLAG2_PADDING_RESOLVED |
2313            PFLAG2_DRAWABLE_RESOLVED;
2314
2315    // There are a couple of flags left in mPrivateFlags2
2316
2317    /* End of masks for mPrivateFlags2 */
2318
2319    /**
2320     * Masks for mPrivateFlags3, as generated by dumpFlags():
2321     *
2322     * |-------|-------|-------|-------|
2323     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2324     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2325     *                               1   PFLAG3_IS_LAID_OUT
2326     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2327     *                             1     PFLAG3_CALLED_SUPER
2328     *                            1      PFLAG3_APPLYING_INSETS
2329     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2330     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2331     *                         1         PFLAG3_ASSIST_BLOCKED
2332     * |-------|-------|-------|-------|
2333     */
2334
2335    /**
2336     * Flag indicating that view has a transform animation set on it. This is used to track whether
2337     * an animation is cleared between successive frames, in order to tell the associated
2338     * DisplayList to clear its animation matrix.
2339     */
2340    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2341
2342    /**
2343     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2344     * animation is cleared between successive frames, in order to tell the associated
2345     * DisplayList to restore its alpha value.
2346     */
2347    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2348
2349    /**
2350     * Flag indicating that the view has been through at least one layout since it
2351     * was last attached to a window.
2352     */
2353    static final int PFLAG3_IS_LAID_OUT = 0x4;
2354
2355    /**
2356     * Flag indicating that a call to measure() was skipped and should be done
2357     * instead when layout() is invoked.
2358     */
2359    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2360
2361    /**
2362     * Flag indicating that an overridden method correctly called down to
2363     * the superclass implementation as required by the API spec.
2364     */
2365    static final int PFLAG3_CALLED_SUPER = 0x10;
2366
2367    /**
2368     * Flag indicating that we're in the process of applying window insets.
2369     */
2370    static final int PFLAG3_APPLYING_INSETS = 0x20;
2371
2372    /**
2373     * Flag indicating that we're in the process of fitting system windows using the old method.
2374     */
2375    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2376
2377    /**
2378     * Flag indicating that nested scrolling is enabled for this view.
2379     * The view will optionally cooperate with views up its parent chain to allow for
2380     * integrated nested scrolling along the same axis.
2381     */
2382    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2383
2384    /* End of masks for mPrivateFlags3 */
2385
2386    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2387
2388    /**
2389     * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse
2390     * into this view.<p>
2391     */
2392    static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2393
2394    /**
2395     * Always allow a user to over-scroll this view, provided it is a
2396     * view that can scroll.
2397     *
2398     * @see #getOverScrollMode()
2399     * @see #setOverScrollMode(int)
2400     */
2401    public static final int OVER_SCROLL_ALWAYS = 0;
2402
2403    /**
2404     * Allow a user to over-scroll this view only if the content is large
2405     * enough to meaningfully scroll, provided it is a view that can scroll.
2406     *
2407     * @see #getOverScrollMode()
2408     * @see #setOverScrollMode(int)
2409     */
2410    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2411
2412    /**
2413     * Never allow a user to over-scroll this view.
2414     *
2415     * @see #getOverScrollMode()
2416     * @see #setOverScrollMode(int)
2417     */
2418    public static final int OVER_SCROLL_NEVER = 2;
2419
2420    /**
2421     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2422     * requested the system UI (status bar) to be visible (the default).
2423     *
2424     * @see #setSystemUiVisibility(int)
2425     */
2426    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2427
2428    /**
2429     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2430     * system UI to enter an unobtrusive "low profile" mode.
2431     *
2432     * <p>This is for use in games, book readers, video players, or any other
2433     * "immersive" application where the usual system chrome is deemed too distracting.
2434     *
2435     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2436     *
2437     * @see #setSystemUiVisibility(int)
2438     */
2439    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2440
2441    /**
2442     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2443     * system navigation be temporarily hidden.
2444     *
2445     * <p>This is an even less obtrusive state than that called for by
2446     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2447     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2448     * those to disappear. This is useful (in conjunction with the
2449     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2450     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2451     * window flags) for displaying content using every last pixel on the display.
2452     *
2453     * <p>There is a limitation: because navigation controls are so important, the least user
2454     * interaction will cause them to reappear immediately.  When this happens, both
2455     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2456     * so that both elements reappear at the same time.
2457     *
2458     * @see #setSystemUiVisibility(int)
2459     */
2460    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2461
2462    /**
2463     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2464     * into the normal fullscreen mode so that its content can take over the screen
2465     * while still allowing the user to interact with the application.
2466     *
2467     * <p>This has the same visual effect as
2468     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2469     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2470     * meaning that non-critical screen decorations (such as the status bar) will be
2471     * hidden while the user is in the View's window, focusing the experience on
2472     * that content.  Unlike the window flag, if you are using ActionBar in
2473     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2474     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2475     * hide the action bar.
2476     *
2477     * <p>This approach to going fullscreen is best used over the window flag when
2478     * it is a transient state -- that is, the application does this at certain
2479     * points in its user interaction where it wants to allow the user to focus
2480     * on content, but not as a continuous state.  For situations where the application
2481     * would like to simply stay full screen the entire time (such as a game that
2482     * wants to take over the screen), the
2483     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2484     * is usually a better approach.  The state set here will be removed by the system
2485     * in various situations (such as the user moving to another application) like
2486     * the other system UI states.
2487     *
2488     * <p>When using this flag, the application should provide some easy facility
2489     * for the user to go out of it.  A common example would be in an e-book
2490     * reader, where tapping on the screen brings back whatever screen and UI
2491     * decorations that had been hidden while the user was immersed in reading
2492     * the book.
2493     *
2494     * @see #setSystemUiVisibility(int)
2495     */
2496    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2497
2498    /**
2499     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2500     * flags, we would like a stable view of the content insets given to
2501     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2502     * will always represent the worst case that the application can expect
2503     * as a continuous state.  In the stock Android UI this is the space for
2504     * the system bar, nav bar, and status bar, but not more transient elements
2505     * such as an input method.
2506     *
2507     * The stable layout your UI sees is based on the system UI modes you can
2508     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2509     * then you will get a stable layout for changes of the
2510     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2511     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2512     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2513     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2514     * with a stable layout.  (Note that you should avoid using
2515     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2516     *
2517     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2518     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2519     * then a hidden status bar will be considered a "stable" state for purposes
2520     * here.  This allows your UI to continually hide the status bar, while still
2521     * using the system UI flags to hide the action bar while still retaining
2522     * a stable layout.  Note that changing the window fullscreen flag will never
2523     * provide a stable layout for a clean transition.
2524     *
2525     * <p>If you are using ActionBar in
2526     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2527     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2528     * insets it adds to those given to the application.
2529     */
2530    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2531
2532    /**
2533     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2534     * to be laid out as if it has requested
2535     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2536     * allows it to avoid artifacts when switching in and out of that mode, at
2537     * the expense that some of its user interface may be covered by screen
2538     * decorations when they are shown.  You can perform layout of your inner
2539     * UI elements to account for the navigation system UI through the
2540     * {@link #fitSystemWindows(Rect)} method.
2541     */
2542    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2543
2544    /**
2545     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2546     * to be laid out as if it has requested
2547     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2548     * allows it to avoid artifacts when switching in and out of that mode, at
2549     * the expense that some of its user interface may be covered by screen
2550     * decorations when they are shown.  You can perform layout of your inner
2551     * UI elements to account for non-fullscreen system UI through the
2552     * {@link #fitSystemWindows(Rect)} method.
2553     */
2554    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2555
2556    /**
2557     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2558     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2559     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2560     * user interaction.
2561     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2562     * has an effect when used in combination with that flag.</p>
2563     */
2564    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2565
2566    /**
2567     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2568     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2569     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2570     * experience while also hiding the system bars.  If this flag is not set,
2571     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2572     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2573     * if the user swipes from the top of the screen.
2574     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2575     * system gestures, such as swiping from the top of the screen.  These transient system bars
2576     * will overlay app’s content, may have some degree of transparency, and will automatically
2577     * hide after a short timeout.
2578     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2579     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2580     * with one or both of those flags.</p>
2581     */
2582    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2583
2584    /**
2585     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2586     * is compatible with light status bar backgrounds.
2587     *
2588     * <p>For this to take effect, the window must request
2589     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2590     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2591     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2592     *         FLAG_TRANSLUCENT_STATUS}.
2593     *
2594     * @see android.R.attr#windowHasLightStatusBar
2595     */
2596    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2597
2598    /**
2599     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2600     */
2601    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2602
2603    /**
2604     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2605     */
2606    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2607
2608    /**
2609     * @hide
2610     *
2611     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2612     * out of the public fields to keep the undefined bits out of the developer's way.
2613     *
2614     * Flag to make the status bar not expandable.  Unless you also
2615     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2616     */
2617    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2618
2619    /**
2620     * @hide
2621     *
2622     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2623     * out of the public fields to keep the undefined bits out of the developer's way.
2624     *
2625     * Flag to hide notification icons and scrolling ticker text.
2626     */
2627    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2628
2629    /**
2630     * @hide
2631     *
2632     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2633     * out of the public fields to keep the undefined bits out of the developer's way.
2634     *
2635     * Flag to disable incoming notification alerts.  This will not block
2636     * icons, but it will block sound, vibrating and other visual or aural notifications.
2637     */
2638    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2639
2640    /**
2641     * @hide
2642     *
2643     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2644     * out of the public fields to keep the undefined bits out of the developer's way.
2645     *
2646     * Flag to hide only the scrolling ticker.  Note that
2647     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2648     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2649     */
2650    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2651
2652    /**
2653     * @hide
2654     *
2655     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2656     * out of the public fields to keep the undefined bits out of the developer's way.
2657     *
2658     * Flag to hide the center system info area.
2659     */
2660    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2661
2662    /**
2663     * @hide
2664     *
2665     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2666     * out of the public fields to keep the undefined bits out of the developer's way.
2667     *
2668     * Flag to hide only the home button.  Don't use this
2669     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2670     */
2671    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2672
2673    /**
2674     * @hide
2675     *
2676     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2677     * out of the public fields to keep the undefined bits out of the developer's way.
2678     *
2679     * Flag to hide only the back button. Don't use this
2680     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2681     */
2682    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2683
2684    /**
2685     * @hide
2686     *
2687     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2688     * out of the public fields to keep the undefined bits out of the developer's way.
2689     *
2690     * Flag to hide only the clock.  You might use this if your activity has
2691     * its own clock making the status bar's clock redundant.
2692     */
2693    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2694
2695    /**
2696     * @hide
2697     *
2698     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2699     * out of the public fields to keep the undefined bits out of the developer's way.
2700     *
2701     * Flag to hide only the recent apps button. Don't use this
2702     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2703     */
2704    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2705
2706    /**
2707     * @hide
2708     *
2709     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2710     * out of the public fields to keep the undefined bits out of the developer's way.
2711     *
2712     * Flag to disable the global search gesture. Don't use this
2713     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2714     */
2715    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2716
2717    /**
2718     * @hide
2719     *
2720     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2721     * out of the public fields to keep the undefined bits out of the developer's way.
2722     *
2723     * Flag to specify that the status bar is displayed in transient mode.
2724     */
2725    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2726
2727    /**
2728     * @hide
2729     *
2730     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2731     * out of the public fields to keep the undefined bits out of the developer's way.
2732     *
2733     * Flag to specify that the navigation bar is displayed in transient mode.
2734     */
2735    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2736
2737    /**
2738     * @hide
2739     *
2740     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2741     * out of the public fields to keep the undefined bits out of the developer's way.
2742     *
2743     * Flag to specify that the hidden status bar would like to be shown.
2744     */
2745    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2746
2747    /**
2748     * @hide
2749     *
2750     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2751     * out of the public fields to keep the undefined bits out of the developer's way.
2752     *
2753     * Flag to specify that the hidden navigation bar would like to be shown.
2754     */
2755    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2756
2757    /**
2758     * @hide
2759     *
2760     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2761     * out of the public fields to keep the undefined bits out of the developer's way.
2762     *
2763     * Flag to specify that the status bar is displayed in translucent mode.
2764     */
2765    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2766
2767    /**
2768     * @hide
2769     *
2770     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2771     * out of the public fields to keep the undefined bits out of the developer's way.
2772     *
2773     * Flag to specify that the navigation bar is displayed in translucent mode.
2774     */
2775    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2776
2777    /**
2778     * @hide
2779     *
2780     * Whether Recents is visible or not.
2781     */
2782    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2783
2784    /**
2785     * @hide
2786     *
2787     * Makes system ui transparent.
2788     */
2789    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2790
2791    /**
2792     * @hide
2793     */
2794    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2795
2796    /**
2797     * These are the system UI flags that can be cleared by events outside
2798     * of an application.  Currently this is just the ability to tap on the
2799     * screen while hiding the navigation bar to have it return.
2800     * @hide
2801     */
2802    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2803            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2804            | SYSTEM_UI_FLAG_FULLSCREEN;
2805
2806    /**
2807     * Flags that can impact the layout in relation to system UI.
2808     */
2809    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2810            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2811            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2812
2813    /** @hide */
2814    @IntDef(flag = true,
2815            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2816    @Retention(RetentionPolicy.SOURCE)
2817    public @interface FindViewFlags {}
2818
2819    /**
2820     * Find views that render the specified text.
2821     *
2822     * @see #findViewsWithText(ArrayList, CharSequence, int)
2823     */
2824    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2825
2826    /**
2827     * Find find views that contain the specified content description.
2828     *
2829     * @see #findViewsWithText(ArrayList, CharSequence, int)
2830     */
2831    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2832
2833    /**
2834     * Find views that contain {@link AccessibilityNodeProvider}. Such
2835     * a View is a root of virtual view hierarchy and may contain the searched
2836     * text. If this flag is set Views with providers are automatically
2837     * added and it is a responsibility of the client to call the APIs of
2838     * the provider to determine whether the virtual tree rooted at this View
2839     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2840     * representing the virtual views with this text.
2841     *
2842     * @see #findViewsWithText(ArrayList, CharSequence, int)
2843     *
2844     * @hide
2845     */
2846    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2847
2848    /**
2849     * The undefined cursor position.
2850     *
2851     * @hide
2852     */
2853    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2854
2855    /**
2856     * Indicates that the screen has changed state and is now off.
2857     *
2858     * @see #onScreenStateChanged(int)
2859     */
2860    public static final int SCREEN_STATE_OFF = 0x0;
2861
2862    /**
2863     * Indicates that the screen has changed state and is now on.
2864     *
2865     * @see #onScreenStateChanged(int)
2866     */
2867    public static final int SCREEN_STATE_ON = 0x1;
2868
2869    /**
2870     * Indicates no axis of view scrolling.
2871     */
2872    public static final int SCROLL_AXIS_NONE = 0;
2873
2874    /**
2875     * Indicates scrolling along the horizontal axis.
2876     */
2877    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2878
2879    /**
2880     * Indicates scrolling along the vertical axis.
2881     */
2882    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2883
2884    /**
2885     * Controls the over-scroll mode for this view.
2886     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2887     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2888     * and {@link #OVER_SCROLL_NEVER}.
2889     */
2890    private int mOverScrollMode;
2891
2892    /**
2893     * The parent this view is attached to.
2894     * {@hide}
2895     *
2896     * @see #getParent()
2897     */
2898    protected ViewParent mParent;
2899
2900    /**
2901     * {@hide}
2902     */
2903    AttachInfo mAttachInfo;
2904
2905    /**
2906     * {@hide}
2907     */
2908    @ViewDebug.ExportedProperty(flagMapping = {
2909        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2910                name = "FORCE_LAYOUT"),
2911        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2912                name = "LAYOUT_REQUIRED"),
2913        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2914            name = "DRAWING_CACHE_INVALID", outputIf = false),
2915        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2916        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2917        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2918        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2919    }, formatToHexString = true)
2920    int mPrivateFlags;
2921    int mPrivateFlags2;
2922    int mPrivateFlags3;
2923
2924    /**
2925     * This view's request for the visibility of the status bar.
2926     * @hide
2927     */
2928    @ViewDebug.ExportedProperty(flagMapping = {
2929        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2930                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2931                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2932        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2933                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2934                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2935        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2936                                equals = SYSTEM_UI_FLAG_VISIBLE,
2937                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2938    }, formatToHexString = true)
2939    int mSystemUiVisibility;
2940
2941    /**
2942     * Reference count for transient state.
2943     * @see #setHasTransientState(boolean)
2944     */
2945    int mTransientStateCount = 0;
2946
2947    /**
2948     * Count of how many windows this view has been attached to.
2949     */
2950    int mWindowAttachCount;
2951
2952    /**
2953     * The layout parameters associated with this view and used by the parent
2954     * {@link android.view.ViewGroup} to determine how this view should be
2955     * laid out.
2956     * {@hide}
2957     */
2958    protected ViewGroup.LayoutParams mLayoutParams;
2959
2960    /**
2961     * The view flags hold various views states.
2962     * {@hide}
2963     */
2964    @ViewDebug.ExportedProperty(formatToHexString = true)
2965    int mViewFlags;
2966
2967    static class TransformationInfo {
2968        /**
2969         * The transform matrix for the View. This transform is calculated internally
2970         * based on the translation, rotation, and scale properties.
2971         *
2972         * Do *not* use this variable directly; instead call getMatrix(), which will
2973         * load the value from the View's RenderNode.
2974         */
2975        private final Matrix mMatrix = new Matrix();
2976
2977        /**
2978         * The inverse transform matrix for the View. This transform is calculated
2979         * internally based on the translation, rotation, and scale properties.
2980         *
2981         * Do *not* use this variable directly; instead call getInverseMatrix(),
2982         * which will load the value from the View's RenderNode.
2983         */
2984        private Matrix mInverseMatrix;
2985
2986        /**
2987         * The opacity of the View. This is a value from 0 to 1, where 0 means
2988         * completely transparent and 1 means completely opaque.
2989         */
2990        @ViewDebug.ExportedProperty
2991        float mAlpha = 1f;
2992
2993        /**
2994         * The opacity of the view as manipulated by the Fade transition. This is a hidden
2995         * property only used by transitions, which is composited with the other alpha
2996         * values to calculate the final visual alpha value.
2997         */
2998        float mTransitionAlpha = 1f;
2999    }
3000
3001    TransformationInfo mTransformationInfo;
3002
3003    /**
3004     * Current clip bounds. to which all drawing of this view are constrained.
3005     */
3006    Rect mClipBounds = null;
3007
3008    private boolean mLastIsOpaque;
3009
3010    /**
3011     * The distance in pixels from the left edge of this view's parent
3012     * to the left edge of this view.
3013     * {@hide}
3014     */
3015    @ViewDebug.ExportedProperty(category = "layout")
3016    protected int mLeft;
3017    /**
3018     * The distance in pixels from the left edge of this view's parent
3019     * to the right edge of this view.
3020     * {@hide}
3021     */
3022    @ViewDebug.ExportedProperty(category = "layout")
3023    protected int mRight;
3024    /**
3025     * The distance in pixels from the top edge of this view's parent
3026     * to the top edge of this view.
3027     * {@hide}
3028     */
3029    @ViewDebug.ExportedProperty(category = "layout")
3030    protected int mTop;
3031    /**
3032     * The distance in pixels from the top edge of this view's parent
3033     * to the bottom edge of this view.
3034     * {@hide}
3035     */
3036    @ViewDebug.ExportedProperty(category = "layout")
3037    protected int mBottom;
3038
3039    /**
3040     * The offset, in pixels, by which the content of this view is scrolled
3041     * horizontally.
3042     * {@hide}
3043     */
3044    @ViewDebug.ExportedProperty(category = "scrolling")
3045    protected int mScrollX;
3046    /**
3047     * The offset, in pixels, by which the content of this view is scrolled
3048     * vertically.
3049     * {@hide}
3050     */
3051    @ViewDebug.ExportedProperty(category = "scrolling")
3052    protected int mScrollY;
3053
3054    /**
3055     * The left padding in pixels, that is the distance in pixels between the
3056     * left edge of this view and the left edge of its content.
3057     * {@hide}
3058     */
3059    @ViewDebug.ExportedProperty(category = "padding")
3060    protected int mPaddingLeft = 0;
3061    /**
3062     * The right padding in pixels, that is the distance in pixels between the
3063     * right edge of this view and the right edge of its content.
3064     * {@hide}
3065     */
3066    @ViewDebug.ExportedProperty(category = "padding")
3067    protected int mPaddingRight = 0;
3068    /**
3069     * The top padding in pixels, that is the distance in pixels between the
3070     * top edge of this view and the top edge of its content.
3071     * {@hide}
3072     */
3073    @ViewDebug.ExportedProperty(category = "padding")
3074    protected int mPaddingTop;
3075    /**
3076     * The bottom padding in pixels, that is the distance in pixels between the
3077     * bottom edge of this view and the bottom edge of its content.
3078     * {@hide}
3079     */
3080    @ViewDebug.ExportedProperty(category = "padding")
3081    protected int mPaddingBottom;
3082
3083    /**
3084     * The layout insets in pixels, that is the distance in pixels between the
3085     * visible edges of this view its bounds.
3086     */
3087    private Insets mLayoutInsets;
3088
3089    /**
3090     * Briefly describes the view and is primarily used for accessibility support.
3091     */
3092    private CharSequence mContentDescription;
3093
3094    /**
3095     * Specifies the id of a view for which this view serves as a label for
3096     * accessibility purposes.
3097     */
3098    private int mLabelForId = View.NO_ID;
3099
3100    /**
3101     * Predicate for matching labeled view id with its label for
3102     * accessibility purposes.
3103     */
3104    private MatchLabelForPredicate mMatchLabelForPredicate;
3105
3106    /**
3107     * Specifies a view before which this one is visited in accessibility traversal.
3108     */
3109    private int mAccessibilityTraversalBeforeId = NO_ID;
3110
3111    /**
3112     * Specifies a view after which this one is visited in accessibility traversal.
3113     */
3114    private int mAccessibilityTraversalAfterId = NO_ID;
3115
3116    /**
3117     * Predicate for matching a view by its id.
3118     */
3119    private MatchIdPredicate mMatchIdPredicate;
3120
3121    /**
3122     * Cache the paddingRight set by the user to append to the scrollbar's size.
3123     *
3124     * @hide
3125     */
3126    @ViewDebug.ExportedProperty(category = "padding")
3127    protected int mUserPaddingRight;
3128
3129    /**
3130     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3131     *
3132     * @hide
3133     */
3134    @ViewDebug.ExportedProperty(category = "padding")
3135    protected int mUserPaddingBottom;
3136
3137    /**
3138     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3139     *
3140     * @hide
3141     */
3142    @ViewDebug.ExportedProperty(category = "padding")
3143    protected int mUserPaddingLeft;
3144
3145    /**
3146     * Cache the paddingStart set by the user to append to the scrollbar's size.
3147     *
3148     */
3149    @ViewDebug.ExportedProperty(category = "padding")
3150    int mUserPaddingStart;
3151
3152    /**
3153     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3154     *
3155     */
3156    @ViewDebug.ExportedProperty(category = "padding")
3157    int mUserPaddingEnd;
3158
3159    /**
3160     * Cache initial left padding.
3161     *
3162     * @hide
3163     */
3164    int mUserPaddingLeftInitial;
3165
3166    /**
3167     * Cache initial right padding.
3168     *
3169     * @hide
3170     */
3171    int mUserPaddingRightInitial;
3172
3173    /**
3174     * Default undefined padding
3175     */
3176    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3177
3178    /**
3179     * Cache if a left padding has been defined
3180     */
3181    private boolean mLeftPaddingDefined = false;
3182
3183    /**
3184     * Cache if a right padding has been defined
3185     */
3186    private boolean mRightPaddingDefined = false;
3187
3188    /**
3189     * @hide
3190     */
3191    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3192    /**
3193     * @hide
3194     */
3195    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3196
3197    private LongSparseLongArray mMeasureCache;
3198
3199    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3200    private Drawable mBackground;
3201    private TintInfo mBackgroundTint;
3202
3203    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3204    private ForegroundInfo mForegroundInfo;
3205
3206    /**
3207     * RenderNode used for backgrounds.
3208     * <p>
3209     * When non-null and valid, this is expected to contain an up-to-date copy
3210     * of the background drawable. It is cleared on temporary detach, and reset
3211     * on cleanup.
3212     */
3213    private RenderNode mBackgroundRenderNode;
3214
3215    private int mBackgroundResource;
3216    private boolean mBackgroundSizeChanged;
3217
3218    private String mTransitionName;
3219
3220    static class TintInfo {
3221        ColorStateList mTintList;
3222        PorterDuff.Mode mTintMode;
3223        boolean mHasTintMode;
3224        boolean mHasTintList;
3225    }
3226
3227    private static class ForegroundInfo {
3228        private Drawable mDrawable;
3229        private TintInfo mTintInfo;
3230        private int mGravity = Gravity.FILL;
3231        private boolean mInsidePadding = true;
3232        private boolean mBoundsChanged = true;
3233        private final Rect mSelfBounds = new Rect();
3234        private final Rect mOverlayBounds = new Rect();
3235    }
3236
3237    static class ListenerInfo {
3238        /**
3239         * Listener used to dispatch focus change events.
3240         * This field should be made private, so it is hidden from the SDK.
3241         * {@hide}
3242         */
3243        protected OnFocusChangeListener mOnFocusChangeListener;
3244
3245        /**
3246         * Listeners for layout change events.
3247         */
3248        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3249
3250        protected OnScrollChangeListener mOnScrollChangeListener;
3251
3252        /**
3253         * Listeners for attach events.
3254         */
3255        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3256
3257        /**
3258         * Listener used to dispatch click events.
3259         * This field should be made private, so it is hidden from the SDK.
3260         * {@hide}
3261         */
3262        public OnClickListener mOnClickListener;
3263
3264        /**
3265         * Listener used to dispatch long click events.
3266         * This field should be made private, so it is hidden from the SDK.
3267         * {@hide}
3268         */
3269        protected OnLongClickListener mOnLongClickListener;
3270
3271        /**
3272         * Listener used to build the context menu.
3273         * This field should be made private, so it is hidden from the SDK.
3274         * {@hide}
3275         */
3276        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3277
3278        private OnKeyListener mOnKeyListener;
3279
3280        private OnTouchListener mOnTouchListener;
3281
3282        private OnHoverListener mOnHoverListener;
3283
3284        private OnGenericMotionListener mOnGenericMotionListener;
3285
3286        private OnDragListener mOnDragListener;
3287
3288        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3289
3290        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3291    }
3292
3293    ListenerInfo mListenerInfo;
3294
3295    /**
3296     * The application environment this view lives in.
3297     * This field should be made private, so it is hidden from the SDK.
3298     * {@hide}
3299     */
3300    @ViewDebug.ExportedProperty(deepExport = true)
3301    protected Context mContext;
3302
3303    private final Resources mResources;
3304
3305    private ScrollabilityCache mScrollCache;
3306
3307    private int[] mDrawableState = null;
3308
3309    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3310
3311    /**
3312     * Animator that automatically runs based on state changes.
3313     */
3314    private StateListAnimator mStateListAnimator;
3315
3316    /**
3317     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3318     * the user may specify which view to go to next.
3319     */
3320    private int mNextFocusLeftId = View.NO_ID;
3321
3322    /**
3323     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3324     * the user may specify which view to go to next.
3325     */
3326    private int mNextFocusRightId = View.NO_ID;
3327
3328    /**
3329     * When this view has focus and the next focus is {@link #FOCUS_UP},
3330     * the user may specify which view to go to next.
3331     */
3332    private int mNextFocusUpId = View.NO_ID;
3333
3334    /**
3335     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3336     * the user may specify which view to go to next.
3337     */
3338    private int mNextFocusDownId = View.NO_ID;
3339
3340    /**
3341     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3342     * the user may specify which view to go to next.
3343     */
3344    int mNextFocusForwardId = View.NO_ID;
3345
3346    private CheckForLongPress mPendingCheckForLongPress;
3347    private CheckForTap mPendingCheckForTap = null;
3348    private PerformClick mPerformClick;
3349    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3350
3351    private UnsetPressedState mUnsetPressedState;
3352
3353    /**
3354     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3355     * up event while a long press is invoked as soon as the long press duration is reached, so
3356     * a long press could be performed before the tap is checked, in which case the tap's action
3357     * should not be invoked.
3358     */
3359    private boolean mHasPerformedLongPress;
3360
3361    /**
3362     * The minimum height of the view. We'll try our best to have the height
3363     * of this view to at least this amount.
3364     */
3365    @ViewDebug.ExportedProperty(category = "measurement")
3366    private int mMinHeight;
3367
3368    /**
3369     * The minimum width of the view. We'll try our best to have the width
3370     * of this view to at least this amount.
3371     */
3372    @ViewDebug.ExportedProperty(category = "measurement")
3373    private int mMinWidth;
3374
3375    /**
3376     * The delegate to handle touch events that are physically in this view
3377     * but should be handled by another view.
3378     */
3379    private TouchDelegate mTouchDelegate = null;
3380
3381    /**
3382     * Solid color to use as a background when creating the drawing cache. Enables
3383     * the cache to use 16 bit bitmaps instead of 32 bit.
3384     */
3385    private int mDrawingCacheBackgroundColor = 0;
3386
3387    /**
3388     * Special tree observer used when mAttachInfo is null.
3389     */
3390    private ViewTreeObserver mFloatingTreeObserver;
3391
3392    /**
3393     * Cache the touch slop from the context that created the view.
3394     */
3395    private int mTouchSlop;
3396
3397    /**
3398     * Object that handles automatic animation of view properties.
3399     */
3400    private ViewPropertyAnimator mAnimator = null;
3401
3402    /**
3403     * Flag indicating that a drag can cross window boundaries.  When
3404     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3405     * with this flag set, all visible applications will be able to participate
3406     * in the drag operation and receive the dragged content.
3407     *
3408     * @hide
3409     */
3410    public static final int DRAG_FLAG_GLOBAL = 1;
3411
3412    /**
3413     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3414     */
3415    private float mVerticalScrollFactor;
3416
3417    /**
3418     * Position of the vertical scroll bar.
3419     */
3420    private int mVerticalScrollbarPosition;
3421
3422    /**
3423     * Position the scroll bar at the default position as determined by the system.
3424     */
3425    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3426
3427    /**
3428     * Position the scroll bar along the left edge.
3429     */
3430    public static final int SCROLLBAR_POSITION_LEFT = 1;
3431
3432    /**
3433     * Position the scroll bar along the right edge.
3434     */
3435    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3436
3437    /**
3438     * Indicates that the view does not have a layer.
3439     *
3440     * @see #getLayerType()
3441     * @see #setLayerType(int, android.graphics.Paint)
3442     * @see #LAYER_TYPE_SOFTWARE
3443     * @see #LAYER_TYPE_HARDWARE
3444     */
3445    public static final int LAYER_TYPE_NONE = 0;
3446
3447    /**
3448     * <p>Indicates that the view has a software layer. A software layer is backed
3449     * by a bitmap and causes the view to be rendered using Android's software
3450     * rendering pipeline, even if hardware acceleration is enabled.</p>
3451     *
3452     * <p>Software layers have various usages:</p>
3453     * <p>When the application is not using hardware acceleration, a software layer
3454     * is useful to apply a specific color filter and/or blending mode and/or
3455     * translucency to a view and all its children.</p>
3456     * <p>When the application is using hardware acceleration, a software layer
3457     * is useful to render drawing primitives not supported by the hardware
3458     * accelerated pipeline. It can also be used to cache a complex view tree
3459     * into a texture and reduce the complexity of drawing operations. For instance,
3460     * when animating a complex view tree with a translation, a software layer can
3461     * be used to render the view tree only once.</p>
3462     * <p>Software layers should be avoided when the affected view tree updates
3463     * often. Every update will require to re-render the software layer, which can
3464     * potentially be slow (particularly when hardware acceleration is turned on
3465     * since the layer will have to be uploaded into a hardware texture after every
3466     * update.)</p>
3467     *
3468     * @see #getLayerType()
3469     * @see #setLayerType(int, android.graphics.Paint)
3470     * @see #LAYER_TYPE_NONE
3471     * @see #LAYER_TYPE_HARDWARE
3472     */
3473    public static final int LAYER_TYPE_SOFTWARE = 1;
3474
3475    /**
3476     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3477     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3478     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3479     * rendering pipeline, but only if hardware acceleration is turned on for the
3480     * view hierarchy. When hardware acceleration is turned off, hardware layers
3481     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3482     *
3483     * <p>A hardware layer is useful to apply a specific color filter and/or
3484     * blending mode and/or translucency to a view and all its children.</p>
3485     * <p>A hardware layer can be used to cache a complex view tree into a
3486     * texture and reduce the complexity of drawing operations. For instance,
3487     * when animating a complex view tree with a translation, a hardware layer can
3488     * be used to render the view tree only once.</p>
3489     * <p>A hardware layer can also be used to increase the rendering quality when
3490     * rotation transformations are applied on a view. It can also be used to
3491     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3492     *
3493     * @see #getLayerType()
3494     * @see #setLayerType(int, android.graphics.Paint)
3495     * @see #LAYER_TYPE_NONE
3496     * @see #LAYER_TYPE_SOFTWARE
3497     */
3498    public static final int LAYER_TYPE_HARDWARE = 2;
3499
3500    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3501            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3502            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3503            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3504    })
3505    int mLayerType = LAYER_TYPE_NONE;
3506    Paint mLayerPaint;
3507
3508    /**
3509     * Set to true when drawing cache is enabled and cannot be created.
3510     *
3511     * @hide
3512     */
3513    public boolean mCachingFailed;
3514    private Bitmap mDrawingCache;
3515    private Bitmap mUnscaledDrawingCache;
3516
3517    /**
3518     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3519     * <p>
3520     * When non-null and valid, this is expected to contain an up-to-date copy
3521     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3522     * cleanup.
3523     */
3524    final RenderNode mRenderNode;
3525
3526    /**
3527     * Set to true when the view is sending hover accessibility events because it
3528     * is the innermost hovered view.
3529     */
3530    private boolean mSendingHoverAccessibilityEvents;
3531
3532    /**
3533     * Delegate for injecting accessibility functionality.
3534     */
3535    AccessibilityDelegate mAccessibilityDelegate;
3536
3537    /**
3538     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3539     * and add/remove objects to/from the overlay directly through the Overlay methods.
3540     */
3541    ViewOverlay mOverlay;
3542
3543    /**
3544     * The currently active parent view for receiving delegated nested scrolling events.
3545     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3546     * by {@link #stopNestedScroll()} at the same point where we clear
3547     * requestDisallowInterceptTouchEvent.
3548     */
3549    private ViewParent mNestedScrollingParent;
3550
3551    /**
3552     * Consistency verifier for debugging purposes.
3553     * @hide
3554     */
3555    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3556            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3557                    new InputEventConsistencyVerifier(this, 0) : null;
3558
3559    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3560
3561    private int[] mTempNestedScrollConsumed;
3562
3563    /**
3564     * An overlay is going to draw this View instead of being drawn as part of this
3565     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3566     * when this view is invalidated.
3567     */
3568    GhostView mGhostView;
3569
3570    /**
3571     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3572     * @hide
3573     */
3574    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3575    public String[] mAttributes;
3576
3577    /**
3578     * Maps a Resource id to its name.
3579     */
3580    private static SparseArray<String> mAttributeMap;
3581
3582    /**
3583     * @hide
3584     */
3585    String mStartActivityRequestWho;
3586
3587    /**
3588     * Simple constructor to use when creating a view from code.
3589     *
3590     * @param context The Context the view is running in, through which it can
3591     *        access the current theme, resources, etc.
3592     */
3593    public View(Context context) {
3594        mContext = context;
3595        mResources = context != null ? context.getResources() : null;
3596        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3597        // Set some flags defaults
3598        mPrivateFlags2 =
3599                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3600                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3601                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3602                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3603                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3604                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3605        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3606        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3607        mUserPaddingStart = UNDEFINED_PADDING;
3608        mUserPaddingEnd = UNDEFINED_PADDING;
3609        mRenderNode = RenderNode.create(getClass().getName(), this);
3610
3611        if (!sCompatibilityDone && context != null) {
3612            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3613
3614            // Older apps may need this compatibility hack for measurement.
3615            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3616
3617            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3618            // of whether a layout was requested on that View.
3619            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3620
3621            Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
3622
3623            sCompatibilityDone = true;
3624        }
3625    }
3626
3627    /**
3628     * Constructor that is called when inflating a view from XML. This is called
3629     * when a view is being constructed from an XML file, supplying attributes
3630     * that were specified in the XML file. This version uses a default style of
3631     * 0, so the only attribute values applied are those in the Context's Theme
3632     * and the given AttributeSet.
3633     *
3634     * <p>
3635     * The method onFinishInflate() will be called after all children have been
3636     * added.
3637     *
3638     * @param context The Context the view is running in, through which it can
3639     *        access the current theme, resources, etc.
3640     * @param attrs The attributes of the XML tag that is inflating the view.
3641     * @see #View(Context, AttributeSet, int)
3642     */
3643    public View(Context context, @Nullable AttributeSet attrs) {
3644        this(context, attrs, 0);
3645    }
3646
3647    /**
3648     * Perform inflation from XML and apply a class-specific base style from a
3649     * theme attribute. This constructor of View allows subclasses to use their
3650     * own base style when they are inflating. For example, a Button class's
3651     * constructor would call this version of the super class constructor and
3652     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3653     * allows the theme's button style to modify all of the base view attributes
3654     * (in particular its background) as well as the Button class's attributes.
3655     *
3656     * @param context The Context the view is running in, through which it can
3657     *        access the current theme, resources, etc.
3658     * @param attrs The attributes of the XML tag that is inflating the view.
3659     * @param defStyleAttr An attribute in the current theme that contains a
3660     *        reference to a style resource that supplies default values for
3661     *        the view. Can be 0 to not look for defaults.
3662     * @see #View(Context, AttributeSet)
3663     */
3664    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3665        this(context, attrs, defStyleAttr, 0);
3666    }
3667
3668    /**
3669     * Perform inflation from XML and apply a class-specific base style from a
3670     * theme attribute or style resource. This constructor of View allows
3671     * subclasses to use their own base style when they are inflating.
3672     * <p>
3673     * When determining the final value of a particular attribute, there are
3674     * four inputs that come into play:
3675     * <ol>
3676     * <li>Any attribute values in the given AttributeSet.
3677     * <li>The style resource specified in the AttributeSet (named "style").
3678     * <li>The default style specified by <var>defStyleAttr</var>.
3679     * <li>The default style specified by <var>defStyleRes</var>.
3680     * <li>The base values in this theme.
3681     * </ol>
3682     * <p>
3683     * Each of these inputs is considered in-order, with the first listed taking
3684     * precedence over the following ones. In other words, if in the
3685     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3686     * , then the button's text will <em>always</em> be black, regardless of
3687     * what is specified in any of the styles.
3688     *
3689     * @param context The Context the view is running in, through which it can
3690     *        access the current theme, resources, etc.
3691     * @param attrs The attributes of the XML tag that is inflating the view.
3692     * @param defStyleAttr An attribute in the current theme that contains a
3693     *        reference to a style resource that supplies default values for
3694     *        the view. Can be 0 to not look for defaults.
3695     * @param defStyleRes A resource identifier of a style resource that
3696     *        supplies default values for the view, used only if
3697     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3698     *        to not look for defaults.
3699     * @see #View(Context, AttributeSet, int)
3700     */
3701    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3702        this(context);
3703
3704        final TypedArray a = context.obtainStyledAttributes(
3705                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3706
3707        if (mDebugViewAttributes) {
3708            saveAttributeData(attrs, a);
3709        }
3710
3711        Drawable background = null;
3712
3713        int leftPadding = -1;
3714        int topPadding = -1;
3715        int rightPadding = -1;
3716        int bottomPadding = -1;
3717        int startPadding = UNDEFINED_PADDING;
3718        int endPadding = UNDEFINED_PADDING;
3719
3720        int padding = -1;
3721
3722        int viewFlagValues = 0;
3723        int viewFlagMasks = 0;
3724
3725        boolean setScrollContainer = false;
3726
3727        int x = 0;
3728        int y = 0;
3729
3730        float tx = 0;
3731        float ty = 0;
3732        float tz = 0;
3733        float elevation = 0;
3734        float rotation = 0;
3735        float rotationX = 0;
3736        float rotationY = 0;
3737        float sx = 1f;
3738        float sy = 1f;
3739        boolean transformSet = false;
3740
3741        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3742        int overScrollMode = mOverScrollMode;
3743        boolean initializeScrollbars = false;
3744
3745        boolean startPaddingDefined = false;
3746        boolean endPaddingDefined = false;
3747        boolean leftPaddingDefined = false;
3748        boolean rightPaddingDefined = false;
3749
3750        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3751
3752        final int N = a.getIndexCount();
3753        for (int i = 0; i < N; i++) {
3754            int attr = a.getIndex(i);
3755            switch (attr) {
3756                case com.android.internal.R.styleable.View_background:
3757                    background = a.getDrawable(attr);
3758                    break;
3759                case com.android.internal.R.styleable.View_padding:
3760                    padding = a.getDimensionPixelSize(attr, -1);
3761                    mUserPaddingLeftInitial = padding;
3762                    mUserPaddingRightInitial = padding;
3763                    leftPaddingDefined = true;
3764                    rightPaddingDefined = true;
3765                    break;
3766                 case com.android.internal.R.styleable.View_paddingLeft:
3767                    leftPadding = a.getDimensionPixelSize(attr, -1);
3768                    mUserPaddingLeftInitial = leftPadding;
3769                    leftPaddingDefined = true;
3770                    break;
3771                case com.android.internal.R.styleable.View_paddingTop:
3772                    topPadding = a.getDimensionPixelSize(attr, -1);
3773                    break;
3774                case com.android.internal.R.styleable.View_paddingRight:
3775                    rightPadding = a.getDimensionPixelSize(attr, -1);
3776                    mUserPaddingRightInitial = rightPadding;
3777                    rightPaddingDefined = true;
3778                    break;
3779                case com.android.internal.R.styleable.View_paddingBottom:
3780                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3781                    break;
3782                case com.android.internal.R.styleable.View_paddingStart:
3783                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3784                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3785                    break;
3786                case com.android.internal.R.styleable.View_paddingEnd:
3787                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3788                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3789                    break;
3790                case com.android.internal.R.styleable.View_scrollX:
3791                    x = a.getDimensionPixelOffset(attr, 0);
3792                    break;
3793                case com.android.internal.R.styleable.View_scrollY:
3794                    y = a.getDimensionPixelOffset(attr, 0);
3795                    break;
3796                case com.android.internal.R.styleable.View_alpha:
3797                    setAlpha(a.getFloat(attr, 1f));
3798                    break;
3799                case com.android.internal.R.styleable.View_transformPivotX:
3800                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3801                    break;
3802                case com.android.internal.R.styleable.View_transformPivotY:
3803                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3804                    break;
3805                case com.android.internal.R.styleable.View_translationX:
3806                    tx = a.getDimensionPixelOffset(attr, 0);
3807                    transformSet = true;
3808                    break;
3809                case com.android.internal.R.styleable.View_translationY:
3810                    ty = a.getDimensionPixelOffset(attr, 0);
3811                    transformSet = true;
3812                    break;
3813                case com.android.internal.R.styleable.View_translationZ:
3814                    tz = a.getDimensionPixelOffset(attr, 0);
3815                    transformSet = true;
3816                    break;
3817                case com.android.internal.R.styleable.View_elevation:
3818                    elevation = a.getDimensionPixelOffset(attr, 0);
3819                    transformSet = true;
3820                    break;
3821                case com.android.internal.R.styleable.View_rotation:
3822                    rotation = a.getFloat(attr, 0);
3823                    transformSet = true;
3824                    break;
3825                case com.android.internal.R.styleable.View_rotationX:
3826                    rotationX = a.getFloat(attr, 0);
3827                    transformSet = true;
3828                    break;
3829                case com.android.internal.R.styleable.View_rotationY:
3830                    rotationY = a.getFloat(attr, 0);
3831                    transformSet = true;
3832                    break;
3833                case com.android.internal.R.styleable.View_scaleX:
3834                    sx = a.getFloat(attr, 1f);
3835                    transformSet = true;
3836                    break;
3837                case com.android.internal.R.styleable.View_scaleY:
3838                    sy = a.getFloat(attr, 1f);
3839                    transformSet = true;
3840                    break;
3841                case com.android.internal.R.styleable.View_id:
3842                    mID = a.getResourceId(attr, NO_ID);
3843                    break;
3844                case com.android.internal.R.styleable.View_tag:
3845                    mTag = a.getText(attr);
3846                    break;
3847                case com.android.internal.R.styleable.View_fitsSystemWindows:
3848                    if (a.getBoolean(attr, false)) {
3849                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3850                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3851                    }
3852                    break;
3853                case com.android.internal.R.styleable.View_focusable:
3854                    if (a.getBoolean(attr, false)) {
3855                        viewFlagValues |= FOCUSABLE;
3856                        viewFlagMasks |= FOCUSABLE_MASK;
3857                    }
3858                    break;
3859                case com.android.internal.R.styleable.View_focusableInTouchMode:
3860                    if (a.getBoolean(attr, false)) {
3861                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3862                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3863                    }
3864                    break;
3865                case com.android.internal.R.styleable.View_clickable:
3866                    if (a.getBoolean(attr, false)) {
3867                        viewFlagValues |= CLICKABLE;
3868                        viewFlagMasks |= CLICKABLE;
3869                    }
3870                    break;
3871                case com.android.internal.R.styleable.View_longClickable:
3872                    if (a.getBoolean(attr, false)) {
3873                        viewFlagValues |= LONG_CLICKABLE;
3874                        viewFlagMasks |= LONG_CLICKABLE;
3875                    }
3876                    break;
3877                case com.android.internal.R.styleable.View_saveEnabled:
3878                    if (!a.getBoolean(attr, true)) {
3879                        viewFlagValues |= SAVE_DISABLED;
3880                        viewFlagMasks |= SAVE_DISABLED_MASK;
3881                    }
3882                    break;
3883                case com.android.internal.R.styleable.View_assistBlocked:
3884                    if (a.getBoolean(attr, false)) {
3885                        mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
3886                    }
3887                    break;
3888                case com.android.internal.R.styleable.View_duplicateParentState:
3889                    if (a.getBoolean(attr, false)) {
3890                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3891                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3892                    }
3893                    break;
3894                case com.android.internal.R.styleable.View_visibility:
3895                    final int visibility = a.getInt(attr, 0);
3896                    if (visibility != 0) {
3897                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3898                        viewFlagMasks |= VISIBILITY_MASK;
3899                    }
3900                    break;
3901                case com.android.internal.R.styleable.View_layoutDirection:
3902                    // Clear any layout direction flags (included resolved bits) already set
3903                    mPrivateFlags2 &=
3904                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3905                    // Set the layout direction flags depending on the value of the attribute
3906                    final int layoutDirection = a.getInt(attr, -1);
3907                    final int value = (layoutDirection != -1) ?
3908                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3909                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3910                    break;
3911                case com.android.internal.R.styleable.View_drawingCacheQuality:
3912                    final int cacheQuality = a.getInt(attr, 0);
3913                    if (cacheQuality != 0) {
3914                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3915                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3916                    }
3917                    break;
3918                case com.android.internal.R.styleable.View_contentDescription:
3919                    setContentDescription(a.getString(attr));
3920                    break;
3921                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
3922                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
3923                    break;
3924                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
3925                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
3926                    break;
3927                case com.android.internal.R.styleable.View_labelFor:
3928                    setLabelFor(a.getResourceId(attr, NO_ID));
3929                    break;
3930                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3931                    if (!a.getBoolean(attr, true)) {
3932                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3933                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3934                    }
3935                    break;
3936                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3937                    if (!a.getBoolean(attr, true)) {
3938                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3939                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3940                    }
3941                    break;
3942                case R.styleable.View_scrollbars:
3943                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3944                    if (scrollbars != SCROLLBARS_NONE) {
3945                        viewFlagValues |= scrollbars;
3946                        viewFlagMasks |= SCROLLBARS_MASK;
3947                        initializeScrollbars = true;
3948                    }
3949                    break;
3950                //noinspection deprecation
3951                case R.styleable.View_fadingEdge:
3952                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3953                        // Ignore the attribute starting with ICS
3954                        break;
3955                    }
3956                    // With builds < ICS, fall through and apply fading edges
3957                case R.styleable.View_requiresFadingEdge:
3958                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3959                    if (fadingEdge != FADING_EDGE_NONE) {
3960                        viewFlagValues |= fadingEdge;
3961                        viewFlagMasks |= FADING_EDGE_MASK;
3962                        initializeFadingEdgeInternal(a);
3963                    }
3964                    break;
3965                case R.styleable.View_scrollbarStyle:
3966                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3967                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3968                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3969                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3970                    }
3971                    break;
3972                case R.styleable.View_isScrollContainer:
3973                    setScrollContainer = true;
3974                    if (a.getBoolean(attr, false)) {
3975                        setScrollContainer(true);
3976                    }
3977                    break;
3978                case com.android.internal.R.styleable.View_keepScreenOn:
3979                    if (a.getBoolean(attr, false)) {
3980                        viewFlagValues |= KEEP_SCREEN_ON;
3981                        viewFlagMasks |= KEEP_SCREEN_ON;
3982                    }
3983                    break;
3984                case R.styleable.View_filterTouchesWhenObscured:
3985                    if (a.getBoolean(attr, false)) {
3986                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3987                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3988                    }
3989                    break;
3990                case R.styleable.View_nextFocusLeft:
3991                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3992                    break;
3993                case R.styleable.View_nextFocusRight:
3994                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3995                    break;
3996                case R.styleable.View_nextFocusUp:
3997                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3998                    break;
3999                case R.styleable.View_nextFocusDown:
4000                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4001                    break;
4002                case R.styleable.View_nextFocusForward:
4003                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4004                    break;
4005                case R.styleable.View_minWidth:
4006                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4007                    break;
4008                case R.styleable.View_minHeight:
4009                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4010                    break;
4011                case R.styleable.View_onClick:
4012                    if (context.isRestricted()) {
4013                        throw new IllegalStateException("The android:onClick attribute cannot "
4014                                + "be used within a restricted context");
4015                    }
4016
4017                    final String handlerName = a.getString(attr);
4018                    if (handlerName != null) {
4019                        setOnClickListener(new OnClickListener() {
4020                            private Method mHandler;
4021
4022                            public void onClick(View v) {
4023                                if (mHandler == null) {
4024                                    try {
4025                                        mHandler = getContext().getClass().getMethod(handlerName,
4026                                                View.class);
4027                                    } catch (NoSuchMethodException e) {
4028                                        int id = getId();
4029                                        String idText = id == NO_ID ? "" : " with id '"
4030                                                + getContext().getResources().getResourceEntryName(
4031                                                    id) + "'";
4032                                        throw new IllegalStateException("Could not find a method " +
4033                                                handlerName + "(View) in the activity "
4034                                                + getContext().getClass() + " for onClick handler"
4035                                                + " on view " + View.this.getClass() + idText, e);
4036                                    }
4037                                }
4038
4039                                try {
4040                                    mHandler.invoke(getContext(), View.this);
4041                                } catch (IllegalAccessException e) {
4042                                    throw new IllegalStateException("Could not execute non "
4043                                            + "public method of the activity", e);
4044                                } catch (InvocationTargetException e) {
4045                                    throw new IllegalStateException("Could not execute "
4046                                            + "method of the activity", e);
4047                                }
4048                            }
4049                        });
4050                    }
4051                    break;
4052                case R.styleable.View_overScrollMode:
4053                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4054                    break;
4055                case R.styleable.View_verticalScrollbarPosition:
4056                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4057                    break;
4058                case R.styleable.View_layerType:
4059                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4060                    break;
4061                case R.styleable.View_textDirection:
4062                    // Clear any text direction flag already set
4063                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4064                    // Set the text direction flags depending on the value of the attribute
4065                    final int textDirection = a.getInt(attr, -1);
4066                    if (textDirection != -1) {
4067                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4068                    }
4069                    break;
4070                case R.styleable.View_textAlignment:
4071                    // Clear any text alignment flag already set
4072                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4073                    // Set the text alignment flag depending on the value of the attribute
4074                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4075                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4076                    break;
4077                case R.styleable.View_importantForAccessibility:
4078                    setImportantForAccessibility(a.getInt(attr,
4079                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4080                    break;
4081                case R.styleable.View_accessibilityLiveRegion:
4082                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4083                    break;
4084                case R.styleable.View_transitionName:
4085                    setTransitionName(a.getString(attr));
4086                    break;
4087                case R.styleable.View_nestedScrollingEnabled:
4088                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4089                    break;
4090                case R.styleable.View_stateListAnimator:
4091                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4092                            a.getResourceId(attr, 0)));
4093                    break;
4094                case R.styleable.View_backgroundTint:
4095                    // This will get applied later during setBackground().
4096                    if (mBackgroundTint == null) {
4097                        mBackgroundTint = new TintInfo();
4098                    }
4099                    mBackgroundTint.mTintList = a.getColorStateList(
4100                            R.styleable.View_backgroundTint);
4101                    mBackgroundTint.mHasTintList = true;
4102                    break;
4103                case R.styleable.View_backgroundTintMode:
4104                    // This will get applied later during setBackground().
4105                    if (mBackgroundTint == null) {
4106                        mBackgroundTint = new TintInfo();
4107                    }
4108                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4109                            R.styleable.View_backgroundTintMode, -1), null);
4110                    mBackgroundTint.mHasTintMode = true;
4111                    break;
4112                case R.styleable.View_outlineProvider:
4113                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4114                            PROVIDER_BACKGROUND));
4115                    break;
4116                case R.styleable.View_foreground:
4117                    setForeground(a.getDrawable(attr));
4118                    break;
4119                case R.styleable.View_foregroundGravity:
4120                    setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4121                    break;
4122                case R.styleable.View_foregroundTintMode:
4123                    setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4124                    break;
4125                case R.styleable.View_foregroundTint:
4126                    setForegroundTintList(a.getColorStateList(attr));
4127                    break;
4128                case R.styleable.View_foregroundInsidePadding:
4129                    if (mForegroundInfo == null) {
4130                        mForegroundInfo = new ForegroundInfo();
4131                    }
4132                    mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4133                            mForegroundInfo.mInsidePadding);
4134                    break;
4135            }
4136        }
4137
4138        setOverScrollMode(overScrollMode);
4139
4140        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4141        // the resolved layout direction). Those cached values will be used later during padding
4142        // resolution.
4143        mUserPaddingStart = startPadding;
4144        mUserPaddingEnd = endPadding;
4145
4146        if (background != null) {
4147            setBackground(background);
4148        }
4149
4150        // setBackground above will record that padding is currently provided by the background.
4151        // If we have padding specified via xml, record that here instead and use it.
4152        mLeftPaddingDefined = leftPaddingDefined;
4153        mRightPaddingDefined = rightPaddingDefined;
4154
4155        if (padding >= 0) {
4156            leftPadding = padding;
4157            topPadding = padding;
4158            rightPadding = padding;
4159            bottomPadding = padding;
4160            mUserPaddingLeftInitial = padding;
4161            mUserPaddingRightInitial = padding;
4162        }
4163
4164        if (isRtlCompatibilityMode()) {
4165            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4166            // left / right padding are used if defined (meaning here nothing to do). If they are not
4167            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4168            // start / end and resolve them as left / right (layout direction is not taken into account).
4169            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4170            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4171            // defined.
4172            if (!mLeftPaddingDefined && startPaddingDefined) {
4173                leftPadding = startPadding;
4174            }
4175            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4176            if (!mRightPaddingDefined && endPaddingDefined) {
4177                rightPadding = endPadding;
4178            }
4179            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4180        } else {
4181            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4182            // values defined. Otherwise, left /right values are used.
4183            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4184            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4185            // defined.
4186            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4187
4188            if (mLeftPaddingDefined && !hasRelativePadding) {
4189                mUserPaddingLeftInitial = leftPadding;
4190            }
4191            if (mRightPaddingDefined && !hasRelativePadding) {
4192                mUserPaddingRightInitial = rightPadding;
4193            }
4194        }
4195
4196        internalSetPadding(
4197                mUserPaddingLeftInitial,
4198                topPadding >= 0 ? topPadding : mPaddingTop,
4199                mUserPaddingRightInitial,
4200                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4201
4202        if (viewFlagMasks != 0) {
4203            setFlags(viewFlagValues, viewFlagMasks);
4204        }
4205
4206        if (initializeScrollbars) {
4207            initializeScrollbarsInternal(a);
4208        }
4209
4210        a.recycle();
4211
4212        // Needs to be called after mViewFlags is set
4213        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4214            recomputePadding();
4215        }
4216
4217        if (x != 0 || y != 0) {
4218            scrollTo(x, y);
4219        }
4220
4221        if (transformSet) {
4222            setTranslationX(tx);
4223            setTranslationY(ty);
4224            setTranslationZ(tz);
4225            setElevation(elevation);
4226            setRotation(rotation);
4227            setRotationX(rotationX);
4228            setRotationY(rotationY);
4229            setScaleX(sx);
4230            setScaleY(sy);
4231        }
4232
4233        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4234            setScrollContainer(true);
4235        }
4236
4237        computeOpaqueFlags();
4238    }
4239
4240    /**
4241     * Non-public constructor for use in testing
4242     */
4243    View() {
4244        mResources = null;
4245        mRenderNode = RenderNode.create(getClass().getName(), this);
4246    }
4247
4248    private static SparseArray<String> getAttributeMap() {
4249        if (mAttributeMap == null) {
4250            mAttributeMap = new SparseArray<String>();
4251        }
4252        return mAttributeMap;
4253    }
4254
4255    private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4256        int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4257        mAttributes = new String[length];
4258
4259        int i = 0;
4260        if (attrs != null) {
4261            for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4262                mAttributes[i] = attrs.getAttributeName(i);
4263                mAttributes[i + 1] = attrs.getAttributeValue(i);
4264            }
4265
4266        }
4267
4268        SparseArray<String> attributeMap = getAttributeMap();
4269        for (int j = 0; j < a.length(); ++j) {
4270            if (a.hasValue(j)) {
4271                try {
4272                    int resourceId = a.getResourceId(j, 0);
4273                    if (resourceId == 0) {
4274                        continue;
4275                    }
4276
4277                    String resourceName = attributeMap.get(resourceId);
4278                    if (resourceName == null) {
4279                        resourceName = a.getResources().getResourceName(resourceId);
4280                        attributeMap.put(resourceId, resourceName);
4281                    }
4282
4283                    mAttributes[i] = resourceName;
4284                    mAttributes[i + 1] = a.getText(j).toString();
4285                    i += 2;
4286                } catch (Resources.NotFoundException e) {
4287                    // if we can't get the resource name, we just ignore it
4288                }
4289            }
4290        }
4291    }
4292
4293    public String toString() {
4294        StringBuilder out = new StringBuilder(128);
4295        out.append(getClass().getName());
4296        out.append('{');
4297        out.append(Integer.toHexString(System.identityHashCode(this)));
4298        out.append(' ');
4299        switch (mViewFlags&VISIBILITY_MASK) {
4300            case VISIBLE: out.append('V'); break;
4301            case INVISIBLE: out.append('I'); break;
4302            case GONE: out.append('G'); break;
4303            default: out.append('.'); break;
4304        }
4305        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4306        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4307        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4308        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4309        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4310        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4311        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4312        out.append(' ');
4313        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4314        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4315        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4316        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4317            out.append('p');
4318        } else {
4319            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4320        }
4321        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4322        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4323        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4324        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4325        out.append(' ');
4326        out.append(mLeft);
4327        out.append(',');
4328        out.append(mTop);
4329        out.append('-');
4330        out.append(mRight);
4331        out.append(',');
4332        out.append(mBottom);
4333        final int id = getId();
4334        if (id != NO_ID) {
4335            out.append(" #");
4336            out.append(Integer.toHexString(id));
4337            final Resources r = mResources;
4338            if (Resources.resourceHasPackage(id) && r != null) {
4339                try {
4340                    String pkgname;
4341                    switch (id&0xff000000) {
4342                        case 0x7f000000:
4343                            pkgname="app";
4344                            break;
4345                        case 0x01000000:
4346                            pkgname="android";
4347                            break;
4348                        default:
4349                            pkgname = r.getResourcePackageName(id);
4350                            break;
4351                    }
4352                    String typename = r.getResourceTypeName(id);
4353                    String entryname = r.getResourceEntryName(id);
4354                    out.append(" ");
4355                    out.append(pkgname);
4356                    out.append(":");
4357                    out.append(typename);
4358                    out.append("/");
4359                    out.append(entryname);
4360                } catch (Resources.NotFoundException e) {
4361                }
4362            }
4363        }
4364        out.append("}");
4365        return out.toString();
4366    }
4367
4368    /**
4369     * <p>
4370     * Initializes the fading edges from a given set of styled attributes. This
4371     * method should be called by subclasses that need fading edges and when an
4372     * instance of these subclasses is created programmatically rather than
4373     * being inflated from XML. This method is automatically called when the XML
4374     * is inflated.
4375     * </p>
4376     *
4377     * @param a the styled attributes set to initialize the fading edges from
4378     *
4379     * @removed
4380     */
4381    protected void initializeFadingEdge(TypedArray a) {
4382        // This method probably shouldn't have been included in the SDK to begin with.
4383        // It relies on 'a' having been initialized using an attribute filter array that is
4384        // not publicly available to the SDK. The old method has been renamed
4385        // to initializeFadingEdgeInternal and hidden for framework use only;
4386        // this one initializes using defaults to make it safe to call for apps.
4387
4388        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4389
4390        initializeFadingEdgeInternal(arr);
4391
4392        arr.recycle();
4393    }
4394
4395    /**
4396     * <p>
4397     * Initializes the fading edges from a given set of styled attributes. This
4398     * method should be called by subclasses that need fading edges and when an
4399     * instance of these subclasses is created programmatically rather than
4400     * being inflated from XML. This method is automatically called when the XML
4401     * is inflated.
4402     * </p>
4403     *
4404     * @param a the styled attributes set to initialize the fading edges from
4405     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4406     */
4407    protected void initializeFadingEdgeInternal(TypedArray a) {
4408        initScrollCache();
4409
4410        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4411                R.styleable.View_fadingEdgeLength,
4412                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4413    }
4414
4415    /**
4416     * Returns the size of the vertical faded edges used to indicate that more
4417     * content in this view is visible.
4418     *
4419     * @return The size in pixels of the vertical faded edge or 0 if vertical
4420     *         faded edges are not enabled for this view.
4421     * @attr ref android.R.styleable#View_fadingEdgeLength
4422     */
4423    public int getVerticalFadingEdgeLength() {
4424        if (isVerticalFadingEdgeEnabled()) {
4425            ScrollabilityCache cache = mScrollCache;
4426            if (cache != null) {
4427                return cache.fadingEdgeLength;
4428            }
4429        }
4430        return 0;
4431    }
4432
4433    /**
4434     * Set the size of the faded edge used to indicate that more content in this
4435     * view is available.  Will not change whether the fading edge is enabled; use
4436     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4437     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4438     * for the vertical or horizontal fading edges.
4439     *
4440     * @param length The size in pixels of the faded edge used to indicate that more
4441     *        content in this view is visible.
4442     */
4443    public void setFadingEdgeLength(int length) {
4444        initScrollCache();
4445        mScrollCache.fadingEdgeLength = length;
4446    }
4447
4448    /**
4449     * Returns the size of the horizontal faded edges used to indicate that more
4450     * content in this view is visible.
4451     *
4452     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4453     *         faded edges are not enabled for this view.
4454     * @attr ref android.R.styleable#View_fadingEdgeLength
4455     */
4456    public int getHorizontalFadingEdgeLength() {
4457        if (isHorizontalFadingEdgeEnabled()) {
4458            ScrollabilityCache cache = mScrollCache;
4459            if (cache != null) {
4460                return cache.fadingEdgeLength;
4461            }
4462        }
4463        return 0;
4464    }
4465
4466    /**
4467     * Returns the width of the vertical scrollbar.
4468     *
4469     * @return The width in pixels of the vertical scrollbar or 0 if there
4470     *         is no vertical scrollbar.
4471     */
4472    public int getVerticalScrollbarWidth() {
4473        ScrollabilityCache cache = mScrollCache;
4474        if (cache != null) {
4475            ScrollBarDrawable scrollBar = cache.scrollBar;
4476            if (scrollBar != null) {
4477                int size = scrollBar.getSize(true);
4478                if (size <= 0) {
4479                    size = cache.scrollBarSize;
4480                }
4481                return size;
4482            }
4483            return 0;
4484        }
4485        return 0;
4486    }
4487
4488    /**
4489     * Returns the height of the horizontal scrollbar.
4490     *
4491     * @return The height in pixels of the horizontal scrollbar or 0 if
4492     *         there is no horizontal scrollbar.
4493     */
4494    protected int getHorizontalScrollbarHeight() {
4495        ScrollabilityCache cache = mScrollCache;
4496        if (cache != null) {
4497            ScrollBarDrawable scrollBar = cache.scrollBar;
4498            if (scrollBar != null) {
4499                int size = scrollBar.getSize(false);
4500                if (size <= 0) {
4501                    size = cache.scrollBarSize;
4502                }
4503                return size;
4504            }
4505            return 0;
4506        }
4507        return 0;
4508    }
4509
4510    /**
4511     * <p>
4512     * Initializes the scrollbars from a given set of styled attributes. This
4513     * method should be called by subclasses that need scrollbars and when an
4514     * instance of these subclasses is created programmatically rather than
4515     * being inflated from XML. This method is automatically called when the XML
4516     * is inflated.
4517     * </p>
4518     *
4519     * @param a the styled attributes set to initialize the scrollbars from
4520     *
4521     * @removed
4522     */
4523    protected void initializeScrollbars(TypedArray a) {
4524        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4525        // using the View filter array which is not available to the SDK. As such, internal
4526        // framework usage now uses initializeScrollbarsInternal and we grab a default
4527        // TypedArray with the right filter instead here.
4528        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4529
4530        initializeScrollbarsInternal(arr);
4531
4532        // We ignored the method parameter. Recycle the one we actually did use.
4533        arr.recycle();
4534    }
4535
4536    /**
4537     * <p>
4538     * Initializes the scrollbars from a given set of styled attributes. This
4539     * method should be called by subclasses that need scrollbars and when an
4540     * instance of these subclasses is created programmatically rather than
4541     * being inflated from XML. This method is automatically called when the XML
4542     * is inflated.
4543     * </p>
4544     *
4545     * @param a the styled attributes set to initialize the scrollbars from
4546     * @hide
4547     */
4548    protected void initializeScrollbarsInternal(TypedArray a) {
4549        initScrollCache();
4550
4551        final ScrollabilityCache scrollabilityCache = mScrollCache;
4552
4553        if (scrollabilityCache.scrollBar == null) {
4554            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4555            scrollabilityCache.scrollBar.setCallback(this);
4556            scrollabilityCache.scrollBar.setState(getDrawableState());
4557        }
4558
4559        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4560
4561        if (!fadeScrollbars) {
4562            scrollabilityCache.state = ScrollabilityCache.ON;
4563        }
4564        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4565
4566
4567        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4568                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4569                        .getScrollBarFadeDuration());
4570        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4571                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4572                ViewConfiguration.getScrollDefaultDelay());
4573
4574
4575        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4576                com.android.internal.R.styleable.View_scrollbarSize,
4577                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4578
4579        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4580        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4581
4582        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4583        if (thumb != null) {
4584            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4585        }
4586
4587        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4588                false);
4589        if (alwaysDraw) {
4590            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4591        }
4592
4593        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4594        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4595
4596        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4597        if (thumb != null) {
4598            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4599        }
4600
4601        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4602                false);
4603        if (alwaysDraw) {
4604            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4605        }
4606
4607        // Apply layout direction to the new Drawables if needed
4608        final int layoutDirection = getLayoutDirection();
4609        if (track != null) {
4610            track.setLayoutDirection(layoutDirection);
4611        }
4612        if (thumb != null) {
4613            thumb.setLayoutDirection(layoutDirection);
4614        }
4615
4616        // Re-apply user/background padding so that scrollbar(s) get added
4617        resolvePadding();
4618    }
4619
4620    /**
4621     * <p>
4622     * Initalizes the scrollability cache if necessary.
4623     * </p>
4624     */
4625    private void initScrollCache() {
4626        if (mScrollCache == null) {
4627            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4628        }
4629    }
4630
4631    private ScrollabilityCache getScrollCache() {
4632        initScrollCache();
4633        return mScrollCache;
4634    }
4635
4636    /**
4637     * Set the position of the vertical scroll bar. Should be one of
4638     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4639     * {@link #SCROLLBAR_POSITION_RIGHT}.
4640     *
4641     * @param position Where the vertical scroll bar should be positioned.
4642     */
4643    public void setVerticalScrollbarPosition(int position) {
4644        if (mVerticalScrollbarPosition != position) {
4645            mVerticalScrollbarPosition = position;
4646            computeOpaqueFlags();
4647            resolvePadding();
4648        }
4649    }
4650
4651    /**
4652     * @return The position where the vertical scroll bar will show, if applicable.
4653     * @see #setVerticalScrollbarPosition(int)
4654     */
4655    public int getVerticalScrollbarPosition() {
4656        return mVerticalScrollbarPosition;
4657    }
4658
4659    ListenerInfo getListenerInfo() {
4660        if (mListenerInfo != null) {
4661            return mListenerInfo;
4662        }
4663        mListenerInfo = new ListenerInfo();
4664        return mListenerInfo;
4665    }
4666
4667    /**
4668     * Register a callback to be invoked when the scroll X or Y positions of
4669     * this view change.
4670     * <p>
4671     * <b>Note:</b> Some views handle scrolling independently from View and may
4672     * have their own separate listeners for scroll-type events. For example,
4673     * {@link android.widget.ListView ListView} allows clients to register an
4674     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
4675     * to listen for changes in list scroll position.
4676     *
4677     * @param l The listener to notify when the scroll X or Y position changes.
4678     * @see android.view.View#getScrollX()
4679     * @see android.view.View#getScrollY()
4680     */
4681    public void setOnScrollChangeListener(OnScrollChangeListener l) {
4682        getListenerInfo().mOnScrollChangeListener = l;
4683    }
4684
4685    /**
4686     * Register a callback to be invoked when focus of this view changed.
4687     *
4688     * @param l The callback that will run.
4689     */
4690    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4691        getListenerInfo().mOnFocusChangeListener = l;
4692    }
4693
4694    /**
4695     * Add a listener that will be called when the bounds of the view change due to
4696     * layout processing.
4697     *
4698     * @param listener The listener that will be called when layout bounds change.
4699     */
4700    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4701        ListenerInfo li = getListenerInfo();
4702        if (li.mOnLayoutChangeListeners == null) {
4703            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4704        }
4705        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4706            li.mOnLayoutChangeListeners.add(listener);
4707        }
4708    }
4709
4710    /**
4711     * Remove a listener for layout changes.
4712     *
4713     * @param listener The listener for layout bounds change.
4714     */
4715    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4716        ListenerInfo li = mListenerInfo;
4717        if (li == null || li.mOnLayoutChangeListeners == null) {
4718            return;
4719        }
4720        li.mOnLayoutChangeListeners.remove(listener);
4721    }
4722
4723    /**
4724     * Add a listener for attach state changes.
4725     *
4726     * This listener will be called whenever this view is attached or detached
4727     * from a window. Remove the listener using
4728     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4729     *
4730     * @param listener Listener to attach
4731     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4732     */
4733    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4734        ListenerInfo li = getListenerInfo();
4735        if (li.mOnAttachStateChangeListeners == null) {
4736            li.mOnAttachStateChangeListeners
4737                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4738        }
4739        li.mOnAttachStateChangeListeners.add(listener);
4740    }
4741
4742    /**
4743     * Remove a listener for attach state changes. The listener will receive no further
4744     * notification of window attach/detach events.
4745     *
4746     * @param listener Listener to remove
4747     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4748     */
4749    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4750        ListenerInfo li = mListenerInfo;
4751        if (li == null || li.mOnAttachStateChangeListeners == null) {
4752            return;
4753        }
4754        li.mOnAttachStateChangeListeners.remove(listener);
4755    }
4756
4757    /**
4758     * Returns the focus-change callback registered for this view.
4759     *
4760     * @return The callback, or null if one is not registered.
4761     */
4762    public OnFocusChangeListener getOnFocusChangeListener() {
4763        ListenerInfo li = mListenerInfo;
4764        return li != null ? li.mOnFocusChangeListener : null;
4765    }
4766
4767    /**
4768     * Register a callback to be invoked when this view is clicked. If this view is not
4769     * clickable, it becomes clickable.
4770     *
4771     * @param l The callback that will run
4772     *
4773     * @see #setClickable(boolean)
4774     */
4775    public void setOnClickListener(@Nullable OnClickListener l) {
4776        if (!isClickable()) {
4777            setClickable(true);
4778        }
4779        getListenerInfo().mOnClickListener = l;
4780    }
4781
4782    /**
4783     * Return whether this view has an attached OnClickListener.  Returns
4784     * true if there is a listener, false if there is none.
4785     */
4786    public boolean hasOnClickListeners() {
4787        ListenerInfo li = mListenerInfo;
4788        return (li != null && li.mOnClickListener != null);
4789    }
4790
4791    /**
4792     * Register a callback to be invoked when this view is clicked and held. If this view is not
4793     * long clickable, it becomes long clickable.
4794     *
4795     * @param l The callback that will run
4796     *
4797     * @see #setLongClickable(boolean)
4798     */
4799    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
4800        if (!isLongClickable()) {
4801            setLongClickable(true);
4802        }
4803        getListenerInfo().mOnLongClickListener = l;
4804    }
4805
4806    /**
4807     * Register a callback to be invoked when the context menu for this view is
4808     * being built. If this view is not long clickable, it becomes long clickable.
4809     *
4810     * @param l The callback that will run
4811     *
4812     */
4813    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4814        if (!isLongClickable()) {
4815            setLongClickable(true);
4816        }
4817        getListenerInfo().mOnCreateContextMenuListener = l;
4818    }
4819
4820    /**
4821     * Call this view's OnClickListener, if it is defined.  Performs all normal
4822     * actions associated with clicking: reporting accessibility event, playing
4823     * a sound, etc.
4824     *
4825     * @return True there was an assigned OnClickListener that was called, false
4826     *         otherwise is returned.
4827     */
4828    public boolean performClick() {
4829        final boolean result;
4830        final ListenerInfo li = mListenerInfo;
4831        if (li != null && li.mOnClickListener != null) {
4832            playSoundEffect(SoundEffectConstants.CLICK);
4833            li.mOnClickListener.onClick(this);
4834            result = true;
4835        } else {
4836            result = false;
4837        }
4838
4839        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4840        return result;
4841    }
4842
4843    /**
4844     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4845     * this only calls the listener, and does not do any associated clicking
4846     * actions like reporting an accessibility event.
4847     *
4848     * @return True there was an assigned OnClickListener that was called, false
4849     *         otherwise is returned.
4850     */
4851    public boolean callOnClick() {
4852        ListenerInfo li = mListenerInfo;
4853        if (li != null && li.mOnClickListener != null) {
4854            li.mOnClickListener.onClick(this);
4855            return true;
4856        }
4857        return false;
4858    }
4859
4860    /**
4861     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4862     * OnLongClickListener did not consume the event.
4863     *
4864     * @return True if one of the above receivers consumed the event, false otherwise.
4865     */
4866    public boolean performLongClick() {
4867        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4868
4869        boolean handled = false;
4870        ListenerInfo li = mListenerInfo;
4871        if (li != null && li.mOnLongClickListener != null) {
4872            handled = li.mOnLongClickListener.onLongClick(View.this);
4873        }
4874        if (!handled) {
4875            handled = showContextMenu();
4876        }
4877        if (handled) {
4878            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4879        }
4880        return handled;
4881    }
4882
4883    /**
4884     * Performs button-related actions during a touch down event.
4885     *
4886     * @param event The event.
4887     * @return True if the down was consumed.
4888     *
4889     * @hide
4890     */
4891    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4892        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
4893            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4894            showContextMenu(event.getX(), event.getY(), event.getMetaState());
4895            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
4896            return true;
4897        }
4898        return false;
4899    }
4900
4901    /**
4902     * Bring up the context menu for this view.
4903     *
4904     * @return Whether a context menu was displayed.
4905     */
4906    public boolean showContextMenu() {
4907        return getParent().showContextMenuForChild(this);
4908    }
4909
4910    /**
4911     * Bring up the context menu for this view, referring to the item under the specified point.
4912     *
4913     * @param x The referenced x coordinate.
4914     * @param y The referenced y coordinate.
4915     * @param metaState The keyboard modifiers that were pressed.
4916     * @return Whether a context menu was displayed.
4917     *
4918     * @hide
4919     */
4920    public boolean showContextMenu(float x, float y, int metaState) {
4921        return showContextMenu();
4922    }
4923
4924    /**
4925     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
4926     *
4927     * @param callback Callback that will control the lifecycle of the action mode
4928     * @return The new action mode if it is started, null otherwise
4929     *
4930     * @see ActionMode
4931     * @see #startActionMode(android.view.ActionMode.Callback, int)
4932     */
4933    public ActionMode startActionMode(ActionMode.Callback callback) {
4934        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
4935    }
4936
4937    /**
4938     * Start an action mode with the given type.
4939     *
4940     * @param callback Callback that will control the lifecycle of the action mode
4941     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
4942     * @return The new action mode if it is started, null otherwise
4943     *
4944     * @see ActionMode
4945     */
4946    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
4947        ViewParent parent = getParent();
4948        if (parent == null) return null;
4949        try {
4950            return parent.startActionModeForChild(this, callback, type);
4951        } catch (AbstractMethodError ame) {
4952            // Older implementations of custom views might not implement this.
4953            return parent.startActionModeForChild(this, callback);
4954        }
4955    }
4956
4957    /**
4958     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
4959     * Context, creating a unique View identifier to retrieve the result.
4960     *
4961     * @param intent The Intent to be started.
4962     * @param requestCode The request code to use.
4963     * @hide
4964     */
4965    public void startActivityForResult(Intent intent, int requestCode) {
4966        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
4967        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
4968    }
4969
4970    /**
4971     * If this View corresponds to the calling who, dispatches the activity result.
4972     * @param who The identifier for the targeted View to receive the result.
4973     * @param requestCode The integer request code originally supplied to
4974     *                    startActivityForResult(), allowing you to identify who this
4975     *                    result came from.
4976     * @param resultCode The integer result code returned by the child activity
4977     *                   through its setResult().
4978     * @param data An Intent, which can return result data to the caller
4979     *               (various data can be attached to Intent "extras").
4980     * @return {@code true} if the activity result was dispatched.
4981     * @hide
4982     */
4983    public boolean dispatchActivityResult(
4984            String who, int requestCode, int resultCode, Intent data) {
4985        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
4986            onActivityResult(requestCode, resultCode, data);
4987            mStartActivityRequestWho = null;
4988            return true;
4989        }
4990        return false;
4991    }
4992
4993    /**
4994     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
4995     *
4996     * @param requestCode The integer request code originally supplied to
4997     *                    startActivityForResult(), allowing you to identify who this
4998     *                    result came from.
4999     * @param resultCode The integer result code returned by the child activity
5000     *                   through its setResult().
5001     * @param data An Intent, which can return result data to the caller
5002     *               (various data can be attached to Intent "extras").
5003     * @hide
5004     */
5005    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5006        // Do nothing.
5007    }
5008
5009    /**
5010     * Register a callback to be invoked when a hardware key is pressed in this view.
5011     * Key presses in software input methods will generally not trigger the methods of
5012     * this listener.
5013     * @param l the key listener to attach to this view
5014     */
5015    public void setOnKeyListener(OnKeyListener l) {
5016        getListenerInfo().mOnKeyListener = l;
5017    }
5018
5019    /**
5020     * Register a callback to be invoked when a touch event is sent to this view.
5021     * @param l the touch listener to attach to this view
5022     */
5023    public void setOnTouchListener(OnTouchListener l) {
5024        getListenerInfo().mOnTouchListener = l;
5025    }
5026
5027    /**
5028     * Register a callback to be invoked when a generic motion event is sent to this view.
5029     * @param l the generic motion listener to attach to this view
5030     */
5031    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5032        getListenerInfo().mOnGenericMotionListener = l;
5033    }
5034
5035    /**
5036     * Register a callback to be invoked when a hover event is sent to this view.
5037     * @param l the hover listener to attach to this view
5038     */
5039    public void setOnHoverListener(OnHoverListener l) {
5040        getListenerInfo().mOnHoverListener = l;
5041    }
5042
5043    /**
5044     * Register a drag event listener callback object for this View. The parameter is
5045     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5046     * View, the system calls the
5047     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5048     * @param l An implementation of {@link android.view.View.OnDragListener}.
5049     */
5050    public void setOnDragListener(OnDragListener l) {
5051        getListenerInfo().mOnDragListener = l;
5052    }
5053
5054    /**
5055     * Give this view focus. This will cause
5056     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5057     *
5058     * Note: this does not check whether this {@link View} should get focus, it just
5059     * gives it focus no matter what.  It should only be called internally by framework
5060     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5061     *
5062     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5063     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5064     *        focus moved when requestFocus() is called. It may not always
5065     *        apply, in which case use the default View.FOCUS_DOWN.
5066     * @param previouslyFocusedRect The rectangle of the view that had focus
5067     *        prior in this View's coordinate system.
5068     */
5069    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5070        if (DBG) {
5071            System.out.println(this + " requestFocus()");
5072        }
5073
5074        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5075            mPrivateFlags |= PFLAG_FOCUSED;
5076
5077            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5078
5079            if (mParent != null) {
5080                mParent.requestChildFocus(this, this);
5081            }
5082
5083            if (mAttachInfo != null) {
5084                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5085            }
5086
5087            onFocusChanged(true, direction, previouslyFocusedRect);
5088            refreshDrawableState();
5089        }
5090    }
5091
5092    /**
5093     * Populates <code>outRect</code> with the hotspot bounds. By default,
5094     * the hotspot bounds are identical to the screen bounds.
5095     *
5096     * @param outRect rect to populate with hotspot bounds
5097     * @hide Only for internal use by views and widgets.
5098     */
5099    public void getHotspotBounds(Rect outRect) {
5100        final Drawable background = getBackground();
5101        if (background != null) {
5102            background.getHotspotBounds(outRect);
5103        } else {
5104            getBoundsOnScreen(outRect);
5105        }
5106    }
5107
5108    /**
5109     * Request that a rectangle of this view be visible on the screen,
5110     * scrolling if necessary just enough.
5111     *
5112     * <p>A View should call this if it maintains some notion of which part
5113     * of its content is interesting.  For example, a text editing view
5114     * should call this when its cursor moves.
5115     *
5116     * @param rectangle The rectangle.
5117     * @return Whether any parent scrolled.
5118     */
5119    public boolean requestRectangleOnScreen(Rect rectangle) {
5120        return requestRectangleOnScreen(rectangle, false);
5121    }
5122
5123    /**
5124     * Request that a rectangle of this view be visible on the screen,
5125     * scrolling if necessary just enough.
5126     *
5127     * <p>A View should call this if it maintains some notion of which part
5128     * of its content is interesting.  For example, a text editing view
5129     * should call this when its cursor moves.
5130     *
5131     * <p>When <code>immediate</code> is set to true, scrolling will not be
5132     * animated.
5133     *
5134     * @param rectangle The rectangle.
5135     * @param immediate True to forbid animated scrolling, false otherwise
5136     * @return Whether any parent scrolled.
5137     */
5138    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5139        if (mParent == null) {
5140            return false;
5141        }
5142
5143        View child = this;
5144
5145        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5146        position.set(rectangle);
5147
5148        ViewParent parent = mParent;
5149        boolean scrolled = false;
5150        while (parent != null) {
5151            rectangle.set((int) position.left, (int) position.top,
5152                    (int) position.right, (int) position.bottom);
5153
5154            scrolled |= parent.requestChildRectangleOnScreen(child,
5155                    rectangle, immediate);
5156
5157            if (!child.hasIdentityMatrix()) {
5158                child.getMatrix().mapRect(position);
5159            }
5160
5161            position.offset(child.mLeft, child.mTop);
5162
5163            if (!(parent instanceof View)) {
5164                break;
5165            }
5166
5167            View parentView = (View) parent;
5168
5169            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5170
5171            child = parentView;
5172            parent = child.getParent();
5173        }
5174
5175        return scrolled;
5176    }
5177
5178    /**
5179     * Called when this view wants to give up focus. If focus is cleared
5180     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5181     * <p>
5182     * <strong>Note:</strong> When a View clears focus the framework is trying
5183     * to give focus to the first focusable View from the top. Hence, if this
5184     * View is the first from the top that can take focus, then all callbacks
5185     * related to clearing focus will be invoked after which the framework will
5186     * give focus to this view.
5187     * </p>
5188     */
5189    public void clearFocus() {
5190        if (DBG) {
5191            System.out.println(this + " clearFocus()");
5192        }
5193
5194        clearFocusInternal(null, true, true);
5195    }
5196
5197    /**
5198     * Clears focus from the view, optionally propagating the change up through
5199     * the parent hierarchy and requesting that the root view place new focus.
5200     *
5201     * @param propagate whether to propagate the change up through the parent
5202     *            hierarchy
5203     * @param refocus when propagate is true, specifies whether to request the
5204     *            root view place new focus
5205     */
5206    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5207        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5208            mPrivateFlags &= ~PFLAG_FOCUSED;
5209
5210            if (propagate && mParent != null) {
5211                mParent.clearChildFocus(this);
5212            }
5213
5214            onFocusChanged(false, 0, null);
5215            refreshDrawableState();
5216
5217            if (propagate && (!refocus || !rootViewRequestFocus())) {
5218                notifyGlobalFocusCleared(this);
5219            }
5220        }
5221    }
5222
5223    void notifyGlobalFocusCleared(View oldFocus) {
5224        if (oldFocus != null && mAttachInfo != null) {
5225            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5226        }
5227    }
5228
5229    boolean rootViewRequestFocus() {
5230        final View root = getRootView();
5231        return root != null && root.requestFocus();
5232    }
5233
5234    /**
5235     * Called internally by the view system when a new view is getting focus.
5236     * This is what clears the old focus.
5237     * <p>
5238     * <b>NOTE:</b> The parent view's focused child must be updated manually
5239     * after calling this method. Otherwise, the view hierarchy may be left in
5240     * an inconstent state.
5241     */
5242    void unFocus(View focused) {
5243        if (DBG) {
5244            System.out.println(this + " unFocus()");
5245        }
5246
5247        clearFocusInternal(focused, false, false);
5248    }
5249
5250    /**
5251     * Returns true if this view has focus itself, or is the ancestor of the
5252     * view that has focus.
5253     *
5254     * @return True if this view has or contains focus, false otherwise.
5255     */
5256    @ViewDebug.ExportedProperty(category = "focus")
5257    public boolean hasFocus() {
5258        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5259    }
5260
5261    /**
5262     * Returns true if this view is focusable or if it contains a reachable View
5263     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5264     * is a View whose parents do not block descendants focus.
5265     *
5266     * Only {@link #VISIBLE} views are considered focusable.
5267     *
5268     * @return True if the view is focusable or if the view contains a focusable
5269     *         View, false otherwise.
5270     *
5271     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5272     * @see ViewGroup#getTouchscreenBlocksFocus()
5273     */
5274    public boolean hasFocusable() {
5275        if (!isFocusableInTouchMode()) {
5276            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5277                final ViewGroup g = (ViewGroup) p;
5278                if (g.shouldBlockFocusForTouchscreen()) {
5279                    return false;
5280                }
5281            }
5282        }
5283        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5284    }
5285
5286    /**
5287     * Called by the view system when the focus state of this view changes.
5288     * When the focus change event is caused by directional navigation, direction
5289     * and previouslyFocusedRect provide insight into where the focus is coming from.
5290     * When overriding, be sure to call up through to the super class so that
5291     * the standard focus handling will occur.
5292     *
5293     * @param gainFocus True if the View has focus; false otherwise.
5294     * @param direction The direction focus has moved when requestFocus()
5295     *                  is called to give this view focus. Values are
5296     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5297     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5298     *                  It may not always apply, in which case use the default.
5299     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5300     *        system, of the previously focused view.  If applicable, this will be
5301     *        passed in as finer grained information about where the focus is coming
5302     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5303     */
5304    @CallSuper
5305    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5306            @Nullable Rect previouslyFocusedRect) {
5307        if (gainFocus) {
5308            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5309        } else {
5310            notifyViewAccessibilityStateChangedIfNeeded(
5311                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5312        }
5313
5314        InputMethodManager imm = InputMethodManager.peekInstance();
5315        if (!gainFocus) {
5316            if (isPressed()) {
5317                setPressed(false);
5318            }
5319            if (imm != null && mAttachInfo != null
5320                    && mAttachInfo.mHasWindowFocus) {
5321                imm.focusOut(this);
5322            }
5323            onFocusLost();
5324        } else if (imm != null && mAttachInfo != null
5325                && mAttachInfo.mHasWindowFocus) {
5326            imm.focusIn(this);
5327        }
5328
5329        invalidate(true);
5330        ListenerInfo li = mListenerInfo;
5331        if (li != null && li.mOnFocusChangeListener != null) {
5332            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5333        }
5334
5335        if (mAttachInfo != null) {
5336            mAttachInfo.mKeyDispatchState.reset(this);
5337        }
5338    }
5339
5340    /**
5341     * Sends an accessibility event of the given type. If accessibility is
5342     * not enabled this method has no effect. The default implementation calls
5343     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5344     * to populate information about the event source (this View), then calls
5345     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5346     * populate the text content of the event source including its descendants,
5347     * and last calls
5348     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5349     * on its parent to request sending of the event to interested parties.
5350     * <p>
5351     * If an {@link AccessibilityDelegate} has been specified via calling
5352     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5353     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5354     * responsible for handling this call.
5355     * </p>
5356     *
5357     * @param eventType The type of the event to send, as defined by several types from
5358     * {@link android.view.accessibility.AccessibilityEvent}, such as
5359     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5360     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5361     *
5362     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5363     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5364     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5365     * @see AccessibilityDelegate
5366     */
5367    public void sendAccessibilityEvent(int eventType) {
5368        if (mAccessibilityDelegate != null) {
5369            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5370        } else {
5371            sendAccessibilityEventInternal(eventType);
5372        }
5373    }
5374
5375    /**
5376     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5377     * {@link AccessibilityEvent} to make an announcement which is related to some
5378     * sort of a context change for which none of the events representing UI transitions
5379     * is a good fit. For example, announcing a new page in a book. If accessibility
5380     * is not enabled this method does nothing.
5381     *
5382     * @param text The announcement text.
5383     */
5384    public void announceForAccessibility(CharSequence text) {
5385        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5386            AccessibilityEvent event = AccessibilityEvent.obtain(
5387                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5388            onInitializeAccessibilityEvent(event);
5389            event.getText().add(text);
5390            event.setContentDescription(null);
5391            mParent.requestSendAccessibilityEvent(this, event);
5392        }
5393    }
5394
5395    /**
5396     * @see #sendAccessibilityEvent(int)
5397     *
5398     * Note: Called from the default {@link AccessibilityDelegate}.
5399     *
5400     * @hide
5401     */
5402    public void sendAccessibilityEventInternal(int eventType) {
5403        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5404            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5405        }
5406    }
5407
5408    /**
5409     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5410     * takes as an argument an empty {@link AccessibilityEvent} and does not
5411     * perform a check whether accessibility is enabled.
5412     * <p>
5413     * If an {@link AccessibilityDelegate} has been specified via calling
5414     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5415     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5416     * is responsible for handling this call.
5417     * </p>
5418     *
5419     * @param event The event to send.
5420     *
5421     * @see #sendAccessibilityEvent(int)
5422     */
5423    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5424        if (mAccessibilityDelegate != null) {
5425            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5426        } else {
5427            sendAccessibilityEventUncheckedInternal(event);
5428        }
5429    }
5430
5431    /**
5432     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5433     *
5434     * Note: Called from the default {@link AccessibilityDelegate}.
5435     *
5436     * @hide
5437     */
5438    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5439        if (!isShown()) {
5440            return;
5441        }
5442        onInitializeAccessibilityEvent(event);
5443        // Only a subset of accessibility events populates text content.
5444        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5445            dispatchPopulateAccessibilityEvent(event);
5446        }
5447        // In the beginning we called #isShown(), so we know that getParent() is not null.
5448        getParent().requestSendAccessibilityEvent(this, event);
5449    }
5450
5451    /**
5452     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5453     * to its children for adding their text content to the event. Note that the
5454     * event text is populated in a separate dispatch path since we add to the
5455     * event not only the text of the source but also the text of all its descendants.
5456     * A typical implementation will call
5457     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5458     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5459     * on each child. Override this method if custom population of the event text
5460     * content is required.
5461     * <p>
5462     * If an {@link AccessibilityDelegate} has been specified via calling
5463     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5464     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5465     * is responsible for handling this call.
5466     * </p>
5467     * <p>
5468     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5469     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5470     * </p>
5471     *
5472     * @param event The event.
5473     *
5474     * @return True if the event population was completed.
5475     */
5476    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5477        if (mAccessibilityDelegate != null) {
5478            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5479        } else {
5480            return dispatchPopulateAccessibilityEventInternal(event);
5481        }
5482    }
5483
5484    /**
5485     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5486     *
5487     * Note: Called from the default {@link AccessibilityDelegate}.
5488     *
5489     * @hide
5490     */
5491    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5492        onPopulateAccessibilityEvent(event);
5493        return false;
5494    }
5495
5496    /**
5497     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5498     * giving a chance to this View to populate the accessibility event with its
5499     * text content. While this method is free to modify event
5500     * attributes other than text content, doing so should normally be performed in
5501     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5502     * <p>
5503     * Example: Adding formatted date string to an accessibility event in addition
5504     *          to the text added by the super implementation:
5505     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5506     *     super.onPopulateAccessibilityEvent(event);
5507     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5508     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5509     *         mCurrentDate.getTimeInMillis(), flags);
5510     *     event.getText().add(selectedDateUtterance);
5511     * }</pre>
5512     * <p>
5513     * If an {@link AccessibilityDelegate} has been specified via calling
5514     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5515     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5516     * is responsible for handling this call.
5517     * </p>
5518     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5519     * information to the event, in case the default implementation has basic information to add.
5520     * </p>
5521     *
5522     * @param event The accessibility event which to populate.
5523     *
5524     * @see #sendAccessibilityEvent(int)
5525     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5526     */
5527    @CallSuper
5528    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5529        if (mAccessibilityDelegate != null) {
5530            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5531        } else {
5532            onPopulateAccessibilityEventInternal(event);
5533        }
5534    }
5535
5536    /**
5537     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5538     *
5539     * Note: Called from the default {@link AccessibilityDelegate}.
5540     *
5541     * @hide
5542     */
5543    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5544    }
5545
5546    /**
5547     * Initializes an {@link AccessibilityEvent} with information about
5548     * this View which is the event source. In other words, the source of
5549     * an accessibility event is the view whose state change triggered firing
5550     * the event.
5551     * <p>
5552     * Example: Setting the password property of an event in addition
5553     *          to properties set by the super implementation:
5554     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5555     *     super.onInitializeAccessibilityEvent(event);
5556     *     event.setPassword(true);
5557     * }</pre>
5558     * <p>
5559     * If an {@link AccessibilityDelegate} has been specified via calling
5560     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5561     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5562     * is responsible for handling this call.
5563     * </p>
5564     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5565     * information to the event, in case the default implementation has basic information to add.
5566     * </p>
5567     * @param event The event to initialize.
5568     *
5569     * @see #sendAccessibilityEvent(int)
5570     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5571     */
5572    @CallSuper
5573    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5574        if (mAccessibilityDelegate != null) {
5575            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5576        } else {
5577            onInitializeAccessibilityEventInternal(event);
5578        }
5579    }
5580
5581    /**
5582     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5583     *
5584     * Note: Called from the default {@link AccessibilityDelegate}.
5585     *
5586     * @hide
5587     */
5588    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5589        event.setSource(this);
5590        event.setClassName(getAccessibilityClassName());
5591        event.setPackageName(getContext().getPackageName());
5592        event.setEnabled(isEnabled());
5593        event.setContentDescription(mContentDescription);
5594
5595        switch (event.getEventType()) {
5596            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5597                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5598                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5599                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5600                event.setItemCount(focusablesTempList.size());
5601                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5602                if (mAttachInfo != null) {
5603                    focusablesTempList.clear();
5604                }
5605            } break;
5606            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5607                CharSequence text = getIterableTextForAccessibility();
5608                if (text != null && text.length() > 0) {
5609                    event.setFromIndex(getAccessibilitySelectionStart());
5610                    event.setToIndex(getAccessibilitySelectionEnd());
5611                    event.setItemCount(text.length());
5612                }
5613            } break;
5614        }
5615    }
5616
5617    /**
5618     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5619     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5620     * This method is responsible for obtaining an accessibility node info from a
5621     * pool of reusable instances and calling
5622     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5623     * initialize the former.
5624     * <p>
5625     * Note: The client is responsible for recycling the obtained instance by calling
5626     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5627     * </p>
5628     *
5629     * @return A populated {@link AccessibilityNodeInfo}.
5630     *
5631     * @see AccessibilityNodeInfo
5632     */
5633    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5634        if (mAccessibilityDelegate != null) {
5635            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5636        } else {
5637            return createAccessibilityNodeInfoInternal();
5638        }
5639    }
5640
5641    /**
5642     * @see #createAccessibilityNodeInfo()
5643     *
5644     * @hide
5645     */
5646    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5647        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5648        if (provider != null) {
5649            return provider.createAccessibilityNodeInfo(View.NO_ID);
5650        } else {
5651            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5652            onInitializeAccessibilityNodeInfo(info);
5653            return info;
5654        }
5655    }
5656
5657    /**
5658     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5659     * The base implementation sets:
5660     * <ul>
5661     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5662     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5663     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5664     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5665     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5666     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5667     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5668     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5669     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5670     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5671     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5672     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5673     * </ul>
5674     * <p>
5675     * Subclasses should override this method, call the super implementation,
5676     * and set additional attributes.
5677     * </p>
5678     * <p>
5679     * If an {@link AccessibilityDelegate} has been specified via calling
5680     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5681     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5682     * is responsible for handling this call.
5683     * </p>
5684     *
5685     * @param info The instance to initialize.
5686     */
5687    @CallSuper
5688    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5689        if (mAccessibilityDelegate != null) {
5690            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5691        } else {
5692            onInitializeAccessibilityNodeInfoInternal(info);
5693        }
5694    }
5695
5696    /**
5697     * Gets the location of this view in screen coordinates.
5698     *
5699     * @param outRect The output location
5700     * @hide
5701     */
5702    public void getBoundsOnScreen(Rect outRect) {
5703        getBoundsOnScreen(outRect, false);
5704    }
5705
5706    /**
5707     * Gets the location of this view in screen coordinates.
5708     *
5709     * @param outRect The output location
5710     * @param clipToParent Whether to clip child bounds to the parent ones.
5711     * @hide
5712     */
5713    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
5714        if (mAttachInfo == null) {
5715            return;
5716        }
5717
5718        RectF position = mAttachInfo.mTmpTransformRect;
5719        position.set(0, 0, mRight - mLeft, mBottom - mTop);
5720
5721        if (!hasIdentityMatrix()) {
5722            getMatrix().mapRect(position);
5723        }
5724
5725        position.offset(mLeft, mTop);
5726
5727        ViewParent parent = mParent;
5728        while (parent instanceof View) {
5729            View parentView = (View) parent;
5730
5731            position.offset(-parentView.mScrollX, -parentView.mScrollY);
5732
5733            if (clipToParent) {
5734                position.left = Math.max(position.left, 0);
5735                position.top = Math.max(position.top, 0);
5736                position.right = Math.min(position.right, parentView.getWidth());
5737                position.bottom = Math.min(position.bottom, parentView.getHeight());
5738            }
5739
5740            if (!parentView.hasIdentityMatrix()) {
5741                parentView.getMatrix().mapRect(position);
5742            }
5743
5744            position.offset(parentView.mLeft, parentView.mTop);
5745
5746            parent = parentView.mParent;
5747        }
5748
5749        if (parent instanceof ViewRootImpl) {
5750            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5751            position.offset(0, -viewRootImpl.mCurScrollY);
5752        }
5753
5754        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5755
5756        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5757                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5758    }
5759
5760    /**
5761     * Return the class name of this object to be used for accessibility purposes.
5762     * Subclasses should only override this if they are implementing something that
5763     * should be seen as a completely new class of view when used by accessibility,
5764     * unrelated to the class it is deriving from.  This is used to fill in
5765     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
5766     */
5767    public CharSequence getAccessibilityClassName() {
5768        return View.class.getName();
5769    }
5770
5771    /**
5772     * Called when assist structure is being retrieved from a view as part of
5773     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
5774     * @param structure Fill in with structured view data.  The default implementation
5775     * fills in all data that can be inferred from the view itself.
5776     */
5777    public void onProvideAssistStructure(ViewAssistStructure structure) {
5778        final int id = mID;
5779        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
5780                && (id&0x0000ffff) != 0) {
5781            String pkg, type, entry;
5782            try {
5783                final Resources res = getResources();
5784                entry = res.getResourceEntryName(id);
5785                type = res.getResourceTypeName(id);
5786                pkg = res.getResourcePackageName(id);
5787            } catch (Resources.NotFoundException e) {
5788                entry = type = pkg = null;
5789            }
5790            structure.setId(id, pkg, type, entry);
5791        } else {
5792            structure.setId(id, null, null, null);
5793        }
5794        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
5795        structure.setVisibility(getVisibility());
5796        structure.setEnabled(isEnabled());
5797        if (isClickable()) {
5798            structure.setClickable(true);
5799        }
5800        if (isFocusable()) {
5801            structure.setFocusable(true);
5802        }
5803        if (isFocused()) {
5804            structure.setFocused(true);
5805        }
5806        if (isAccessibilityFocused()) {
5807            structure.setAccessibilityFocused(true);
5808        }
5809        if (isSelected()) {
5810            structure.setSelected(true);
5811        }
5812        if (isActivated()) {
5813            structure.setActivated(true);
5814        }
5815        if (isLongClickable()) {
5816            structure.setLongClickable(true);
5817        }
5818        if (this instanceof Checkable) {
5819            structure.setCheckable(true);
5820            if (((Checkable)this).isChecked()) {
5821                structure.setChecked(true);
5822            }
5823        }
5824        structure.setClassName(getAccessibilityClassName().toString());
5825        structure.setContentDescription(getContentDescription());
5826    }
5827
5828    /**
5829     * Called when assist structure is being retrieved from a view as part of
5830     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
5831     * generate additional virtual structure under this view.  The defaullt implementation
5832     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
5833     * view's virtual accessibility nodes, if any.  You can override this for a more
5834     * optimal implementation providing this data.
5835     */
5836    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
5837        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5838        if (provider != null) {
5839            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
5840            Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
5841            structure.setChildCount(1);
5842            ViewAssistStructure root = structure.newChild(0);
5843            populateVirtualAssistStructure(root, provider, info);
5844            info.recycle();
5845        }
5846    }
5847
5848    private void populateVirtualAssistStructure(ViewAssistStructure structure,
5849            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
5850        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
5851                null, null, null);
5852        Rect rect = structure.getTempRect();
5853        info.getBoundsInParent(rect);
5854        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
5855        structure.setVisibility(VISIBLE);
5856        structure.setEnabled(info.isEnabled());
5857        if (info.isClickable()) {
5858            structure.setClickable(true);
5859        }
5860        if (info.isFocusable()) {
5861            structure.setFocusable(true);
5862        }
5863        if (info.isFocused()) {
5864            structure.setFocused(true);
5865        }
5866        if (info.isAccessibilityFocused()) {
5867            structure.setAccessibilityFocused(true);
5868        }
5869        if (info.isSelected()) {
5870            structure.setSelected(true);
5871        }
5872        if (info.isLongClickable()) {
5873            structure.setLongClickable(true);
5874        }
5875        if (info.isCheckable()) {
5876            structure.setCheckable(true);
5877            if (info.isChecked()) {
5878                structure.setChecked(true);
5879            }
5880        }
5881        CharSequence cname = info.getClassName();
5882        structure.setClassName(cname != null ? cname.toString() : null);
5883        structure.setContentDescription(info.getContentDescription());
5884        Log.i("View", "vassist " + cname + " @ " + rect.toShortString()
5885                + " text=" + info.getText() + " cd=" + info.getContentDescription());
5886        if (info.getText() != null || info.getError() != null) {
5887            structure.setText(info.getText(), info.getTextSelectionStart(),
5888                    info.getTextSelectionEnd());
5889        }
5890        final int NCHILDREN = info.getChildCount();
5891        if (NCHILDREN > 0) {
5892            structure.setChildCount(NCHILDREN);
5893            for (int i=0; i<NCHILDREN; i++) {
5894                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
5895                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
5896                ViewAssistStructure child = structure.newChild(i);
5897                populateVirtualAssistStructure(child, provider, cinfo);
5898                cinfo.recycle();
5899            }
5900        }
5901    }
5902
5903    /**
5904     * Dispatch creation of {@link ViewAssistStructure} down the hierarchy.  The default
5905     * implementation calls {@link #onProvideAssistStructure} and
5906     * {@link #onProvideVirtualAssistStructure}.
5907     */
5908    public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
5909        if (!isAssistBlocked()) {
5910            onProvideAssistStructure(structure);
5911            onProvideVirtualAssistStructure(structure);
5912        } else {
5913            structure.setClassName(getAccessibilityClassName().toString());
5914            structure.setAssistBlocked(true);
5915        }
5916    }
5917
5918    /**
5919     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5920     *
5921     * Note: Called from the default {@link AccessibilityDelegate}.
5922     *
5923     * @hide
5924     */
5925    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5926        Rect bounds = mAttachInfo.mTmpInvalRect;
5927
5928        getDrawingRect(bounds);
5929        info.setBoundsInParent(bounds);
5930
5931        getBoundsOnScreen(bounds, true);
5932        info.setBoundsInScreen(bounds);
5933
5934        ViewParent parent = getParentForAccessibility();
5935        if (parent instanceof View) {
5936            info.setParent((View) parent);
5937        }
5938
5939        if (mID != View.NO_ID) {
5940            View rootView = getRootView();
5941            if (rootView == null) {
5942                rootView = this;
5943            }
5944
5945            View label = rootView.findLabelForView(this, mID);
5946            if (label != null) {
5947                info.setLabeledBy(label);
5948            }
5949
5950            if ((mAttachInfo.mAccessibilityFetchFlags
5951                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5952                    && Resources.resourceHasPackage(mID)) {
5953                try {
5954                    String viewId = getResources().getResourceName(mID);
5955                    info.setViewIdResourceName(viewId);
5956                } catch (Resources.NotFoundException nfe) {
5957                    /* ignore */
5958                }
5959            }
5960        }
5961
5962        if (mLabelForId != View.NO_ID) {
5963            View rootView = getRootView();
5964            if (rootView == null) {
5965                rootView = this;
5966            }
5967            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5968            if (labeled != null) {
5969                info.setLabelFor(labeled);
5970            }
5971        }
5972
5973        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
5974            View rootView = getRootView();
5975            if (rootView == null) {
5976                rootView = this;
5977            }
5978            View next = rootView.findViewInsideOutShouldExist(this,
5979                    mAccessibilityTraversalBeforeId);
5980            if (next != null) {
5981                info.setTraversalBefore(next);
5982            }
5983        }
5984
5985        if (mAccessibilityTraversalAfterId != View.NO_ID) {
5986            View rootView = getRootView();
5987            if (rootView == null) {
5988                rootView = this;
5989            }
5990            View next = rootView.findViewInsideOutShouldExist(this,
5991                    mAccessibilityTraversalAfterId);
5992            if (next != null) {
5993                info.setTraversalAfter(next);
5994            }
5995        }
5996
5997        info.setVisibleToUser(isVisibleToUser());
5998
5999        info.setPackageName(mContext.getPackageName());
6000        info.setClassName(getAccessibilityClassName());
6001        info.setContentDescription(getContentDescription());
6002
6003        info.setEnabled(isEnabled());
6004        info.setClickable(isClickable());
6005        info.setFocusable(isFocusable());
6006        info.setFocused(isFocused());
6007        info.setAccessibilityFocused(isAccessibilityFocused());
6008        info.setSelected(isSelected());
6009        info.setLongClickable(isLongClickable());
6010        info.setLiveRegion(getAccessibilityLiveRegion());
6011
6012        // TODO: These make sense only if we are in an AdapterView but all
6013        // views can be selected. Maybe from accessibility perspective
6014        // we should report as selectable view in an AdapterView.
6015        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6016        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6017
6018        if (isFocusable()) {
6019            if (isFocused()) {
6020                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6021            } else {
6022                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6023            }
6024        }
6025
6026        if (!isAccessibilityFocused()) {
6027            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6028        } else {
6029            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6030        }
6031
6032        if (isClickable() && isEnabled()) {
6033            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6034        }
6035
6036        if (isLongClickable() && isEnabled()) {
6037            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6038        }
6039
6040        CharSequence text = getIterableTextForAccessibility();
6041        if (text != null && text.length() > 0) {
6042            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6043
6044            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6045            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6046            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6047            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6048                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6049                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6050        }
6051
6052        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6053    }
6054
6055    private View findLabelForView(View view, int labeledId) {
6056        if (mMatchLabelForPredicate == null) {
6057            mMatchLabelForPredicate = new MatchLabelForPredicate();
6058        }
6059        mMatchLabelForPredicate.mLabeledId = labeledId;
6060        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6061    }
6062
6063    /**
6064     * Computes whether this view is visible to the user. Such a view is
6065     * attached, visible, all its predecessors are visible, it is not clipped
6066     * entirely by its predecessors, and has an alpha greater than zero.
6067     *
6068     * @return Whether the view is visible on the screen.
6069     *
6070     * @hide
6071     */
6072    protected boolean isVisibleToUser() {
6073        return isVisibleToUser(null);
6074    }
6075
6076    /**
6077     * Computes whether the given portion of this view is visible to the user.
6078     * Such a view is attached, visible, all its predecessors are visible,
6079     * has an alpha greater than zero, and the specified portion is not
6080     * clipped entirely by its predecessors.
6081     *
6082     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6083     *                    <code>null</code>, and the entire view will be tested in this case.
6084     *                    When <code>true</code> is returned by the function, the actual visible
6085     *                    region will be stored in this parameter; that is, if boundInView is fully
6086     *                    contained within the view, no modification will be made, otherwise regions
6087     *                    outside of the visible area of the view will be clipped.
6088     *
6089     * @return Whether the specified portion of the view is visible on the screen.
6090     *
6091     * @hide
6092     */
6093    protected boolean isVisibleToUser(Rect boundInView) {
6094        if (mAttachInfo != null) {
6095            // Attached to invisible window means this view is not visible.
6096            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6097                return false;
6098            }
6099            // An invisible predecessor or one with alpha zero means
6100            // that this view is not visible to the user.
6101            Object current = this;
6102            while (current instanceof View) {
6103                View view = (View) current;
6104                // We have attach info so this view is attached and there is no
6105                // need to check whether we reach to ViewRootImpl on the way up.
6106                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6107                        view.getVisibility() != VISIBLE) {
6108                    return false;
6109                }
6110                current = view.mParent;
6111            }
6112            // Check if the view is entirely covered by its predecessors.
6113            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6114            Point offset = mAttachInfo.mPoint;
6115            if (!getGlobalVisibleRect(visibleRect, offset)) {
6116                return false;
6117            }
6118            // Check if the visible portion intersects the rectangle of interest.
6119            if (boundInView != null) {
6120                visibleRect.offset(-offset.x, -offset.y);
6121                return boundInView.intersect(visibleRect);
6122            }
6123            return true;
6124        }
6125        return false;
6126    }
6127
6128    /**
6129     * Returns the delegate for implementing accessibility support via
6130     * composition. For more details see {@link AccessibilityDelegate}.
6131     *
6132     * @return The delegate, or null if none set.
6133     *
6134     * @hide
6135     */
6136    public AccessibilityDelegate getAccessibilityDelegate() {
6137        return mAccessibilityDelegate;
6138    }
6139
6140    /**
6141     * Sets a delegate for implementing accessibility support via composition as
6142     * opposed to inheritance. The delegate's primary use is for implementing
6143     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6144     *
6145     * @param delegate The delegate instance.
6146     *
6147     * @see AccessibilityDelegate
6148     */
6149    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6150        mAccessibilityDelegate = delegate;
6151    }
6152
6153    /**
6154     * Gets the provider for managing a virtual view hierarchy rooted at this View
6155     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6156     * that explore the window content.
6157     * <p>
6158     * If this method returns an instance, this instance is responsible for managing
6159     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6160     * View including the one representing the View itself. Similarly the returned
6161     * instance is responsible for performing accessibility actions on any virtual
6162     * view or the root view itself.
6163     * </p>
6164     * <p>
6165     * If an {@link AccessibilityDelegate} has been specified via calling
6166     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6167     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6168     * is responsible for handling this call.
6169     * </p>
6170     *
6171     * @return The provider.
6172     *
6173     * @see AccessibilityNodeProvider
6174     */
6175    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6176        if (mAccessibilityDelegate != null) {
6177            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6178        } else {
6179            return null;
6180        }
6181    }
6182
6183    /**
6184     * Gets the unique identifier of this view on the screen for accessibility purposes.
6185     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6186     *
6187     * @return The view accessibility id.
6188     *
6189     * @hide
6190     */
6191    public int getAccessibilityViewId() {
6192        if (mAccessibilityViewId == NO_ID) {
6193            mAccessibilityViewId = sNextAccessibilityViewId++;
6194        }
6195        return mAccessibilityViewId;
6196    }
6197
6198    /**
6199     * Gets the unique identifier of the window in which this View reseides.
6200     *
6201     * @return The window accessibility id.
6202     *
6203     * @hide
6204     */
6205    public int getAccessibilityWindowId() {
6206        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6207                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6208    }
6209
6210    /**
6211     * Gets the {@link View} description. It briefly describes the view and is
6212     * primarily used for accessibility support. Set this property to enable
6213     * better accessibility support for your application. This is especially
6214     * true for views that do not have textual representation (For example,
6215     * ImageButton).
6216     *
6217     * @return The content description.
6218     *
6219     * @attr ref android.R.styleable#View_contentDescription
6220     */
6221    @ViewDebug.ExportedProperty(category = "accessibility")
6222    public CharSequence getContentDescription() {
6223        return mContentDescription;
6224    }
6225
6226    /**
6227     * Sets the {@link View} description. It briefly describes the view and is
6228     * primarily used for accessibility support. Set this property to enable
6229     * better accessibility support for your application. This is especially
6230     * true for views that do not have textual representation (For example,
6231     * ImageButton).
6232     *
6233     * @param contentDescription The content description.
6234     *
6235     * @attr ref android.R.styleable#View_contentDescription
6236     */
6237    @RemotableViewMethod
6238    public void setContentDescription(CharSequence contentDescription) {
6239        if (mContentDescription == null) {
6240            if (contentDescription == null) {
6241                return;
6242            }
6243        } else if (mContentDescription.equals(contentDescription)) {
6244            return;
6245        }
6246        mContentDescription = contentDescription;
6247        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6248        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6249            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6250            notifySubtreeAccessibilityStateChangedIfNeeded();
6251        } else {
6252            notifyViewAccessibilityStateChangedIfNeeded(
6253                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6254        }
6255    }
6256
6257    /**
6258     * Sets the id of a view before which this one is visited in accessibility traversal.
6259     * A screen-reader must visit the content of this view before the content of the one
6260     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6261     * will traverse the entire content of B before traversing the entire content of A,
6262     * regardles of what traversal strategy it is using.
6263     * <p>
6264     * Views that do not have specified before/after relationships are traversed in order
6265     * determined by the screen-reader.
6266     * </p>
6267     * <p>
6268     * Setting that this view is before a view that is not important for accessibility
6269     * or if this view is not important for accessibility will have no effect as the
6270     * screen-reader is not aware of unimportant views.
6271     * </p>
6272     *
6273     * @param beforeId The id of a view this one precedes in accessibility traversal.
6274     *
6275     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6276     *
6277     * @see #setImportantForAccessibility(int)
6278     */
6279    @RemotableViewMethod
6280    public void setAccessibilityTraversalBefore(int beforeId) {
6281        if (mAccessibilityTraversalBeforeId == beforeId) {
6282            return;
6283        }
6284        mAccessibilityTraversalBeforeId = beforeId;
6285        notifyViewAccessibilityStateChangedIfNeeded(
6286                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6287    }
6288
6289    /**
6290     * Gets the id of a view before which this one is visited in accessibility traversal.
6291     *
6292     * @return The id of a view this one precedes in accessibility traversal if
6293     *         specified, otherwise {@link #NO_ID}.
6294     *
6295     * @see #setAccessibilityTraversalBefore(int)
6296     */
6297    public int getAccessibilityTraversalBefore() {
6298        return mAccessibilityTraversalBeforeId;
6299    }
6300
6301    /**
6302     * Sets the id of a view after which this one is visited in accessibility traversal.
6303     * A screen-reader must visit the content of the other view before the content of this
6304     * one. For example, if view B is set to be after view A, then a screen-reader
6305     * will traverse the entire content of A before traversing the entire content of B,
6306     * regardles of what traversal strategy it is using.
6307     * <p>
6308     * Views that do not have specified before/after relationships are traversed in order
6309     * determined by the screen-reader.
6310     * </p>
6311     * <p>
6312     * Setting that this view is after a view that is not important for accessibility
6313     * or if this view is not important for accessibility will have no effect as the
6314     * screen-reader is not aware of unimportant views.
6315     * </p>
6316     *
6317     * @param afterId The id of a view this one succedees in accessibility traversal.
6318     *
6319     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6320     *
6321     * @see #setImportantForAccessibility(int)
6322     */
6323    @RemotableViewMethod
6324    public void setAccessibilityTraversalAfter(int afterId) {
6325        if (mAccessibilityTraversalAfterId == afterId) {
6326            return;
6327        }
6328        mAccessibilityTraversalAfterId = afterId;
6329        notifyViewAccessibilityStateChangedIfNeeded(
6330                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6331    }
6332
6333    /**
6334     * Gets the id of a view after which this one is visited in accessibility traversal.
6335     *
6336     * @return The id of a view this one succeedes in accessibility traversal if
6337     *         specified, otherwise {@link #NO_ID}.
6338     *
6339     * @see #setAccessibilityTraversalAfter(int)
6340     */
6341    public int getAccessibilityTraversalAfter() {
6342        return mAccessibilityTraversalAfterId;
6343    }
6344
6345    /**
6346     * Gets the id of a view for which this view serves as a label for
6347     * accessibility purposes.
6348     *
6349     * @return The labeled view id.
6350     */
6351    @ViewDebug.ExportedProperty(category = "accessibility")
6352    public int getLabelFor() {
6353        return mLabelForId;
6354    }
6355
6356    /**
6357     * Sets the id of a view for which this view serves as a label for
6358     * accessibility purposes.
6359     *
6360     * @param id The labeled view id.
6361     */
6362    @RemotableViewMethod
6363    public void setLabelFor(@IdRes int id) {
6364        if (mLabelForId == id) {
6365            return;
6366        }
6367        mLabelForId = id;
6368        if (mLabelForId != View.NO_ID
6369                && mID == View.NO_ID) {
6370            mID = generateViewId();
6371        }
6372        notifyViewAccessibilityStateChangedIfNeeded(
6373                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6374    }
6375
6376    /**
6377     * Invoked whenever this view loses focus, either by losing window focus or by losing
6378     * focus within its window. This method can be used to clear any state tied to the
6379     * focus. For instance, if a button is held pressed with the trackball and the window
6380     * loses focus, this method can be used to cancel the press.
6381     *
6382     * Subclasses of View overriding this method should always call super.onFocusLost().
6383     *
6384     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6385     * @see #onWindowFocusChanged(boolean)
6386     *
6387     * @hide pending API council approval
6388     */
6389    @CallSuper
6390    protected void onFocusLost() {
6391        resetPressedState();
6392    }
6393
6394    private void resetPressedState() {
6395        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6396            return;
6397        }
6398
6399        if (isPressed()) {
6400            setPressed(false);
6401
6402            if (!mHasPerformedLongPress) {
6403                removeLongPressCallback();
6404            }
6405        }
6406    }
6407
6408    /**
6409     * Returns true if this view has focus
6410     *
6411     * @return True if this view has focus, false otherwise.
6412     */
6413    @ViewDebug.ExportedProperty(category = "focus")
6414    public boolean isFocused() {
6415        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6416    }
6417
6418    /**
6419     * Find the view in the hierarchy rooted at this view that currently has
6420     * focus.
6421     *
6422     * @return The view that currently has focus, or null if no focused view can
6423     *         be found.
6424     */
6425    public View findFocus() {
6426        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6427    }
6428
6429    /**
6430     * Indicates whether this view is one of the set of scrollable containers in
6431     * its window.
6432     *
6433     * @return whether this view is one of the set of scrollable containers in
6434     * its window
6435     *
6436     * @attr ref android.R.styleable#View_isScrollContainer
6437     */
6438    public boolean isScrollContainer() {
6439        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6440    }
6441
6442    /**
6443     * Change whether this view is one of the set of scrollable containers in
6444     * its window.  This will be used to determine whether the window can
6445     * resize or must pan when a soft input area is open -- scrollable
6446     * containers allow the window to use resize mode since the container
6447     * will appropriately shrink.
6448     *
6449     * @attr ref android.R.styleable#View_isScrollContainer
6450     */
6451    public void setScrollContainer(boolean isScrollContainer) {
6452        if (isScrollContainer) {
6453            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6454                mAttachInfo.mScrollContainers.add(this);
6455                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6456            }
6457            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6458        } else {
6459            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6460                mAttachInfo.mScrollContainers.remove(this);
6461            }
6462            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6463        }
6464    }
6465
6466    /**
6467     * Returns the quality of the drawing cache.
6468     *
6469     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6470     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6471     *
6472     * @see #setDrawingCacheQuality(int)
6473     * @see #setDrawingCacheEnabled(boolean)
6474     * @see #isDrawingCacheEnabled()
6475     *
6476     * @attr ref android.R.styleable#View_drawingCacheQuality
6477     */
6478    @DrawingCacheQuality
6479    public int getDrawingCacheQuality() {
6480        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6481    }
6482
6483    /**
6484     * Set the drawing cache quality of this view. This value is used only when the
6485     * drawing cache is enabled
6486     *
6487     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6488     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6489     *
6490     * @see #getDrawingCacheQuality()
6491     * @see #setDrawingCacheEnabled(boolean)
6492     * @see #isDrawingCacheEnabled()
6493     *
6494     * @attr ref android.R.styleable#View_drawingCacheQuality
6495     */
6496    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6497        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6498    }
6499
6500    /**
6501     * Returns whether the screen should remain on, corresponding to the current
6502     * value of {@link #KEEP_SCREEN_ON}.
6503     *
6504     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6505     *
6506     * @see #setKeepScreenOn(boolean)
6507     *
6508     * @attr ref android.R.styleable#View_keepScreenOn
6509     */
6510    public boolean getKeepScreenOn() {
6511        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6512    }
6513
6514    /**
6515     * Controls whether the screen should remain on, modifying the
6516     * value of {@link #KEEP_SCREEN_ON}.
6517     *
6518     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6519     *
6520     * @see #getKeepScreenOn()
6521     *
6522     * @attr ref android.R.styleable#View_keepScreenOn
6523     */
6524    public void setKeepScreenOn(boolean keepScreenOn) {
6525        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6526    }
6527
6528    /**
6529     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6530     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6531     *
6532     * @attr ref android.R.styleable#View_nextFocusLeft
6533     */
6534    public int getNextFocusLeftId() {
6535        return mNextFocusLeftId;
6536    }
6537
6538    /**
6539     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6540     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6541     * decide automatically.
6542     *
6543     * @attr ref android.R.styleable#View_nextFocusLeft
6544     */
6545    public void setNextFocusLeftId(int nextFocusLeftId) {
6546        mNextFocusLeftId = nextFocusLeftId;
6547    }
6548
6549    /**
6550     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6551     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6552     *
6553     * @attr ref android.R.styleable#View_nextFocusRight
6554     */
6555    public int getNextFocusRightId() {
6556        return mNextFocusRightId;
6557    }
6558
6559    /**
6560     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6561     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6562     * decide automatically.
6563     *
6564     * @attr ref android.R.styleable#View_nextFocusRight
6565     */
6566    public void setNextFocusRightId(int nextFocusRightId) {
6567        mNextFocusRightId = nextFocusRightId;
6568    }
6569
6570    /**
6571     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6572     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6573     *
6574     * @attr ref android.R.styleable#View_nextFocusUp
6575     */
6576    public int getNextFocusUpId() {
6577        return mNextFocusUpId;
6578    }
6579
6580    /**
6581     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6582     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6583     * decide automatically.
6584     *
6585     * @attr ref android.R.styleable#View_nextFocusUp
6586     */
6587    public void setNextFocusUpId(int nextFocusUpId) {
6588        mNextFocusUpId = nextFocusUpId;
6589    }
6590
6591    /**
6592     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6593     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6594     *
6595     * @attr ref android.R.styleable#View_nextFocusDown
6596     */
6597    public int getNextFocusDownId() {
6598        return mNextFocusDownId;
6599    }
6600
6601    /**
6602     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6603     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6604     * decide automatically.
6605     *
6606     * @attr ref android.R.styleable#View_nextFocusDown
6607     */
6608    public void setNextFocusDownId(int nextFocusDownId) {
6609        mNextFocusDownId = nextFocusDownId;
6610    }
6611
6612    /**
6613     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6614     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6615     *
6616     * @attr ref android.R.styleable#View_nextFocusForward
6617     */
6618    public int getNextFocusForwardId() {
6619        return mNextFocusForwardId;
6620    }
6621
6622    /**
6623     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6624     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6625     * decide automatically.
6626     *
6627     * @attr ref android.R.styleable#View_nextFocusForward
6628     */
6629    public void setNextFocusForwardId(int nextFocusForwardId) {
6630        mNextFocusForwardId = nextFocusForwardId;
6631    }
6632
6633    /**
6634     * Returns the visibility of this view and all of its ancestors
6635     *
6636     * @return True if this view and all of its ancestors are {@link #VISIBLE}
6637     */
6638    public boolean isShown() {
6639        View current = this;
6640        //noinspection ConstantConditions
6641        do {
6642            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6643                return false;
6644            }
6645            ViewParent parent = current.mParent;
6646            if (parent == null) {
6647                return false; // We are not attached to the view root
6648            }
6649            if (!(parent instanceof View)) {
6650                return true;
6651            }
6652            current = (View) parent;
6653        } while (current != null);
6654
6655        return false;
6656    }
6657
6658    /**
6659     * Called by the view hierarchy when the content insets for a window have
6660     * changed, to allow it to adjust its content to fit within those windows.
6661     * The content insets tell you the space that the status bar, input method,
6662     * and other system windows infringe on the application's window.
6663     *
6664     * <p>You do not normally need to deal with this function, since the default
6665     * window decoration given to applications takes care of applying it to the
6666     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6667     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6668     * and your content can be placed under those system elements.  You can then
6669     * use this method within your view hierarchy if you have parts of your UI
6670     * which you would like to ensure are not being covered.
6671     *
6672     * <p>The default implementation of this method simply applies the content
6673     * insets to the view's padding, consuming that content (modifying the
6674     * insets to be 0), and returning true.  This behavior is off by default, but can
6675     * be enabled through {@link #setFitsSystemWindows(boolean)}.
6676     *
6677     * <p>This function's traversal down the hierarchy is depth-first.  The same content
6678     * insets object is propagated down the hierarchy, so any changes made to it will
6679     * be seen by all following views (including potentially ones above in
6680     * the hierarchy since this is a depth-first traversal).  The first view
6681     * that returns true will abort the entire traversal.
6682     *
6683     * <p>The default implementation works well for a situation where it is
6684     * used with a container that covers the entire window, allowing it to
6685     * apply the appropriate insets to its content on all edges.  If you need
6686     * a more complicated layout (such as two different views fitting system
6687     * windows, one on the top of the window, and one on the bottom),
6688     * you can override the method and handle the insets however you would like.
6689     * Note that the insets provided by the framework are always relative to the
6690     * far edges of the window, not accounting for the location of the called view
6691     * within that window.  (In fact when this method is called you do not yet know
6692     * where the layout will place the view, as it is done before layout happens.)
6693     *
6694     * <p>Note: unlike many View methods, there is no dispatch phase to this
6695     * call.  If you are overriding it in a ViewGroup and want to allow the
6696     * call to continue to your children, you must be sure to call the super
6697     * implementation.
6698     *
6699     * <p>Here is a sample layout that makes use of fitting system windows
6700     * to have controls for a video view placed inside of the window decorations
6701     * that it hides and shows.  This can be used with code like the second
6702     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6703     *
6704     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6705     *
6706     * @param insets Current content insets of the window.  Prior to
6707     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6708     * the insets or else you and Android will be unhappy.
6709     *
6710     * @return {@code true} if this view applied the insets and it should not
6711     * continue propagating further down the hierarchy, {@code false} otherwise.
6712     * @see #getFitsSystemWindows()
6713     * @see #setFitsSystemWindows(boolean)
6714     * @see #setSystemUiVisibility(int)
6715     *
6716     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6717     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6718     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6719     * to implement handling their own insets.
6720     */
6721    protected boolean fitSystemWindows(Rect insets) {
6722        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6723            if (insets == null) {
6724                // Null insets by definition have already been consumed.
6725                // This call cannot apply insets since there are none to apply,
6726                // so return false.
6727                return false;
6728            }
6729            // If we're not in the process of dispatching the newer apply insets call,
6730            // that means we're not in the compatibility path. Dispatch into the newer
6731            // apply insets path and take things from there.
6732            try {
6733                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6734                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6735            } finally {
6736                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6737            }
6738        } else {
6739            // We're being called from the newer apply insets path.
6740            // Perform the standard fallback behavior.
6741            return fitSystemWindowsInt(insets);
6742        }
6743    }
6744
6745    private boolean fitSystemWindowsInt(Rect insets) {
6746        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6747            mUserPaddingStart = UNDEFINED_PADDING;
6748            mUserPaddingEnd = UNDEFINED_PADDING;
6749            Rect localInsets = sThreadLocal.get();
6750            if (localInsets == null) {
6751                localInsets = new Rect();
6752                sThreadLocal.set(localInsets);
6753            }
6754            boolean res = computeFitSystemWindows(insets, localInsets);
6755            mUserPaddingLeftInitial = localInsets.left;
6756            mUserPaddingRightInitial = localInsets.right;
6757            internalSetPadding(localInsets.left, localInsets.top,
6758                    localInsets.right, localInsets.bottom);
6759            return res;
6760        }
6761        return false;
6762    }
6763
6764    /**
6765     * Called when the view should apply {@link WindowInsets} according to its internal policy.
6766     *
6767     * <p>This method should be overridden by views that wish to apply a policy different from or
6768     * in addition to the default behavior. Clients that wish to force a view subtree
6769     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6770     *
6771     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6772     * it will be called during dispatch instead of this method. The listener may optionally
6773     * call this method from its own implementation if it wishes to apply the view's default
6774     * insets policy in addition to its own.</p>
6775     *
6776     * <p>Implementations of this method should either return the insets parameter unchanged
6777     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6778     * that this view applied itself. This allows new inset types added in future platform
6779     * versions to pass through existing implementations unchanged without being erroneously
6780     * consumed.</p>
6781     *
6782     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6783     * property is set then the view will consume the system window insets and apply them
6784     * as padding for the view.</p>
6785     *
6786     * @param insets Insets to apply
6787     * @return The supplied insets with any applied insets consumed
6788     */
6789    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6790        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6791            // We weren't called from within a direct call to fitSystemWindows,
6792            // call into it as a fallback in case we're in a class that overrides it
6793            // and has logic to perform.
6794            if (fitSystemWindows(insets.getSystemWindowInsets())) {
6795                return insets.consumeSystemWindowInsets();
6796            }
6797        } else {
6798            // We were called from within a direct call to fitSystemWindows.
6799            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6800                return insets.consumeSystemWindowInsets();
6801            }
6802        }
6803        return insets;
6804    }
6805
6806    /**
6807     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6808     * window insets to this view. The listener's
6809     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6810     * method will be called instead of the view's
6811     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6812     *
6813     * @param listener Listener to set
6814     *
6815     * @see #onApplyWindowInsets(WindowInsets)
6816     */
6817    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6818        getListenerInfo().mOnApplyWindowInsetsListener = listener;
6819    }
6820
6821    /**
6822     * Request to apply the given window insets to this view or another view in its subtree.
6823     *
6824     * <p>This method should be called by clients wishing to apply insets corresponding to areas
6825     * obscured by window decorations or overlays. This can include the status and navigation bars,
6826     * action bars, input methods and more. New inset categories may be added in the future.
6827     * The method returns the insets provided minus any that were applied by this view or its
6828     * children.</p>
6829     *
6830     * <p>Clients wishing to provide custom behavior should override the
6831     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6832     * {@link OnApplyWindowInsetsListener} via the
6833     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6834     * method.</p>
6835     *
6836     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6837     * </p>
6838     *
6839     * @param insets Insets to apply
6840     * @return The provided insets minus the insets that were consumed
6841     */
6842    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6843        try {
6844            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6845            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6846                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6847            } else {
6848                return onApplyWindowInsets(insets);
6849            }
6850        } finally {
6851            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6852        }
6853    }
6854
6855    /**
6856     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
6857     * only available if the view is attached.
6858     *
6859     * @return WindowInsets from the top of the view hierarchy or null if View is detached
6860     */
6861    public WindowInsets getRootWindowInsets() {
6862        if (mAttachInfo != null) {
6863            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
6864        }
6865        return null;
6866    }
6867
6868    /**
6869     * @hide Compute the insets that should be consumed by this view and the ones
6870     * that should propagate to those under it.
6871     */
6872    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6873        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6874                || mAttachInfo == null
6875                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6876                        && !mAttachInfo.mOverscanRequested)) {
6877            outLocalInsets.set(inoutInsets);
6878            inoutInsets.set(0, 0, 0, 0);
6879            return true;
6880        } else {
6881            // The application wants to take care of fitting system window for
6882            // the content...  however we still need to take care of any overscan here.
6883            final Rect overscan = mAttachInfo.mOverscanInsets;
6884            outLocalInsets.set(overscan);
6885            inoutInsets.left -= overscan.left;
6886            inoutInsets.top -= overscan.top;
6887            inoutInsets.right -= overscan.right;
6888            inoutInsets.bottom -= overscan.bottom;
6889            return false;
6890        }
6891    }
6892
6893    /**
6894     * Compute insets that should be consumed by this view and the ones that should propagate
6895     * to those under it.
6896     *
6897     * @param in Insets currently being processed by this View, likely received as a parameter
6898     *           to {@link #onApplyWindowInsets(WindowInsets)}.
6899     * @param outLocalInsets A Rect that will receive the insets that should be consumed
6900     *                       by this view
6901     * @return Insets that should be passed along to views under this one
6902     */
6903    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6904        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6905                || mAttachInfo == null
6906                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6907            outLocalInsets.set(in.getSystemWindowInsets());
6908            return in.consumeSystemWindowInsets();
6909        } else {
6910            outLocalInsets.set(0, 0, 0, 0);
6911            return in;
6912        }
6913    }
6914
6915    /**
6916     * Sets whether or not this view should account for system screen decorations
6917     * such as the status bar and inset its content; that is, controlling whether
6918     * the default implementation of {@link #fitSystemWindows(Rect)} will be
6919     * executed.  See that method for more details.
6920     *
6921     * <p>Note that if you are providing your own implementation of
6922     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6923     * flag to true -- your implementation will be overriding the default
6924     * implementation that checks this flag.
6925     *
6926     * @param fitSystemWindows If true, then the default implementation of
6927     * {@link #fitSystemWindows(Rect)} will be executed.
6928     *
6929     * @attr ref android.R.styleable#View_fitsSystemWindows
6930     * @see #getFitsSystemWindows()
6931     * @see #fitSystemWindows(Rect)
6932     * @see #setSystemUiVisibility(int)
6933     */
6934    public void setFitsSystemWindows(boolean fitSystemWindows) {
6935        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6936    }
6937
6938    /**
6939     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6940     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6941     * will be executed.
6942     *
6943     * @return {@code true} if the default implementation of
6944     * {@link #fitSystemWindows(Rect)} will be executed.
6945     *
6946     * @attr ref android.R.styleable#View_fitsSystemWindows
6947     * @see #setFitsSystemWindows(boolean)
6948     * @see #fitSystemWindows(Rect)
6949     * @see #setSystemUiVisibility(int)
6950     */
6951    @ViewDebug.ExportedProperty
6952    public boolean getFitsSystemWindows() {
6953        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6954    }
6955
6956    /** @hide */
6957    public boolean fitsSystemWindows() {
6958        return getFitsSystemWindows();
6959    }
6960
6961    /**
6962     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6963     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6964     */
6965    public void requestFitSystemWindows() {
6966        if (mParent != null) {
6967            mParent.requestFitSystemWindows();
6968        }
6969    }
6970
6971    /**
6972     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6973     */
6974    public void requestApplyInsets() {
6975        requestFitSystemWindows();
6976    }
6977
6978    /**
6979     * For use by PhoneWindow to make its own system window fitting optional.
6980     * @hide
6981     */
6982    public void makeOptionalFitsSystemWindows() {
6983        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6984    }
6985
6986    /**
6987     * Returns the visibility status for this view.
6988     *
6989     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6990     * @attr ref android.R.styleable#View_visibility
6991     */
6992    @ViewDebug.ExportedProperty(mapping = {
6993        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6994        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6995        @ViewDebug.IntToString(from = GONE,      to = "GONE")
6996    })
6997    @Visibility
6998    public int getVisibility() {
6999        return mViewFlags & VISIBILITY_MASK;
7000    }
7001
7002    /**
7003     * Set the enabled state of this view.
7004     *
7005     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7006     * @attr ref android.R.styleable#View_visibility
7007     */
7008    @RemotableViewMethod
7009    public void setVisibility(@Visibility int visibility) {
7010        setFlags(visibility, VISIBILITY_MASK);
7011    }
7012
7013    /**
7014     * Returns the enabled status for this view. The interpretation of the
7015     * enabled state varies by subclass.
7016     *
7017     * @return True if this view is enabled, false otherwise.
7018     */
7019    @ViewDebug.ExportedProperty
7020    public boolean isEnabled() {
7021        return (mViewFlags & ENABLED_MASK) == ENABLED;
7022    }
7023
7024    /**
7025     * Set the enabled state of this view. The interpretation of the enabled
7026     * state varies by subclass.
7027     *
7028     * @param enabled True if this view is enabled, false otherwise.
7029     */
7030    @RemotableViewMethod
7031    public void setEnabled(boolean enabled) {
7032        if (enabled == isEnabled()) return;
7033
7034        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7035
7036        /*
7037         * The View most likely has to change its appearance, so refresh
7038         * the drawable state.
7039         */
7040        refreshDrawableState();
7041
7042        // Invalidate too, since the default behavior for views is to be
7043        // be drawn at 50% alpha rather than to change the drawable.
7044        invalidate(true);
7045
7046        if (!enabled) {
7047            cancelPendingInputEvents();
7048        }
7049    }
7050
7051    /**
7052     * Set whether this view can receive the focus.
7053     *
7054     * Setting this to false will also ensure that this view is not focusable
7055     * in touch mode.
7056     *
7057     * @param focusable If true, this view can receive the focus.
7058     *
7059     * @see #setFocusableInTouchMode(boolean)
7060     * @attr ref android.R.styleable#View_focusable
7061     */
7062    public void setFocusable(boolean focusable) {
7063        if (!focusable) {
7064            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7065        }
7066        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7067    }
7068
7069    /**
7070     * Set whether this view can receive focus while in touch mode.
7071     *
7072     * Setting this to true will also ensure that this view is focusable.
7073     *
7074     * @param focusableInTouchMode If true, this view can receive the focus while
7075     *   in touch mode.
7076     *
7077     * @see #setFocusable(boolean)
7078     * @attr ref android.R.styleable#View_focusableInTouchMode
7079     */
7080    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7081        // Focusable in touch mode should always be set before the focusable flag
7082        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7083        // which, in touch mode, will not successfully request focus on this view
7084        // because the focusable in touch mode flag is not set
7085        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7086        if (focusableInTouchMode) {
7087            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7088        }
7089    }
7090
7091    /**
7092     * Set whether this view should have sound effects enabled for events such as
7093     * clicking and touching.
7094     *
7095     * <p>You may wish to disable sound effects for a view if you already play sounds,
7096     * for instance, a dial key that plays dtmf tones.
7097     *
7098     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7099     * @see #isSoundEffectsEnabled()
7100     * @see #playSoundEffect(int)
7101     * @attr ref android.R.styleable#View_soundEffectsEnabled
7102     */
7103    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7104        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7105    }
7106
7107    /**
7108     * @return whether this view should have sound effects enabled for events such as
7109     *     clicking and touching.
7110     *
7111     * @see #setSoundEffectsEnabled(boolean)
7112     * @see #playSoundEffect(int)
7113     * @attr ref android.R.styleable#View_soundEffectsEnabled
7114     */
7115    @ViewDebug.ExportedProperty
7116    public boolean isSoundEffectsEnabled() {
7117        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7118    }
7119
7120    /**
7121     * Set whether this view should have haptic feedback for events such as
7122     * long presses.
7123     *
7124     * <p>You may wish to disable haptic feedback if your view already controls
7125     * its own haptic feedback.
7126     *
7127     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7128     * @see #isHapticFeedbackEnabled()
7129     * @see #performHapticFeedback(int)
7130     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7131     */
7132    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7133        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7134    }
7135
7136    /**
7137     * @return whether this view should have haptic feedback enabled for events
7138     * long presses.
7139     *
7140     * @see #setHapticFeedbackEnabled(boolean)
7141     * @see #performHapticFeedback(int)
7142     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7143     */
7144    @ViewDebug.ExportedProperty
7145    public boolean isHapticFeedbackEnabled() {
7146        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7147    }
7148
7149    /**
7150     * Returns the layout direction for this view.
7151     *
7152     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7153     *   {@link #LAYOUT_DIRECTION_RTL},
7154     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7155     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7156     *
7157     * @attr ref android.R.styleable#View_layoutDirection
7158     *
7159     * @hide
7160     */
7161    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7162        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7163        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7164        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7165        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7166    })
7167    @LayoutDir
7168    public int getRawLayoutDirection() {
7169        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7170    }
7171
7172    /**
7173     * Set the layout direction for this view. This will propagate a reset of layout direction
7174     * resolution to the view's children and resolve layout direction for this view.
7175     *
7176     * @param layoutDirection the layout direction to set. Should be one of:
7177     *
7178     * {@link #LAYOUT_DIRECTION_LTR},
7179     * {@link #LAYOUT_DIRECTION_RTL},
7180     * {@link #LAYOUT_DIRECTION_INHERIT},
7181     * {@link #LAYOUT_DIRECTION_LOCALE}.
7182     *
7183     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7184     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7185     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7186     *
7187     * @attr ref android.R.styleable#View_layoutDirection
7188     */
7189    @RemotableViewMethod
7190    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7191        if (getRawLayoutDirection() != layoutDirection) {
7192            // Reset the current layout direction and the resolved one
7193            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7194            resetRtlProperties();
7195            // Set the new layout direction (filtered)
7196            mPrivateFlags2 |=
7197                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7198            // We need to resolve all RTL properties as they all depend on layout direction
7199            resolveRtlPropertiesIfNeeded();
7200            requestLayout();
7201            invalidate(true);
7202        }
7203    }
7204
7205    /**
7206     * Returns the resolved layout direction for this view.
7207     *
7208     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7209     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7210     *
7211     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7212     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7213     *
7214     * @attr ref android.R.styleable#View_layoutDirection
7215     */
7216    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7217        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7218        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7219    })
7220    @ResolvedLayoutDir
7221    public int getLayoutDirection() {
7222        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7223        if (targetSdkVersion < JELLY_BEAN_MR1) {
7224            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7225            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7226        }
7227        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7228                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7229    }
7230
7231    /**
7232     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7233     * layout attribute and/or the inherited value from the parent
7234     *
7235     * @return true if the layout is right-to-left.
7236     *
7237     * @hide
7238     */
7239    @ViewDebug.ExportedProperty(category = "layout")
7240    public boolean isLayoutRtl() {
7241        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7242    }
7243
7244    /**
7245     * Indicates whether the view is currently tracking transient state that the
7246     * app should not need to concern itself with saving and restoring, but that
7247     * the framework should take special note to preserve when possible.
7248     *
7249     * <p>A view with transient state cannot be trivially rebound from an external
7250     * data source, such as an adapter binding item views in a list. This may be
7251     * because the view is performing an animation, tracking user selection
7252     * of content, or similar.</p>
7253     *
7254     * @return true if the view has transient state
7255     */
7256    @ViewDebug.ExportedProperty(category = "layout")
7257    public boolean hasTransientState() {
7258        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7259    }
7260
7261    /**
7262     * Set whether this view is currently tracking transient state that the
7263     * framework should attempt to preserve when possible. This flag is reference counted,
7264     * so every call to setHasTransientState(true) should be paired with a later call
7265     * to setHasTransientState(false).
7266     *
7267     * <p>A view with transient state cannot be trivially rebound from an external
7268     * data source, such as an adapter binding item views in a list. This may be
7269     * because the view is performing an animation, tracking user selection
7270     * of content, or similar.</p>
7271     *
7272     * @param hasTransientState true if this view has transient state
7273     */
7274    public void setHasTransientState(boolean hasTransientState) {
7275        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7276                mTransientStateCount - 1;
7277        if (mTransientStateCount < 0) {
7278            mTransientStateCount = 0;
7279            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7280                    "unmatched pair of setHasTransientState calls");
7281        } else if ((hasTransientState && mTransientStateCount == 1) ||
7282                (!hasTransientState && mTransientStateCount == 0)) {
7283            // update flag if we've just incremented up from 0 or decremented down to 0
7284            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7285                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7286            if (mParent != null) {
7287                try {
7288                    mParent.childHasTransientStateChanged(this, hasTransientState);
7289                } catch (AbstractMethodError e) {
7290                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7291                            " does not fully implement ViewParent", e);
7292                }
7293            }
7294        }
7295    }
7296
7297    /**
7298     * Returns true if this view is currently attached to a window.
7299     */
7300    public boolean isAttachedToWindow() {
7301        return mAttachInfo != null;
7302    }
7303
7304    /**
7305     * Returns true if this view has been through at least one layout since it
7306     * was last attached to or detached from a window.
7307     */
7308    public boolean isLaidOut() {
7309        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7310    }
7311
7312    /**
7313     * If this view doesn't do any drawing on its own, set this flag to
7314     * allow further optimizations. By default, this flag is not set on
7315     * View, but could be set on some View subclasses such as ViewGroup.
7316     *
7317     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7318     * you should clear this flag.
7319     *
7320     * @param willNotDraw whether or not this View draw on its own
7321     */
7322    public void setWillNotDraw(boolean willNotDraw) {
7323        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7324    }
7325
7326    /**
7327     * Returns whether or not this View draws on its own.
7328     *
7329     * @return true if this view has nothing to draw, false otherwise
7330     */
7331    @ViewDebug.ExportedProperty(category = "drawing")
7332    public boolean willNotDraw() {
7333        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7334    }
7335
7336    /**
7337     * When a View's drawing cache is enabled, drawing is redirected to an
7338     * offscreen bitmap. Some views, like an ImageView, must be able to
7339     * bypass this mechanism if they already draw a single bitmap, to avoid
7340     * unnecessary usage of the memory.
7341     *
7342     * @param willNotCacheDrawing true if this view does not cache its
7343     *        drawing, false otherwise
7344     */
7345    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7346        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7347    }
7348
7349    /**
7350     * Returns whether or not this View can cache its drawing or not.
7351     *
7352     * @return true if this view does not cache its drawing, false otherwise
7353     */
7354    @ViewDebug.ExportedProperty(category = "drawing")
7355    public boolean willNotCacheDrawing() {
7356        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7357    }
7358
7359    /**
7360     * Indicates whether this view reacts to click events or not.
7361     *
7362     * @return true if the view is clickable, false otherwise
7363     *
7364     * @see #setClickable(boolean)
7365     * @attr ref android.R.styleable#View_clickable
7366     */
7367    @ViewDebug.ExportedProperty
7368    public boolean isClickable() {
7369        return (mViewFlags & CLICKABLE) == CLICKABLE;
7370    }
7371
7372    /**
7373     * Enables or disables click events for this view. When a view
7374     * is clickable it will change its state to "pressed" on every click.
7375     * Subclasses should set the view clickable to visually react to
7376     * user's clicks.
7377     *
7378     * @param clickable true to make the view clickable, false otherwise
7379     *
7380     * @see #isClickable()
7381     * @attr ref android.R.styleable#View_clickable
7382     */
7383    public void setClickable(boolean clickable) {
7384        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7385    }
7386
7387    /**
7388     * Indicates whether this view reacts to long click events or not.
7389     *
7390     * @return true if the view is long clickable, false otherwise
7391     *
7392     * @see #setLongClickable(boolean)
7393     * @attr ref android.R.styleable#View_longClickable
7394     */
7395    public boolean isLongClickable() {
7396        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7397    }
7398
7399    /**
7400     * Enables or disables long click events for this view. When a view is long
7401     * clickable it reacts to the user holding down the button for a longer
7402     * duration than a tap. This event can either launch the listener or a
7403     * context menu.
7404     *
7405     * @param longClickable true to make the view long clickable, false otherwise
7406     * @see #isLongClickable()
7407     * @attr ref android.R.styleable#View_longClickable
7408     */
7409    public void setLongClickable(boolean longClickable) {
7410        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7411    }
7412
7413    /**
7414     * Sets the pressed state for this view and provides a touch coordinate for
7415     * animation hinting.
7416     *
7417     * @param pressed Pass true to set the View's internal state to "pressed",
7418     *            or false to reverts the View's internal state from a
7419     *            previously set "pressed" state.
7420     * @param x The x coordinate of the touch that caused the press
7421     * @param y The y coordinate of the touch that caused the press
7422     */
7423    private void setPressed(boolean pressed, float x, float y) {
7424        if (pressed) {
7425            drawableHotspotChanged(x, y);
7426        }
7427
7428        setPressed(pressed);
7429    }
7430
7431    /**
7432     * Sets the pressed state for this view.
7433     *
7434     * @see #isClickable()
7435     * @see #setClickable(boolean)
7436     *
7437     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7438     *        the View's internal state from a previously set "pressed" state.
7439     */
7440    public void setPressed(boolean pressed) {
7441        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7442
7443        if (pressed) {
7444            mPrivateFlags |= PFLAG_PRESSED;
7445        } else {
7446            mPrivateFlags &= ~PFLAG_PRESSED;
7447        }
7448
7449        if (needsRefresh) {
7450            refreshDrawableState();
7451        }
7452        dispatchSetPressed(pressed);
7453    }
7454
7455    /**
7456     * Dispatch setPressed to all of this View's children.
7457     *
7458     * @see #setPressed(boolean)
7459     *
7460     * @param pressed The new pressed state
7461     */
7462    protected void dispatchSetPressed(boolean pressed) {
7463    }
7464
7465    /**
7466     * Indicates whether the view is currently in pressed state. Unless
7467     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7468     * the pressed state.
7469     *
7470     * @see #setPressed(boolean)
7471     * @see #isClickable()
7472     * @see #setClickable(boolean)
7473     *
7474     * @return true if the view is currently pressed, false otherwise
7475     */
7476    @ViewDebug.ExportedProperty
7477    public boolean isPressed() {
7478        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7479    }
7480
7481    /**
7482     * Indicates whether this view will participate in data collection through
7483     * {@link android.view.ViewAssistStructure}.  If true, it will not provide any data
7484     * for itself or its children.  If false, the normal data collection will be allowed.
7485     *
7486     * @return Returns false if assist data collection is not blocked, else true.
7487     *
7488     * @see #setAssistBlocked(boolean)
7489     * @attr ref android.R.styleable#View_assistBlocked
7490     */
7491    public boolean isAssistBlocked() {
7492        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7493    }
7494
7495    /**
7496     * Controls whether assist data collection from this view and its children is enabled
7497     * (that is, whether {@link #onProvideAssistStructure} and
7498     * {@link #onProvideVirtualAssistStructure} will be called).  The default value is false,
7499     * allowing normal assist collection.  Setting this to false will disable assist collection.
7500     *
7501     * @param enabled Set to true to <em>disable</em> assist data collection, or false
7502     * (the default) to allow it.
7503     *
7504     * @see #isAssistBlocked()
7505     * @see #onProvideAssistStructure
7506     * @see #onProvideVirtualAssistStructure
7507     * @attr ref android.R.styleable#View_assistBlocked
7508     */
7509    public void setAssistBlocked(boolean enabled) {
7510        if (enabled) {
7511            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7512        } else {
7513            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7514        }
7515    }
7516
7517    /**
7518     * Indicates whether this view will save its state (that is,
7519     * whether its {@link #onSaveInstanceState} method will be called).
7520     *
7521     * @return Returns true if the view state saving is enabled, else false.
7522     *
7523     * @see #setSaveEnabled(boolean)
7524     * @attr ref android.R.styleable#View_saveEnabled
7525     */
7526    public boolean isSaveEnabled() {
7527        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7528    }
7529
7530    /**
7531     * Controls whether the saving of this view's state is
7532     * enabled (that is, whether its {@link #onSaveInstanceState} method
7533     * will be called).  Note that even if freezing is enabled, the
7534     * view still must have an id assigned to it (via {@link #setId(int)})
7535     * for its state to be saved.  This flag can only disable the
7536     * saving of this view; any child views may still have their state saved.
7537     *
7538     * @param enabled Set to false to <em>disable</em> state saving, or true
7539     * (the default) to allow it.
7540     *
7541     * @see #isSaveEnabled()
7542     * @see #setId(int)
7543     * @see #onSaveInstanceState()
7544     * @attr ref android.R.styleable#View_saveEnabled
7545     */
7546    public void setSaveEnabled(boolean enabled) {
7547        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7548    }
7549
7550    /**
7551     * Gets whether the framework should discard touches when the view's
7552     * window is obscured by another visible window.
7553     * Refer to the {@link View} security documentation for more details.
7554     *
7555     * @return True if touch filtering is enabled.
7556     *
7557     * @see #setFilterTouchesWhenObscured(boolean)
7558     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7559     */
7560    @ViewDebug.ExportedProperty
7561    public boolean getFilterTouchesWhenObscured() {
7562        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7563    }
7564
7565    /**
7566     * Sets whether the framework should discard touches when the view's
7567     * window is obscured by another visible window.
7568     * Refer to the {@link View} security documentation for more details.
7569     *
7570     * @param enabled True if touch filtering should be enabled.
7571     *
7572     * @see #getFilterTouchesWhenObscured
7573     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7574     */
7575    public void setFilterTouchesWhenObscured(boolean enabled) {
7576        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7577                FILTER_TOUCHES_WHEN_OBSCURED);
7578    }
7579
7580    /**
7581     * Indicates whether the entire hierarchy under this view will save its
7582     * state when a state saving traversal occurs from its parent.  The default
7583     * is true; if false, these views will not be saved unless
7584     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7585     *
7586     * @return Returns true if the view state saving from parent is enabled, else false.
7587     *
7588     * @see #setSaveFromParentEnabled(boolean)
7589     */
7590    public boolean isSaveFromParentEnabled() {
7591        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7592    }
7593
7594    /**
7595     * Controls whether the entire hierarchy under this view will save its
7596     * state when a state saving traversal occurs from its parent.  The default
7597     * is true; if false, these views will not be saved unless
7598     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7599     *
7600     * @param enabled Set to false to <em>disable</em> state saving, or true
7601     * (the default) to allow it.
7602     *
7603     * @see #isSaveFromParentEnabled()
7604     * @see #setId(int)
7605     * @see #onSaveInstanceState()
7606     */
7607    public void setSaveFromParentEnabled(boolean enabled) {
7608        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7609    }
7610
7611
7612    /**
7613     * Returns whether this View is able to take focus.
7614     *
7615     * @return True if this view can take focus, or false otherwise.
7616     * @attr ref android.R.styleable#View_focusable
7617     */
7618    @ViewDebug.ExportedProperty(category = "focus")
7619    public final boolean isFocusable() {
7620        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7621    }
7622
7623    /**
7624     * When a view is focusable, it may not want to take focus when in touch mode.
7625     * For example, a button would like focus when the user is navigating via a D-pad
7626     * so that the user can click on it, but once the user starts touching the screen,
7627     * the button shouldn't take focus
7628     * @return Whether the view is focusable in touch mode.
7629     * @attr ref android.R.styleable#View_focusableInTouchMode
7630     */
7631    @ViewDebug.ExportedProperty
7632    public final boolean isFocusableInTouchMode() {
7633        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7634    }
7635
7636    /**
7637     * Find the nearest view in the specified direction that can take focus.
7638     * This does not actually give focus to that view.
7639     *
7640     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7641     *
7642     * @return The nearest focusable in the specified direction, or null if none
7643     *         can be found.
7644     */
7645    public View focusSearch(@FocusRealDirection int direction) {
7646        if (mParent != null) {
7647            return mParent.focusSearch(this, direction);
7648        } else {
7649            return null;
7650        }
7651    }
7652
7653    /**
7654     * This method is the last chance for the focused view and its ancestors to
7655     * respond to an arrow key. This is called when the focused view did not
7656     * consume the key internally, nor could the view system find a new view in
7657     * the requested direction to give focus to.
7658     *
7659     * @param focused The currently focused view.
7660     * @param direction The direction focus wants to move. One of FOCUS_UP,
7661     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7662     * @return True if the this view consumed this unhandled move.
7663     */
7664    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7665        return false;
7666    }
7667
7668    /**
7669     * If a user manually specified the next view id for a particular direction,
7670     * use the root to look up the view.
7671     * @param root The root view of the hierarchy containing this view.
7672     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7673     * or FOCUS_BACKWARD.
7674     * @return The user specified next view, or null if there is none.
7675     */
7676    View findUserSetNextFocus(View root, @FocusDirection int direction) {
7677        switch (direction) {
7678            case FOCUS_LEFT:
7679                if (mNextFocusLeftId == View.NO_ID) return null;
7680                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7681            case FOCUS_RIGHT:
7682                if (mNextFocusRightId == View.NO_ID) return null;
7683                return findViewInsideOutShouldExist(root, mNextFocusRightId);
7684            case FOCUS_UP:
7685                if (mNextFocusUpId == View.NO_ID) return null;
7686                return findViewInsideOutShouldExist(root, mNextFocusUpId);
7687            case FOCUS_DOWN:
7688                if (mNextFocusDownId == View.NO_ID) return null;
7689                return findViewInsideOutShouldExist(root, mNextFocusDownId);
7690            case FOCUS_FORWARD:
7691                if (mNextFocusForwardId == View.NO_ID) return null;
7692                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7693            case FOCUS_BACKWARD: {
7694                if (mID == View.NO_ID) return null;
7695                final int id = mID;
7696                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7697                    @Override
7698                    public boolean apply(View t) {
7699                        return t.mNextFocusForwardId == id;
7700                    }
7701                });
7702            }
7703        }
7704        return null;
7705    }
7706
7707    private View findViewInsideOutShouldExist(View root, int id) {
7708        if (mMatchIdPredicate == null) {
7709            mMatchIdPredicate = new MatchIdPredicate();
7710        }
7711        mMatchIdPredicate.mId = id;
7712        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7713        if (result == null) {
7714            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7715        }
7716        return result;
7717    }
7718
7719    /**
7720     * Find and return all focusable views that are descendants of this view,
7721     * possibly including this view if it is focusable itself.
7722     *
7723     * @param direction The direction of the focus
7724     * @return A list of focusable views
7725     */
7726    public ArrayList<View> getFocusables(@FocusDirection int direction) {
7727        ArrayList<View> result = new ArrayList<View>(24);
7728        addFocusables(result, direction);
7729        return result;
7730    }
7731
7732    /**
7733     * Add any focusable views that are descendants of this view (possibly
7734     * including this view if it is focusable itself) to views.  If we are in touch mode,
7735     * only add views that are also focusable in touch mode.
7736     *
7737     * @param views Focusable views found so far
7738     * @param direction The direction of the focus
7739     */
7740    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7741        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7742    }
7743
7744    /**
7745     * Adds any focusable views that are descendants of this view (possibly
7746     * including this view if it is focusable itself) to views. This method
7747     * adds all focusable views regardless if we are in touch mode or
7748     * only views focusable in touch mode if we are in touch mode or
7749     * only views that can take accessibility focus if accessibility is enabled
7750     * depending on the focusable mode parameter.
7751     *
7752     * @param views Focusable views found so far or null if all we are interested is
7753     *        the number of focusables.
7754     * @param direction The direction of the focus.
7755     * @param focusableMode The type of focusables to be added.
7756     *
7757     * @see #FOCUSABLES_ALL
7758     * @see #FOCUSABLES_TOUCH_MODE
7759     */
7760    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7761            @FocusableMode int focusableMode) {
7762        if (views == null) {
7763            return;
7764        }
7765        if (!isFocusable()) {
7766            return;
7767        }
7768        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7769                && isInTouchMode() && !isFocusableInTouchMode()) {
7770            return;
7771        }
7772        views.add(this);
7773    }
7774
7775    /**
7776     * Finds the Views that contain given text. The containment is case insensitive.
7777     * The search is performed by either the text that the View renders or the content
7778     * description that describes the view for accessibility purposes and the view does
7779     * not render or both. Clients can specify how the search is to be performed via
7780     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7781     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7782     *
7783     * @param outViews The output list of matching Views.
7784     * @param searched The text to match against.
7785     *
7786     * @see #FIND_VIEWS_WITH_TEXT
7787     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7788     * @see #setContentDescription(CharSequence)
7789     */
7790    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7791            @FindViewFlags int flags) {
7792        if (getAccessibilityNodeProvider() != null) {
7793            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7794                outViews.add(this);
7795            }
7796        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7797                && (searched != null && searched.length() > 0)
7798                && (mContentDescription != null && mContentDescription.length() > 0)) {
7799            String searchedLowerCase = searched.toString().toLowerCase();
7800            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7801            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7802                outViews.add(this);
7803            }
7804        }
7805    }
7806
7807    /**
7808     * Find and return all touchable views that are descendants of this view,
7809     * possibly including this view if it is touchable itself.
7810     *
7811     * @return A list of touchable views
7812     */
7813    public ArrayList<View> getTouchables() {
7814        ArrayList<View> result = new ArrayList<View>();
7815        addTouchables(result);
7816        return result;
7817    }
7818
7819    /**
7820     * Add any touchable views that are descendants of this view (possibly
7821     * including this view if it is touchable itself) to views.
7822     *
7823     * @param views Touchable views found so far
7824     */
7825    public void addTouchables(ArrayList<View> views) {
7826        final int viewFlags = mViewFlags;
7827
7828        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7829                && (viewFlags & ENABLED_MASK) == ENABLED) {
7830            views.add(this);
7831        }
7832    }
7833
7834    /**
7835     * Returns whether this View is accessibility focused.
7836     *
7837     * @return True if this View is accessibility focused.
7838     */
7839    public boolean isAccessibilityFocused() {
7840        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7841    }
7842
7843    /**
7844     * Call this to try to give accessibility focus to this view.
7845     *
7846     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7847     * returns false or the view is no visible or the view already has accessibility
7848     * focus.
7849     *
7850     * See also {@link #focusSearch(int)}, which is what you call to say that you
7851     * have focus, and you want your parent to look for the next one.
7852     *
7853     * @return Whether this view actually took accessibility focus.
7854     *
7855     * @hide
7856     */
7857    public boolean requestAccessibilityFocus() {
7858        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7859        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7860            return false;
7861        }
7862        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7863            return false;
7864        }
7865        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7866            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7867            ViewRootImpl viewRootImpl = getViewRootImpl();
7868            if (viewRootImpl != null) {
7869                viewRootImpl.setAccessibilityFocus(this, null);
7870            }
7871            invalidate();
7872            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7873            return true;
7874        }
7875        return false;
7876    }
7877
7878    /**
7879     * Call this to try to clear accessibility focus of this view.
7880     *
7881     * See also {@link #focusSearch(int)}, which is what you call to say that you
7882     * have focus, and you want your parent to look for the next one.
7883     *
7884     * @hide
7885     */
7886    public void clearAccessibilityFocus() {
7887        clearAccessibilityFocusNoCallbacks();
7888        // Clear the global reference of accessibility focus if this
7889        // view or any of its descendants had accessibility focus.
7890        ViewRootImpl viewRootImpl = getViewRootImpl();
7891        if (viewRootImpl != null) {
7892            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7893            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7894                viewRootImpl.setAccessibilityFocus(null, null);
7895            }
7896        }
7897    }
7898
7899    private void sendAccessibilityHoverEvent(int eventType) {
7900        // Since we are not delivering to a client accessibility events from not
7901        // important views (unless the clinet request that) we need to fire the
7902        // event from the deepest view exposed to the client. As a consequence if
7903        // the user crosses a not exposed view the client will see enter and exit
7904        // of the exposed predecessor followed by and enter and exit of that same
7905        // predecessor when entering and exiting the not exposed descendant. This
7906        // is fine since the client has a clear idea which view is hovered at the
7907        // price of a couple more events being sent. This is a simple and
7908        // working solution.
7909        View source = this;
7910        while (true) {
7911            if (source.includeForAccessibility()) {
7912                source.sendAccessibilityEvent(eventType);
7913                return;
7914            }
7915            ViewParent parent = source.getParent();
7916            if (parent instanceof View) {
7917                source = (View) parent;
7918            } else {
7919                return;
7920            }
7921        }
7922    }
7923
7924    /**
7925     * Clears accessibility focus without calling any callback methods
7926     * normally invoked in {@link #clearAccessibilityFocus()}. This method
7927     * is used for clearing accessibility focus when giving this focus to
7928     * another view.
7929     */
7930    void clearAccessibilityFocusNoCallbacks() {
7931        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7932            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7933            invalidate();
7934            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7935        }
7936    }
7937
7938    /**
7939     * Call this to try to give focus to a specific view or to one of its
7940     * descendants.
7941     *
7942     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7943     * false), or if it is focusable and it is not focusable in touch mode
7944     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7945     *
7946     * See also {@link #focusSearch(int)}, which is what you call to say that you
7947     * have focus, and you want your parent to look for the next one.
7948     *
7949     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7950     * {@link #FOCUS_DOWN} and <code>null</code>.
7951     *
7952     * @return Whether this view or one of its descendants actually took focus.
7953     */
7954    public final boolean requestFocus() {
7955        return requestFocus(View.FOCUS_DOWN);
7956    }
7957
7958    /**
7959     * Call this to try to give focus to a specific view or to one of its
7960     * descendants and give it a hint about what direction focus is heading.
7961     *
7962     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7963     * false), or if it is focusable and it is not focusable in touch mode
7964     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7965     *
7966     * See also {@link #focusSearch(int)}, which is what you call to say that you
7967     * have focus, and you want your parent to look for the next one.
7968     *
7969     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7970     * <code>null</code> set for the previously focused rectangle.
7971     *
7972     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7973     * @return Whether this view or one of its descendants actually took focus.
7974     */
7975    public final boolean requestFocus(int direction) {
7976        return requestFocus(direction, null);
7977    }
7978
7979    /**
7980     * Call this to try to give focus to a specific view or to one of its descendants
7981     * and give it hints about the direction and a specific rectangle that the focus
7982     * is coming from.  The rectangle can help give larger views a finer grained hint
7983     * about where focus is coming from, and therefore, where to show selection, or
7984     * forward focus change internally.
7985     *
7986     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7987     * false), or if it is focusable and it is not focusable in touch mode
7988     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7989     *
7990     * A View will not take focus if it is not visible.
7991     *
7992     * A View will not take focus if one of its parents has
7993     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7994     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7995     *
7996     * See also {@link #focusSearch(int)}, which is what you call to say that you
7997     * have focus, and you want your parent to look for the next one.
7998     *
7999     * You may wish to override this method if your custom {@link View} has an internal
8000     * {@link View} that it wishes to forward the request to.
8001     *
8002     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8003     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8004     *        to give a finer grained hint about where focus is coming from.  May be null
8005     *        if there is no hint.
8006     * @return Whether this view or one of its descendants actually took focus.
8007     */
8008    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8009        return requestFocusNoSearch(direction, previouslyFocusedRect);
8010    }
8011
8012    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8013        // need to be focusable
8014        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8015                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8016            return false;
8017        }
8018
8019        // need to be focusable in touch mode if in touch mode
8020        if (isInTouchMode() &&
8021            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8022               return false;
8023        }
8024
8025        // need to not have any parents blocking us
8026        if (hasAncestorThatBlocksDescendantFocus()) {
8027            return false;
8028        }
8029
8030        handleFocusGainInternal(direction, previouslyFocusedRect);
8031        return true;
8032    }
8033
8034    /**
8035     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8036     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8037     * touch mode to request focus when they are touched.
8038     *
8039     * @return Whether this view or one of its descendants actually took focus.
8040     *
8041     * @see #isInTouchMode()
8042     *
8043     */
8044    public final boolean requestFocusFromTouch() {
8045        // Leave touch mode if we need to
8046        if (isInTouchMode()) {
8047            ViewRootImpl viewRoot = getViewRootImpl();
8048            if (viewRoot != null) {
8049                viewRoot.ensureTouchMode(false);
8050            }
8051        }
8052        return requestFocus(View.FOCUS_DOWN);
8053    }
8054
8055    /**
8056     * @return Whether any ancestor of this view blocks descendant focus.
8057     */
8058    private boolean hasAncestorThatBlocksDescendantFocus() {
8059        final boolean focusableInTouchMode = isFocusableInTouchMode();
8060        ViewParent ancestor = mParent;
8061        while (ancestor instanceof ViewGroup) {
8062            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8063            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8064                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8065                return true;
8066            } else {
8067                ancestor = vgAncestor.getParent();
8068            }
8069        }
8070        return false;
8071    }
8072
8073    /**
8074     * Gets the mode for determining whether this View is important for accessibility
8075     * which is if it fires accessibility events and if it is reported to
8076     * accessibility services that query the screen.
8077     *
8078     * @return The mode for determining whether a View is important for accessibility.
8079     *
8080     * @attr ref android.R.styleable#View_importantForAccessibility
8081     *
8082     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8083     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8084     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8085     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8086     */
8087    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8088            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8089            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8090            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8091            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8092                    to = "noHideDescendants")
8093        })
8094    public int getImportantForAccessibility() {
8095        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8096                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8097    }
8098
8099    /**
8100     * Sets the live region mode for this view. This indicates to accessibility
8101     * services whether they should automatically notify the user about changes
8102     * to the view's content description or text, or to the content descriptions
8103     * or text of the view's children (where applicable).
8104     * <p>
8105     * For example, in a login screen with a TextView that displays an "incorrect
8106     * password" notification, that view should be marked as a live region with
8107     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8108     * <p>
8109     * To disable change notifications for this view, use
8110     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8111     * mode for most views.
8112     * <p>
8113     * To indicate that the user should be notified of changes, use
8114     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8115     * <p>
8116     * If the view's changes should interrupt ongoing speech and notify the user
8117     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8118     *
8119     * @param mode The live region mode for this view, one of:
8120     *        <ul>
8121     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8122     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8123     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8124     *        </ul>
8125     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8126     */
8127    public void setAccessibilityLiveRegion(int mode) {
8128        if (mode != getAccessibilityLiveRegion()) {
8129            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8130            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8131                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8132            notifyViewAccessibilityStateChangedIfNeeded(
8133                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8134        }
8135    }
8136
8137    /**
8138     * Gets the live region mode for this View.
8139     *
8140     * @return The live region mode for the view.
8141     *
8142     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8143     *
8144     * @see #setAccessibilityLiveRegion(int)
8145     */
8146    public int getAccessibilityLiveRegion() {
8147        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8148                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8149    }
8150
8151    /**
8152     * Sets how to determine whether this view is important for accessibility
8153     * which is if it fires accessibility events and if it is reported to
8154     * accessibility services that query the screen.
8155     *
8156     * @param mode How to determine whether this view is important for accessibility.
8157     *
8158     * @attr ref android.R.styleable#View_importantForAccessibility
8159     *
8160     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8161     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8162     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8163     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8164     */
8165    public void setImportantForAccessibility(int mode) {
8166        final int oldMode = getImportantForAccessibility();
8167        if (mode != oldMode) {
8168            // If we're moving between AUTO and another state, we might not need
8169            // to send a subtree changed notification. We'll store the computed
8170            // importance, since we'll need to check it later to make sure.
8171            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8172                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8173            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8174            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8175            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8176                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8177            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8178                notifySubtreeAccessibilityStateChangedIfNeeded();
8179            } else {
8180                notifyViewAccessibilityStateChangedIfNeeded(
8181                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8182            }
8183        }
8184    }
8185
8186    /**
8187     * Computes whether this view should be exposed for accessibility. In
8188     * general, views that are interactive or provide information are exposed
8189     * while views that serve only as containers are hidden.
8190     * <p>
8191     * If an ancestor of this view has importance
8192     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8193     * returns <code>false</code>.
8194     * <p>
8195     * Otherwise, the value is computed according to the view's
8196     * {@link #getImportantForAccessibility()} value:
8197     * <ol>
8198     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8199     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8200     * </code>
8201     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8202     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8203     * view satisfies any of the following:
8204     * <ul>
8205     * <li>Is actionable, e.g. {@link #isClickable()},
8206     * {@link #isLongClickable()}, or {@link #isFocusable()}
8207     * <li>Has an {@link AccessibilityDelegate}
8208     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8209     * {@link OnKeyListener}, etc.
8210     * <li>Is an accessibility live region, e.g.
8211     * {@link #getAccessibilityLiveRegion()} is not
8212     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8213     * </ul>
8214     * </ol>
8215     *
8216     * @return Whether the view is exposed for accessibility.
8217     * @see #setImportantForAccessibility(int)
8218     * @see #getImportantForAccessibility()
8219     */
8220    public boolean isImportantForAccessibility() {
8221        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8222                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8223        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8224                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8225            return false;
8226        }
8227
8228        // Check parent mode to ensure we're not hidden.
8229        ViewParent parent = mParent;
8230        while (parent instanceof View) {
8231            if (((View) parent).getImportantForAccessibility()
8232                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8233                return false;
8234            }
8235            parent = parent.getParent();
8236        }
8237
8238        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8239                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8240                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8241    }
8242
8243    /**
8244     * Gets the parent for accessibility purposes. Note that the parent for
8245     * accessibility is not necessary the immediate parent. It is the first
8246     * predecessor that is important for accessibility.
8247     *
8248     * @return The parent for accessibility purposes.
8249     */
8250    public ViewParent getParentForAccessibility() {
8251        if (mParent instanceof View) {
8252            View parentView = (View) mParent;
8253            if (parentView.includeForAccessibility()) {
8254                return mParent;
8255            } else {
8256                return mParent.getParentForAccessibility();
8257            }
8258        }
8259        return null;
8260    }
8261
8262    /**
8263     * Adds the children of a given View for accessibility. Since some Views are
8264     * not important for accessibility the children for accessibility are not
8265     * necessarily direct children of the view, rather they are the first level of
8266     * descendants important for accessibility.
8267     *
8268     * @param children The list of children for accessibility.
8269     */
8270    public void addChildrenForAccessibility(ArrayList<View> children) {
8271
8272    }
8273
8274    /**
8275     * Whether to regard this view for accessibility. A view is regarded for
8276     * accessibility if it is important for accessibility or the querying
8277     * accessibility service has explicitly requested that view not
8278     * important for accessibility are regarded.
8279     *
8280     * @return Whether to regard the view for accessibility.
8281     *
8282     * @hide
8283     */
8284    public boolean includeForAccessibility() {
8285        if (mAttachInfo != null) {
8286            return (mAttachInfo.mAccessibilityFetchFlags
8287                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8288                    || isImportantForAccessibility();
8289        }
8290        return false;
8291    }
8292
8293    /**
8294     * Returns whether the View is considered actionable from
8295     * accessibility perspective. Such view are important for
8296     * accessibility.
8297     *
8298     * @return True if the view is actionable for accessibility.
8299     *
8300     * @hide
8301     */
8302    public boolean isActionableForAccessibility() {
8303        return (isClickable() || isLongClickable() || isFocusable());
8304    }
8305
8306    /**
8307     * Returns whether the View has registered callbacks which makes it
8308     * important for accessibility.
8309     *
8310     * @return True if the view is actionable for accessibility.
8311     */
8312    private boolean hasListenersForAccessibility() {
8313        ListenerInfo info = getListenerInfo();
8314        return mTouchDelegate != null || info.mOnKeyListener != null
8315                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8316                || info.mOnHoverListener != null || info.mOnDragListener != null;
8317    }
8318
8319    /**
8320     * Notifies that the accessibility state of this view changed. The change
8321     * is local to this view and does not represent structural changes such
8322     * as children and parent. For example, the view became focusable. The
8323     * notification is at at most once every
8324     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8325     * to avoid unnecessary load to the system. Also once a view has a pending
8326     * notification this method is a NOP until the notification has been sent.
8327     *
8328     * @hide
8329     */
8330    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8331        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8332            return;
8333        }
8334        if (mSendViewStateChangedAccessibilityEvent == null) {
8335            mSendViewStateChangedAccessibilityEvent =
8336                    new SendViewStateChangedAccessibilityEvent();
8337        }
8338        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8339    }
8340
8341    /**
8342     * Notifies that the accessibility state of this view changed. The change
8343     * is *not* local to this view and does represent structural changes such
8344     * as children and parent. For example, the view size changed. The
8345     * notification is at at most once every
8346     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8347     * to avoid unnecessary load to the system. Also once a view has a pending
8348     * notification this method is a NOP until the notification has been sent.
8349     *
8350     * @hide
8351     */
8352    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8353        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8354            return;
8355        }
8356        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8357            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8358            if (mParent != null) {
8359                try {
8360                    mParent.notifySubtreeAccessibilityStateChanged(
8361                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8362                } catch (AbstractMethodError e) {
8363                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8364                            " does not fully implement ViewParent", e);
8365                }
8366            }
8367        }
8368    }
8369
8370    /**
8371     * Reset the flag indicating the accessibility state of the subtree rooted
8372     * at this view changed.
8373     */
8374    void resetSubtreeAccessibilityStateChanged() {
8375        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8376    }
8377
8378    /**
8379     * Report an accessibility action to this view's parents for delegated processing.
8380     *
8381     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8382     * call this method to delegate an accessibility action to a supporting parent. If the parent
8383     * returns true from its
8384     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8385     * method this method will return true to signify that the action was consumed.</p>
8386     *
8387     * <p>This method is useful for implementing nested scrolling child views. If
8388     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8389     * a custom view implementation may invoke this method to allow a parent to consume the
8390     * scroll first. If this method returns true the custom view should skip its own scrolling
8391     * behavior.</p>
8392     *
8393     * @param action Accessibility action to delegate
8394     * @param arguments Optional action arguments
8395     * @return true if the action was consumed by a parent
8396     */
8397    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8398        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8399            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8400                return true;
8401            }
8402        }
8403        return false;
8404    }
8405
8406    /**
8407     * Performs the specified accessibility action on the view. For
8408     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8409     * <p>
8410     * If an {@link AccessibilityDelegate} has been specified via calling
8411     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8412     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8413     * is responsible for handling this call.
8414     * </p>
8415     *
8416     * <p>The default implementation will delegate
8417     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8418     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8419     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8420     *
8421     * @param action The action to perform.
8422     * @param arguments Optional action arguments.
8423     * @return Whether the action was performed.
8424     */
8425    public boolean performAccessibilityAction(int action, Bundle arguments) {
8426      if (mAccessibilityDelegate != null) {
8427          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8428      } else {
8429          return performAccessibilityActionInternal(action, arguments);
8430      }
8431    }
8432
8433   /**
8434    * @see #performAccessibilityAction(int, Bundle)
8435    *
8436    * Note: Called from the default {@link AccessibilityDelegate}.
8437    *
8438    * @hide
8439    */
8440    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8441        if (isNestedScrollingEnabled()
8442                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8443                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
8444            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8445                return true;
8446            }
8447        }
8448
8449        switch (action) {
8450            case AccessibilityNodeInfo.ACTION_CLICK: {
8451                if (isClickable()) {
8452                    performClick();
8453                    return true;
8454                }
8455            } break;
8456            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8457                if (isLongClickable()) {
8458                    performLongClick();
8459                    return true;
8460                }
8461            } break;
8462            case AccessibilityNodeInfo.ACTION_FOCUS: {
8463                if (!hasFocus()) {
8464                    // Get out of touch mode since accessibility
8465                    // wants to move focus around.
8466                    getViewRootImpl().ensureTouchMode(false);
8467                    return requestFocus();
8468                }
8469            } break;
8470            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8471                if (hasFocus()) {
8472                    clearFocus();
8473                    return !isFocused();
8474                }
8475            } break;
8476            case AccessibilityNodeInfo.ACTION_SELECT: {
8477                if (!isSelected()) {
8478                    setSelected(true);
8479                    return isSelected();
8480                }
8481            } break;
8482            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8483                if (isSelected()) {
8484                    setSelected(false);
8485                    return !isSelected();
8486                }
8487            } break;
8488            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8489                if (!isAccessibilityFocused()) {
8490                    return requestAccessibilityFocus();
8491                }
8492            } break;
8493            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8494                if (isAccessibilityFocused()) {
8495                    clearAccessibilityFocus();
8496                    return true;
8497                }
8498            } break;
8499            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8500                if (arguments != null) {
8501                    final int granularity = arguments.getInt(
8502                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8503                    final boolean extendSelection = arguments.getBoolean(
8504                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8505                    return traverseAtGranularity(granularity, true, extendSelection);
8506                }
8507            } break;
8508            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8509                if (arguments != null) {
8510                    final int granularity = arguments.getInt(
8511                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8512                    final boolean extendSelection = arguments.getBoolean(
8513                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8514                    return traverseAtGranularity(granularity, false, extendSelection);
8515                }
8516            } break;
8517            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8518                CharSequence text = getIterableTextForAccessibility();
8519                if (text == null) {
8520                    return false;
8521                }
8522                final int start = (arguments != null) ? arguments.getInt(
8523                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8524                final int end = (arguments != null) ? arguments.getInt(
8525                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8526                // Only cursor position can be specified (selection length == 0)
8527                if ((getAccessibilitySelectionStart() != start
8528                        || getAccessibilitySelectionEnd() != end)
8529                        && (start == end)) {
8530                    setAccessibilitySelection(start, end);
8531                    notifyViewAccessibilityStateChangedIfNeeded(
8532                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8533                    return true;
8534                }
8535            } break;
8536            case R.id.accessibilityActionShowOnScreen: {
8537                if (mAttachInfo != null) {
8538                    final Rect r = mAttachInfo.mTmpInvalRect;
8539                    getDrawingRect(r);
8540                    return requestRectangleOnScreen(r, true);
8541                }
8542            } break;
8543        }
8544        return false;
8545    }
8546
8547    private boolean traverseAtGranularity(int granularity, boolean forward,
8548            boolean extendSelection) {
8549        CharSequence text = getIterableTextForAccessibility();
8550        if (text == null || text.length() == 0) {
8551            return false;
8552        }
8553        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8554        if (iterator == null) {
8555            return false;
8556        }
8557        int current = getAccessibilitySelectionEnd();
8558        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8559            current = forward ? 0 : text.length();
8560        }
8561        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8562        if (range == null) {
8563            return false;
8564        }
8565        final int segmentStart = range[0];
8566        final int segmentEnd = range[1];
8567        int selectionStart;
8568        int selectionEnd;
8569        if (extendSelection && isAccessibilitySelectionExtendable()) {
8570            selectionStart = getAccessibilitySelectionStart();
8571            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8572                selectionStart = forward ? segmentStart : segmentEnd;
8573            }
8574            selectionEnd = forward ? segmentEnd : segmentStart;
8575        } else {
8576            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8577        }
8578        setAccessibilitySelection(selectionStart, selectionEnd);
8579        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8580                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8581        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8582        return true;
8583    }
8584
8585    /**
8586     * Gets the text reported for accessibility purposes.
8587     *
8588     * @return The accessibility text.
8589     *
8590     * @hide
8591     */
8592    public CharSequence getIterableTextForAccessibility() {
8593        return getContentDescription();
8594    }
8595
8596    /**
8597     * Gets whether accessibility selection can be extended.
8598     *
8599     * @return If selection is extensible.
8600     *
8601     * @hide
8602     */
8603    public boolean isAccessibilitySelectionExtendable() {
8604        return false;
8605    }
8606
8607    /**
8608     * @hide
8609     */
8610    public int getAccessibilitySelectionStart() {
8611        return mAccessibilityCursorPosition;
8612    }
8613
8614    /**
8615     * @hide
8616     */
8617    public int getAccessibilitySelectionEnd() {
8618        return getAccessibilitySelectionStart();
8619    }
8620
8621    /**
8622     * @hide
8623     */
8624    public void setAccessibilitySelection(int start, int end) {
8625        if (start ==  end && end == mAccessibilityCursorPosition) {
8626            return;
8627        }
8628        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8629            mAccessibilityCursorPosition = start;
8630        } else {
8631            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8632        }
8633        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8634    }
8635
8636    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8637            int fromIndex, int toIndex) {
8638        if (mParent == null) {
8639            return;
8640        }
8641        AccessibilityEvent event = AccessibilityEvent.obtain(
8642                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8643        onInitializeAccessibilityEvent(event);
8644        onPopulateAccessibilityEvent(event);
8645        event.setFromIndex(fromIndex);
8646        event.setToIndex(toIndex);
8647        event.setAction(action);
8648        event.setMovementGranularity(granularity);
8649        mParent.requestSendAccessibilityEvent(this, event);
8650    }
8651
8652    /**
8653     * @hide
8654     */
8655    public TextSegmentIterator getIteratorForGranularity(int granularity) {
8656        switch (granularity) {
8657            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8658                CharSequence text = getIterableTextForAccessibility();
8659                if (text != null && text.length() > 0) {
8660                    CharacterTextSegmentIterator iterator =
8661                        CharacterTextSegmentIterator.getInstance(
8662                                mContext.getResources().getConfiguration().locale);
8663                    iterator.initialize(text.toString());
8664                    return iterator;
8665                }
8666            } break;
8667            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8668                CharSequence text = getIterableTextForAccessibility();
8669                if (text != null && text.length() > 0) {
8670                    WordTextSegmentIterator iterator =
8671                        WordTextSegmentIterator.getInstance(
8672                                mContext.getResources().getConfiguration().locale);
8673                    iterator.initialize(text.toString());
8674                    return iterator;
8675                }
8676            } break;
8677            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8678                CharSequence text = getIterableTextForAccessibility();
8679                if (text != null && text.length() > 0) {
8680                    ParagraphTextSegmentIterator iterator =
8681                        ParagraphTextSegmentIterator.getInstance();
8682                    iterator.initialize(text.toString());
8683                    return iterator;
8684                }
8685            } break;
8686        }
8687        return null;
8688    }
8689
8690    /**
8691     * @hide
8692     */
8693    public void dispatchStartTemporaryDetach() {
8694        onStartTemporaryDetach();
8695    }
8696
8697    /**
8698     * This is called when a container is going to temporarily detach a child, with
8699     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8700     * It will either be followed by {@link #onFinishTemporaryDetach()} or
8701     * {@link #onDetachedFromWindow()} when the container is done.
8702     */
8703    public void onStartTemporaryDetach() {
8704        removeUnsetPressCallback();
8705        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8706    }
8707
8708    /**
8709     * @hide
8710     */
8711    public void dispatchFinishTemporaryDetach() {
8712        onFinishTemporaryDetach();
8713    }
8714
8715    /**
8716     * Called after {@link #onStartTemporaryDetach} when the container is done
8717     * changing the view.
8718     */
8719    public void onFinishTemporaryDetach() {
8720    }
8721
8722    /**
8723     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8724     * for this view's window.  Returns null if the view is not currently attached
8725     * to the window.  Normally you will not need to use this directly, but
8726     * just use the standard high-level event callbacks like
8727     * {@link #onKeyDown(int, KeyEvent)}.
8728     */
8729    public KeyEvent.DispatcherState getKeyDispatcherState() {
8730        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8731    }
8732
8733    /**
8734     * Dispatch a key event before it is processed by any input method
8735     * associated with the view hierarchy.  This can be used to intercept
8736     * key events in special situations before the IME consumes them; a
8737     * typical example would be handling the BACK key to update the application's
8738     * UI instead of allowing the IME to see it and close itself.
8739     *
8740     * @param event The key event to be dispatched.
8741     * @return True if the event was handled, false otherwise.
8742     */
8743    public boolean dispatchKeyEventPreIme(KeyEvent event) {
8744        return onKeyPreIme(event.getKeyCode(), event);
8745    }
8746
8747    /**
8748     * Dispatch a key event to the next view on the focus path. This path runs
8749     * from the top of the view tree down to the currently focused view. If this
8750     * view has focus, it will dispatch to itself. Otherwise it will dispatch
8751     * the next node down the focus path. This method also fires any key
8752     * listeners.
8753     *
8754     * @param event The key event to be dispatched.
8755     * @return True if the event was handled, false otherwise.
8756     */
8757    public boolean dispatchKeyEvent(KeyEvent event) {
8758        if (mInputEventConsistencyVerifier != null) {
8759            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8760        }
8761
8762        // Give any attached key listener a first crack at the event.
8763        //noinspection SimplifiableIfStatement
8764        ListenerInfo li = mListenerInfo;
8765        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8766                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8767            return true;
8768        }
8769
8770        if (event.dispatch(this, mAttachInfo != null
8771                ? mAttachInfo.mKeyDispatchState : null, this)) {
8772            return true;
8773        }
8774
8775        if (mInputEventConsistencyVerifier != null) {
8776            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8777        }
8778        return false;
8779    }
8780
8781    /**
8782     * Dispatches a key shortcut event.
8783     *
8784     * @param event The key event to be dispatched.
8785     * @return True if the event was handled by the view, false otherwise.
8786     */
8787    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8788        return onKeyShortcut(event.getKeyCode(), event);
8789    }
8790
8791    /**
8792     * Pass the touch screen motion event down to the target view, or this
8793     * view if it is the target.
8794     *
8795     * @param event The motion event to be dispatched.
8796     * @return True if the event was handled by the view, false otherwise.
8797     */
8798    public boolean dispatchTouchEvent(MotionEvent event) {
8799        // If the event should be handled by accessibility focus first.
8800        if (event.isTargetAccessibilityFocus()) {
8801            // We don't have focus or no virtual descendant has it, do not handle the event.
8802            if (!isAccessibilityFocusedViewOrHost()) {
8803                return false;
8804            }
8805            // We have focus and got the event, then use normal event dispatch.
8806            event.setTargetAccessibilityFocus(false);
8807        }
8808
8809        boolean result = false;
8810
8811        if (mInputEventConsistencyVerifier != null) {
8812            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8813        }
8814
8815        final int actionMasked = event.getActionMasked();
8816        if (actionMasked == MotionEvent.ACTION_DOWN) {
8817            // Defensive cleanup for new gesture
8818            stopNestedScroll();
8819        }
8820
8821        if (onFilterTouchEventForSecurity(event)) {
8822            //noinspection SimplifiableIfStatement
8823            ListenerInfo li = mListenerInfo;
8824            if (li != null && li.mOnTouchListener != null
8825                    && (mViewFlags & ENABLED_MASK) == ENABLED
8826                    && li.mOnTouchListener.onTouch(this, event)) {
8827                result = true;
8828            }
8829
8830            if (!result && onTouchEvent(event)) {
8831                result = true;
8832            }
8833        }
8834
8835        if (!result && mInputEventConsistencyVerifier != null) {
8836            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8837        }
8838
8839        // Clean up after nested scrolls if this is the end of a gesture;
8840        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8841        // of the gesture.
8842        if (actionMasked == MotionEvent.ACTION_UP ||
8843                actionMasked == MotionEvent.ACTION_CANCEL ||
8844                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8845            stopNestedScroll();
8846        }
8847
8848        return result;
8849    }
8850
8851    boolean isAccessibilityFocusedViewOrHost() {
8852        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
8853                .getAccessibilityFocusedHost() == this);
8854    }
8855
8856    /**
8857     * Filter the touch event to apply security policies.
8858     *
8859     * @param event The motion event to be filtered.
8860     * @return True if the event should be dispatched, false if the event should be dropped.
8861     *
8862     * @see #getFilterTouchesWhenObscured
8863     */
8864    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8865        //noinspection RedundantIfStatement
8866        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8867                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8868            // Window is obscured, drop this touch.
8869            return false;
8870        }
8871        return true;
8872    }
8873
8874    /**
8875     * Pass a trackball motion event down to the focused view.
8876     *
8877     * @param event The motion event to be dispatched.
8878     * @return True if the event was handled by the view, false otherwise.
8879     */
8880    public boolean dispatchTrackballEvent(MotionEvent event) {
8881        if (mInputEventConsistencyVerifier != null) {
8882            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8883        }
8884
8885        return onTrackballEvent(event);
8886    }
8887
8888    /**
8889     * Dispatch a generic motion event.
8890     * <p>
8891     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8892     * are delivered to the view under the pointer.  All other generic motion events are
8893     * delivered to the focused view.  Hover events are handled specially and are delivered
8894     * to {@link #onHoverEvent(MotionEvent)}.
8895     * </p>
8896     *
8897     * @param event The motion event to be dispatched.
8898     * @return True if the event was handled by the view, false otherwise.
8899     */
8900    public boolean dispatchGenericMotionEvent(MotionEvent event) {
8901        if (mInputEventConsistencyVerifier != null) {
8902            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8903        }
8904
8905        final int source = event.getSource();
8906        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8907            final int action = event.getAction();
8908            if (action == MotionEvent.ACTION_HOVER_ENTER
8909                    || action == MotionEvent.ACTION_HOVER_MOVE
8910                    || action == MotionEvent.ACTION_HOVER_EXIT) {
8911                if (dispatchHoverEvent(event)) {
8912                    return true;
8913                }
8914            } else if (dispatchGenericPointerEvent(event)) {
8915                return true;
8916            }
8917        } else if (dispatchGenericFocusedEvent(event)) {
8918            return true;
8919        }
8920
8921        if (dispatchGenericMotionEventInternal(event)) {
8922            return true;
8923        }
8924
8925        if (mInputEventConsistencyVerifier != null) {
8926            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8927        }
8928        return false;
8929    }
8930
8931    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8932        //noinspection SimplifiableIfStatement
8933        ListenerInfo li = mListenerInfo;
8934        if (li != null && li.mOnGenericMotionListener != null
8935                && (mViewFlags & ENABLED_MASK) == ENABLED
8936                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8937            return true;
8938        }
8939
8940        if (onGenericMotionEvent(event)) {
8941            return true;
8942        }
8943
8944        if (mInputEventConsistencyVerifier != null) {
8945            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8946        }
8947        return false;
8948    }
8949
8950    /**
8951     * Dispatch a hover event.
8952     * <p>
8953     * Do not call this method directly.
8954     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8955     * </p>
8956     *
8957     * @param event The motion event to be dispatched.
8958     * @return True if the event was handled by the view, false otherwise.
8959     */
8960    protected boolean dispatchHoverEvent(MotionEvent event) {
8961        ListenerInfo li = mListenerInfo;
8962        //noinspection SimplifiableIfStatement
8963        if (li != null && li.mOnHoverListener != null
8964                && (mViewFlags & ENABLED_MASK) == ENABLED
8965                && li.mOnHoverListener.onHover(this, event)) {
8966            return true;
8967        }
8968
8969        return onHoverEvent(event);
8970    }
8971
8972    /**
8973     * Returns true if the view has a child to which it has recently sent
8974     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8975     * it does not have a hovered child, then it must be the innermost hovered view.
8976     * @hide
8977     */
8978    protected boolean hasHoveredChild() {
8979        return false;
8980    }
8981
8982    /**
8983     * Dispatch a generic motion event to the view under the first pointer.
8984     * <p>
8985     * Do not call this method directly.
8986     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8987     * </p>
8988     *
8989     * @param event The motion event to be dispatched.
8990     * @return True if the event was handled by the view, false otherwise.
8991     */
8992    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8993        return false;
8994    }
8995
8996    /**
8997     * Dispatch a generic motion event to the currently focused view.
8998     * <p>
8999     * Do not call this method directly.
9000     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9001     * </p>
9002     *
9003     * @param event The motion event to be dispatched.
9004     * @return True if the event was handled by the view, false otherwise.
9005     */
9006    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9007        return false;
9008    }
9009
9010    /**
9011     * Dispatch a pointer event.
9012     * <p>
9013     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9014     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9015     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9016     * and should not be expected to handle other pointing device features.
9017     * </p>
9018     *
9019     * @param event The motion event to be dispatched.
9020     * @return True if the event was handled by the view, false otherwise.
9021     * @hide
9022     */
9023    public final boolean dispatchPointerEvent(MotionEvent event) {
9024        if (event.isTouchEvent()) {
9025            return dispatchTouchEvent(event);
9026        } else {
9027            return dispatchGenericMotionEvent(event);
9028        }
9029    }
9030
9031    /**
9032     * Called when the window containing this view gains or loses window focus.
9033     * ViewGroups should override to route to their children.
9034     *
9035     * @param hasFocus True if the window containing this view now has focus,
9036     *        false otherwise.
9037     */
9038    public void dispatchWindowFocusChanged(boolean hasFocus) {
9039        onWindowFocusChanged(hasFocus);
9040    }
9041
9042    /**
9043     * Called when the window containing this view gains or loses focus.  Note
9044     * that this is separate from view focus: to receive key events, both
9045     * your view and its window must have focus.  If a window is displayed
9046     * on top of yours that takes input focus, then your own window will lose
9047     * focus but the view focus will remain unchanged.
9048     *
9049     * @param hasWindowFocus True if the window containing this view now has
9050     *        focus, false otherwise.
9051     */
9052    public void onWindowFocusChanged(boolean hasWindowFocus) {
9053        InputMethodManager imm = InputMethodManager.peekInstance();
9054        if (!hasWindowFocus) {
9055            if (isPressed()) {
9056                setPressed(false);
9057            }
9058            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9059                imm.focusOut(this);
9060            }
9061            removeLongPressCallback();
9062            removeTapCallback();
9063            onFocusLost();
9064        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9065            imm.focusIn(this);
9066        }
9067        refreshDrawableState();
9068    }
9069
9070    /**
9071     * Returns true if this view is in a window that currently has window focus.
9072     * Note that this is not the same as the view itself having focus.
9073     *
9074     * @return True if this view is in a window that currently has window focus.
9075     */
9076    public boolean hasWindowFocus() {
9077        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9078    }
9079
9080    /**
9081     * Dispatch a view visibility change down the view hierarchy.
9082     * ViewGroups should override to route to their children.
9083     * @param changedView The view whose visibility changed. Could be 'this' or
9084     * an ancestor view.
9085     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9086     * {@link #INVISIBLE} or {@link #GONE}.
9087     */
9088    protected void dispatchVisibilityChanged(@NonNull View changedView,
9089            @Visibility int visibility) {
9090        onVisibilityChanged(changedView, visibility);
9091    }
9092
9093    /**
9094     * Called when the visibility of the view or an ancestor of the view has
9095     * changed.
9096     *
9097     * @param changedView The view whose visibility changed. May be
9098     *                    {@code this} or an ancestor view.
9099     * @param visibility The new visibility, one of {@link #VISIBLE},
9100     *                   {@link #INVISIBLE} or {@link #GONE}.
9101     */
9102    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9103        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9104        if (visible) {
9105            if (mAttachInfo != null) {
9106                initialAwakenScrollBars();
9107            } else {
9108                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
9109            }
9110        }
9111
9112        final Drawable dr = mBackground;
9113        if (dr != null && visible != dr.isVisible()) {
9114            dr.setVisible(visible, false);
9115        }
9116        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9117        if (fg != null && visible != fg.isVisible()) {
9118            fg.setVisible(visible, false);
9119        }
9120    }
9121
9122    /**
9123     * Dispatch a hint about whether this view is displayed. For instance, when
9124     * a View moves out of the screen, it might receives a display hint indicating
9125     * the view is not displayed. Applications should not <em>rely</em> on this hint
9126     * as there is no guarantee that they will receive one.
9127     *
9128     * @param hint A hint about whether or not this view is displayed:
9129     * {@link #VISIBLE} or {@link #INVISIBLE}.
9130     */
9131    public void dispatchDisplayHint(@Visibility int hint) {
9132        onDisplayHint(hint);
9133    }
9134
9135    /**
9136     * Gives this view a hint about whether is displayed or not. For instance, when
9137     * a View moves out of the screen, it might receives a display hint indicating
9138     * the view is not displayed. Applications should not <em>rely</em> on this hint
9139     * as there is no guarantee that they will receive one.
9140     *
9141     * @param hint A hint about whether or not this view is displayed:
9142     * {@link #VISIBLE} or {@link #INVISIBLE}.
9143     */
9144    protected void onDisplayHint(@Visibility int hint) {
9145    }
9146
9147    /**
9148     * Dispatch a window visibility change down the view hierarchy.
9149     * ViewGroups should override to route to their children.
9150     *
9151     * @param visibility The new visibility of the window.
9152     *
9153     * @see #onWindowVisibilityChanged(int)
9154     */
9155    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9156        onWindowVisibilityChanged(visibility);
9157    }
9158
9159    /**
9160     * Called when the window containing has change its visibility
9161     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9162     * that this tells you whether or not your window is being made visible
9163     * to the window manager; this does <em>not</em> tell you whether or not
9164     * your window is obscured by other windows on the screen, even if it
9165     * is itself visible.
9166     *
9167     * @param visibility The new visibility of the window.
9168     */
9169    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9170        if (visibility == VISIBLE) {
9171            initialAwakenScrollBars();
9172        }
9173    }
9174
9175    /**
9176     * Returns the current visibility of the window this view is attached to
9177     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9178     *
9179     * @return Returns the current visibility of the view's window.
9180     */
9181    @Visibility
9182    public int getWindowVisibility() {
9183        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9184    }
9185
9186    /**
9187     * Retrieve the overall visible display size in which the window this view is
9188     * attached to has been positioned in.  This takes into account screen
9189     * decorations above the window, for both cases where the window itself
9190     * is being position inside of them or the window is being placed under
9191     * then and covered insets are used for the window to position its content
9192     * inside.  In effect, this tells you the available area where content can
9193     * be placed and remain visible to users.
9194     *
9195     * <p>This function requires an IPC back to the window manager to retrieve
9196     * the requested information, so should not be used in performance critical
9197     * code like drawing.
9198     *
9199     * @param outRect Filled in with the visible display frame.  If the view
9200     * is not attached to a window, this is simply the raw display size.
9201     */
9202    public void getWindowVisibleDisplayFrame(Rect outRect) {
9203        if (mAttachInfo != null) {
9204            try {
9205                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9206            } catch (RemoteException e) {
9207                return;
9208            }
9209            // XXX This is really broken, and probably all needs to be done
9210            // in the window manager, and we need to know more about whether
9211            // we want the area behind or in front of the IME.
9212            final Rect insets = mAttachInfo.mVisibleInsets;
9213            outRect.left += insets.left;
9214            outRect.top += insets.top;
9215            outRect.right -= insets.right;
9216            outRect.bottom -= insets.bottom;
9217            return;
9218        }
9219        // The view is not attached to a display so we don't have a context.
9220        // Make a best guess about the display size.
9221        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9222        d.getRectSize(outRect);
9223    }
9224
9225    /**
9226     * Dispatch a notification about a resource configuration change down
9227     * the view hierarchy.
9228     * ViewGroups should override to route to their children.
9229     *
9230     * @param newConfig The new resource configuration.
9231     *
9232     * @see #onConfigurationChanged(android.content.res.Configuration)
9233     */
9234    public void dispatchConfigurationChanged(Configuration newConfig) {
9235        onConfigurationChanged(newConfig);
9236    }
9237
9238    /**
9239     * Called when the current configuration of the resources being used
9240     * by the application have changed.  You can use this to decide when
9241     * to reload resources that can changed based on orientation and other
9242     * configuration characteristics.  You only need to use this if you are
9243     * not relying on the normal {@link android.app.Activity} mechanism of
9244     * recreating the activity instance upon a configuration change.
9245     *
9246     * @param newConfig The new resource configuration.
9247     */
9248    protected void onConfigurationChanged(Configuration newConfig) {
9249    }
9250
9251    /**
9252     * Private function to aggregate all per-view attributes in to the view
9253     * root.
9254     */
9255    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9256        performCollectViewAttributes(attachInfo, visibility);
9257    }
9258
9259    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9260        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9261            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9262                attachInfo.mKeepScreenOn = true;
9263            }
9264            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9265            ListenerInfo li = mListenerInfo;
9266            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9267                attachInfo.mHasSystemUiListeners = true;
9268            }
9269        }
9270    }
9271
9272    void needGlobalAttributesUpdate(boolean force) {
9273        final AttachInfo ai = mAttachInfo;
9274        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9275            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9276                    || ai.mHasSystemUiListeners) {
9277                ai.mRecomputeGlobalAttributes = true;
9278            }
9279        }
9280    }
9281
9282    /**
9283     * Returns whether the device is currently in touch mode.  Touch mode is entered
9284     * once the user begins interacting with the device by touch, and affects various
9285     * things like whether focus is always visible to the user.
9286     *
9287     * @return Whether the device is in touch mode.
9288     */
9289    @ViewDebug.ExportedProperty
9290    public boolean isInTouchMode() {
9291        if (mAttachInfo != null) {
9292            return mAttachInfo.mInTouchMode;
9293        } else {
9294            return ViewRootImpl.isInTouchMode();
9295        }
9296    }
9297
9298    /**
9299     * Returns the context the view is running in, through which it can
9300     * access the current theme, resources, etc.
9301     *
9302     * @return The view's Context.
9303     */
9304    @ViewDebug.CapturedViewProperty
9305    public final Context getContext() {
9306        return mContext;
9307    }
9308
9309    /**
9310     * Handle a key event before it is processed by any input method
9311     * associated with the view hierarchy.  This can be used to intercept
9312     * key events in special situations before the IME consumes them; a
9313     * typical example would be handling the BACK key to update the application's
9314     * UI instead of allowing the IME to see it and close itself.
9315     *
9316     * @param keyCode The value in event.getKeyCode().
9317     * @param event Description of the key event.
9318     * @return If you handled the event, return true. If you want to allow the
9319     *         event to be handled by the next receiver, return false.
9320     */
9321    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9322        return false;
9323    }
9324
9325    /**
9326     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9327     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9328     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9329     * is released, if the view is enabled and clickable.
9330     *
9331     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9332     * although some may elect to do so in some situations. Do not rely on this to
9333     * catch software key presses.
9334     *
9335     * @param keyCode A key code that represents the button pressed, from
9336     *                {@link android.view.KeyEvent}.
9337     * @param event   The KeyEvent object that defines the button action.
9338     */
9339    public boolean onKeyDown(int keyCode, KeyEvent event) {
9340        boolean result = false;
9341
9342        if (KeyEvent.isConfirmKey(keyCode)) {
9343            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9344                return true;
9345            }
9346            // Long clickable items don't necessarily have to be clickable
9347            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9348                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9349                    (event.getRepeatCount() == 0)) {
9350                setPressed(true);
9351                checkForLongClick(0);
9352                return true;
9353            }
9354        }
9355        return result;
9356    }
9357
9358    /**
9359     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9360     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9361     * the event).
9362     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9363     * although some may elect to do so in some situations. Do not rely on this to
9364     * catch software key presses.
9365     */
9366    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9367        return false;
9368    }
9369
9370    /**
9371     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9372     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9373     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9374     * {@link KeyEvent#KEYCODE_ENTER} is released.
9375     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9376     * although some may elect to do so in some situations. Do not rely on this to
9377     * catch software key presses.
9378     *
9379     * @param keyCode A key code that represents the button pressed, from
9380     *                {@link android.view.KeyEvent}.
9381     * @param event   The KeyEvent object that defines the button action.
9382     */
9383    public boolean onKeyUp(int keyCode, KeyEvent event) {
9384        if (KeyEvent.isConfirmKey(keyCode)) {
9385            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9386                return true;
9387            }
9388            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9389                setPressed(false);
9390
9391                if (!mHasPerformedLongPress) {
9392                    // This is a tap, so remove the longpress check
9393                    removeLongPressCallback();
9394                    return performClick();
9395                }
9396            }
9397        }
9398        return false;
9399    }
9400
9401    /**
9402     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9403     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9404     * the event).
9405     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9406     * although some may elect to do so in some situations. Do not rely on this to
9407     * catch software key presses.
9408     *
9409     * @param keyCode     A key code that represents the button pressed, from
9410     *                    {@link android.view.KeyEvent}.
9411     * @param repeatCount The number of times the action was made.
9412     * @param event       The KeyEvent object that defines the button action.
9413     */
9414    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9415        return false;
9416    }
9417
9418    /**
9419     * Called on the focused view when a key shortcut event is not handled.
9420     * Override this method to implement local key shortcuts for the View.
9421     * Key shortcuts can also be implemented by setting the
9422     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9423     *
9424     * @param keyCode The value in event.getKeyCode().
9425     * @param event Description of the key event.
9426     * @return If you handled the event, return true. If you want to allow the
9427     *         event to be handled by the next receiver, return false.
9428     */
9429    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9430        return false;
9431    }
9432
9433    /**
9434     * Check whether the called view is a text editor, in which case it
9435     * would make sense to automatically display a soft input window for
9436     * it.  Subclasses should override this if they implement
9437     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9438     * a call on that method would return a non-null InputConnection, and
9439     * they are really a first-class editor that the user would normally
9440     * start typing on when the go into a window containing your view.
9441     *
9442     * <p>The default implementation always returns false.  This does
9443     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9444     * will not be called or the user can not otherwise perform edits on your
9445     * view; it is just a hint to the system that this is not the primary
9446     * purpose of this view.
9447     *
9448     * @return Returns true if this view is a text editor, else false.
9449     */
9450    public boolean onCheckIsTextEditor() {
9451        return false;
9452    }
9453
9454    /**
9455     * Create a new InputConnection for an InputMethod to interact
9456     * with the view.  The default implementation returns null, since it doesn't
9457     * support input methods.  You can override this to implement such support.
9458     * This is only needed for views that take focus and text input.
9459     *
9460     * <p>When implementing this, you probably also want to implement
9461     * {@link #onCheckIsTextEditor()} to indicate you will return a
9462     * non-null InputConnection.</p>
9463     *
9464     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9465     * object correctly and in its entirety, so that the connected IME can rely
9466     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9467     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9468     * must be filled in with the correct cursor position for IMEs to work correctly
9469     * with your application.</p>
9470     *
9471     * @param outAttrs Fill in with attribute information about the connection.
9472     */
9473    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9474        return null;
9475    }
9476
9477    /**
9478     * Called by the {@link android.view.inputmethod.InputMethodManager}
9479     * when a view who is not the current
9480     * input connection target is trying to make a call on the manager.  The
9481     * default implementation returns false; you can override this to return
9482     * true for certain views if you are performing InputConnection proxying
9483     * to them.
9484     * @param view The View that is making the InputMethodManager call.
9485     * @return Return true to allow the call, false to reject.
9486     */
9487    public boolean checkInputConnectionProxy(View view) {
9488        return false;
9489    }
9490
9491    /**
9492     * Show the context menu for this view. It is not safe to hold on to the
9493     * menu after returning from this method.
9494     *
9495     * You should normally not overload this method. Overload
9496     * {@link #onCreateContextMenu(ContextMenu)} or define an
9497     * {@link OnCreateContextMenuListener} to add items to the context menu.
9498     *
9499     * @param menu The context menu to populate
9500     */
9501    public void createContextMenu(ContextMenu menu) {
9502        ContextMenuInfo menuInfo = getContextMenuInfo();
9503
9504        // Sets the current menu info so all items added to menu will have
9505        // my extra info set.
9506        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9507
9508        onCreateContextMenu(menu);
9509        ListenerInfo li = mListenerInfo;
9510        if (li != null && li.mOnCreateContextMenuListener != null) {
9511            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9512        }
9513
9514        // Clear the extra information so subsequent items that aren't mine don't
9515        // have my extra info.
9516        ((MenuBuilder)menu).setCurrentMenuInfo(null);
9517
9518        if (mParent != null) {
9519            mParent.createContextMenu(menu);
9520        }
9521    }
9522
9523    /**
9524     * Views should implement this if they have extra information to associate
9525     * with the context menu. The return result is supplied as a parameter to
9526     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9527     * callback.
9528     *
9529     * @return Extra information about the item for which the context menu
9530     *         should be shown. This information will vary across different
9531     *         subclasses of View.
9532     */
9533    protected ContextMenuInfo getContextMenuInfo() {
9534        return null;
9535    }
9536
9537    /**
9538     * Views should implement this if the view itself is going to add items to
9539     * the context menu.
9540     *
9541     * @param menu the context menu to populate
9542     */
9543    protected void onCreateContextMenu(ContextMenu menu) {
9544    }
9545
9546    /**
9547     * Implement this method to handle trackball motion events.  The
9548     * <em>relative</em> movement of the trackball since the last event
9549     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9550     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
9551     * that a movement of 1 corresponds to the user pressing one DPAD key (so
9552     * they will often be fractional values, representing the more fine-grained
9553     * movement information available from a trackball).
9554     *
9555     * @param event The motion event.
9556     * @return True if the event was handled, false otherwise.
9557     */
9558    public boolean onTrackballEvent(MotionEvent event) {
9559        return false;
9560    }
9561
9562    /**
9563     * Implement this method to handle generic motion events.
9564     * <p>
9565     * Generic motion events describe joystick movements, mouse hovers, track pad
9566     * touches, scroll wheel movements and other input events.  The
9567     * {@link MotionEvent#getSource() source} of the motion event specifies
9568     * the class of input that was received.  Implementations of this method
9569     * must examine the bits in the source before processing the event.
9570     * The following code example shows how this is done.
9571     * </p><p>
9572     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9573     * are delivered to the view under the pointer.  All other generic motion events are
9574     * delivered to the focused view.
9575     * </p>
9576     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9577     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9578     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
9579     *             // process the joystick movement...
9580     *             return true;
9581     *         }
9582     *     }
9583     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9584     *         switch (event.getAction()) {
9585     *             case MotionEvent.ACTION_HOVER_MOVE:
9586     *                 // process the mouse hover movement...
9587     *                 return true;
9588     *             case MotionEvent.ACTION_SCROLL:
9589     *                 // process the scroll wheel movement...
9590     *                 return true;
9591     *         }
9592     *     }
9593     *     return super.onGenericMotionEvent(event);
9594     * }</pre>
9595     *
9596     * @param event The generic motion event being processed.
9597     * @return True if the event was handled, false otherwise.
9598     */
9599    public boolean onGenericMotionEvent(MotionEvent event) {
9600        return false;
9601    }
9602
9603    /**
9604     * Implement this method to handle hover events.
9605     * <p>
9606     * This method is called whenever a pointer is hovering into, over, or out of the
9607     * bounds of a view and the view is not currently being touched.
9608     * Hover events are represented as pointer events with action
9609     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9610     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9611     * </p>
9612     * <ul>
9613     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9614     * when the pointer enters the bounds of the view.</li>
9615     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9616     * when the pointer has already entered the bounds of the view and has moved.</li>
9617     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9618     * when the pointer has exited the bounds of the view or when the pointer is
9619     * about to go down due to a button click, tap, or similar user action that
9620     * causes the view to be touched.</li>
9621     * </ul>
9622     * <p>
9623     * The view should implement this method to return true to indicate that it is
9624     * handling the hover event, such as by changing its drawable state.
9625     * </p><p>
9626     * The default implementation calls {@link #setHovered} to update the hovered state
9627     * of the view when a hover enter or hover exit event is received, if the view
9628     * is enabled and is clickable.  The default implementation also sends hover
9629     * accessibility events.
9630     * </p>
9631     *
9632     * @param event The motion event that describes the hover.
9633     * @return True if the view handled the hover event.
9634     *
9635     * @see #isHovered
9636     * @see #setHovered
9637     * @see #onHoverChanged
9638     */
9639    public boolean onHoverEvent(MotionEvent event) {
9640        // The root view may receive hover (or touch) events that are outside the bounds of
9641        // the window.  This code ensures that we only send accessibility events for
9642        // hovers that are actually within the bounds of the root view.
9643        final int action = event.getActionMasked();
9644        if (!mSendingHoverAccessibilityEvents) {
9645            if ((action == MotionEvent.ACTION_HOVER_ENTER
9646                    || action == MotionEvent.ACTION_HOVER_MOVE)
9647                    && !hasHoveredChild()
9648                    && pointInView(event.getX(), event.getY())) {
9649                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9650                mSendingHoverAccessibilityEvents = true;
9651            }
9652        } else {
9653            if (action == MotionEvent.ACTION_HOVER_EXIT
9654                    || (action == MotionEvent.ACTION_MOVE
9655                            && !pointInView(event.getX(), event.getY()))) {
9656                mSendingHoverAccessibilityEvents = false;
9657                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9658            }
9659        }
9660
9661        if (isHoverable()) {
9662            switch (action) {
9663                case MotionEvent.ACTION_HOVER_ENTER:
9664                    setHovered(true);
9665                    break;
9666                case MotionEvent.ACTION_HOVER_EXIT:
9667                    setHovered(false);
9668                    break;
9669            }
9670
9671            // Dispatch the event to onGenericMotionEvent before returning true.
9672            // This is to provide compatibility with existing applications that
9673            // handled HOVER_MOVE events in onGenericMotionEvent and that would
9674            // break because of the new default handling for hoverable views
9675            // in onHoverEvent.
9676            // Note that onGenericMotionEvent will be called by default when
9677            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9678            dispatchGenericMotionEventInternal(event);
9679            // The event was already handled by calling setHovered(), so always
9680            // return true.
9681            return true;
9682        }
9683
9684        return false;
9685    }
9686
9687    /**
9688     * Returns true if the view should handle {@link #onHoverEvent}
9689     * by calling {@link #setHovered} to change its hovered state.
9690     *
9691     * @return True if the view is hoverable.
9692     */
9693    private boolean isHoverable() {
9694        final int viewFlags = mViewFlags;
9695        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9696            return false;
9697        }
9698
9699        return (viewFlags & CLICKABLE) == CLICKABLE
9700                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9701    }
9702
9703    /**
9704     * Returns true if the view is currently hovered.
9705     *
9706     * @return True if the view is currently hovered.
9707     *
9708     * @see #setHovered
9709     * @see #onHoverChanged
9710     */
9711    @ViewDebug.ExportedProperty
9712    public boolean isHovered() {
9713        return (mPrivateFlags & PFLAG_HOVERED) != 0;
9714    }
9715
9716    /**
9717     * Sets whether the view is currently hovered.
9718     * <p>
9719     * Calling this method also changes the drawable state of the view.  This
9720     * enables the view to react to hover by using different drawable resources
9721     * to change its appearance.
9722     * </p><p>
9723     * The {@link #onHoverChanged} method is called when the hovered state changes.
9724     * </p>
9725     *
9726     * @param hovered True if the view is hovered.
9727     *
9728     * @see #isHovered
9729     * @see #onHoverChanged
9730     */
9731    public void setHovered(boolean hovered) {
9732        if (hovered) {
9733            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9734                mPrivateFlags |= PFLAG_HOVERED;
9735                refreshDrawableState();
9736                onHoverChanged(true);
9737            }
9738        } else {
9739            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9740                mPrivateFlags &= ~PFLAG_HOVERED;
9741                refreshDrawableState();
9742                onHoverChanged(false);
9743            }
9744        }
9745    }
9746
9747    /**
9748     * Implement this method to handle hover state changes.
9749     * <p>
9750     * This method is called whenever the hover state changes as a result of a
9751     * call to {@link #setHovered}.
9752     * </p>
9753     *
9754     * @param hovered The current hover state, as returned by {@link #isHovered}.
9755     *
9756     * @see #isHovered
9757     * @see #setHovered
9758     */
9759    public void onHoverChanged(boolean hovered) {
9760    }
9761
9762    /**
9763     * Implement this method to handle touch screen motion events.
9764     * <p>
9765     * If this method is used to detect click actions, it is recommended that
9766     * the actions be performed by implementing and calling
9767     * {@link #performClick()}. This will ensure consistent system behavior,
9768     * including:
9769     * <ul>
9770     * <li>obeying click sound preferences
9771     * <li>dispatching OnClickListener calls
9772     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9773     * accessibility features are enabled
9774     * </ul>
9775     *
9776     * @param event The motion event.
9777     * @return True if the event was handled, false otherwise.
9778     */
9779    public boolean onTouchEvent(MotionEvent event) {
9780        final float x = event.getX();
9781        final float y = event.getY();
9782        final int viewFlags = mViewFlags;
9783
9784        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9785            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9786                setPressed(false);
9787            }
9788            // A disabled view that is clickable still consumes the touch
9789            // events, it just doesn't respond to them.
9790            return (((viewFlags & CLICKABLE) == CLICKABLE ||
9791                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9792        }
9793
9794        if (mTouchDelegate != null) {
9795            if (mTouchDelegate.onTouchEvent(event)) {
9796                return true;
9797            }
9798        }
9799
9800        if (((viewFlags & CLICKABLE) == CLICKABLE ||
9801                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9802            switch (event.getAction()) {
9803                case MotionEvent.ACTION_UP:
9804                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9805                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9806                        // take focus if we don't have it already and we should in
9807                        // touch mode.
9808                        boolean focusTaken = false;
9809                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9810                            focusTaken = requestFocus();
9811                        }
9812
9813                        if (prepressed) {
9814                            // The button is being released before we actually
9815                            // showed it as pressed.  Make it show the pressed
9816                            // state now (before scheduling the click) to ensure
9817                            // the user sees it.
9818                            setPressed(true, x, y);
9819                       }
9820
9821                        if (!mHasPerformedLongPress) {
9822                            // This is a tap, so remove the longpress check
9823                            removeLongPressCallback();
9824
9825                            // Only perform take click actions if we were in the pressed state
9826                            if (!focusTaken) {
9827                                // Use a Runnable and post this rather than calling
9828                                // performClick directly. This lets other visual state
9829                                // of the view update before click actions start.
9830                                if (mPerformClick == null) {
9831                                    mPerformClick = new PerformClick();
9832                                }
9833                                if (!post(mPerformClick)) {
9834                                    performClick();
9835                                }
9836                            }
9837                        }
9838
9839                        if (mUnsetPressedState == null) {
9840                            mUnsetPressedState = new UnsetPressedState();
9841                        }
9842
9843                        if (prepressed) {
9844                            postDelayed(mUnsetPressedState,
9845                                    ViewConfiguration.getPressedStateDuration());
9846                        } else if (!post(mUnsetPressedState)) {
9847                            // If the post failed, unpress right now
9848                            mUnsetPressedState.run();
9849                        }
9850
9851                        removeTapCallback();
9852                    }
9853                    break;
9854
9855                case MotionEvent.ACTION_DOWN:
9856                    mHasPerformedLongPress = false;
9857
9858                    if (performButtonActionOnTouchDown(event)) {
9859                        break;
9860                    }
9861
9862                    // Walk up the hierarchy to determine if we're inside a scrolling container.
9863                    boolean isInScrollingContainer = isInScrollingContainer();
9864
9865                    // For views inside a scrolling container, delay the pressed feedback for
9866                    // a short period in case this is a scroll.
9867                    if (isInScrollingContainer) {
9868                        mPrivateFlags |= PFLAG_PREPRESSED;
9869                        if (mPendingCheckForTap == null) {
9870                            mPendingCheckForTap = new CheckForTap();
9871                        }
9872                        mPendingCheckForTap.x = event.getX();
9873                        mPendingCheckForTap.y = event.getY();
9874                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9875                    } else {
9876                        // Not inside a scrolling container, so show the feedback right away
9877                        setPressed(true, x, y);
9878                        checkForLongClick(0);
9879                    }
9880                    break;
9881
9882                case MotionEvent.ACTION_CANCEL:
9883                    setPressed(false);
9884                    removeTapCallback();
9885                    removeLongPressCallback();
9886                    break;
9887
9888                case MotionEvent.ACTION_MOVE:
9889                    drawableHotspotChanged(x, y);
9890
9891                    // Be lenient about moving outside of buttons
9892                    if (!pointInView(x, y, mTouchSlop)) {
9893                        // Outside button
9894                        removeTapCallback();
9895                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9896                            // Remove any future long press/tap checks
9897                            removeLongPressCallback();
9898
9899                            setPressed(false);
9900                        }
9901                    }
9902                    break;
9903            }
9904
9905            return true;
9906        }
9907
9908        return false;
9909    }
9910
9911    /**
9912     * @hide
9913     */
9914    public boolean isInScrollingContainer() {
9915        ViewParent p = getParent();
9916        while (p != null && p instanceof ViewGroup) {
9917            if (((ViewGroup) p).shouldDelayChildPressedState()) {
9918                return true;
9919            }
9920            p = p.getParent();
9921        }
9922        return false;
9923    }
9924
9925    /**
9926     * Remove the longpress detection timer.
9927     */
9928    private void removeLongPressCallback() {
9929        if (mPendingCheckForLongPress != null) {
9930          removeCallbacks(mPendingCheckForLongPress);
9931        }
9932    }
9933
9934    /**
9935     * Remove the pending click action
9936     */
9937    private void removePerformClickCallback() {
9938        if (mPerformClick != null) {
9939            removeCallbacks(mPerformClick);
9940        }
9941    }
9942
9943    /**
9944     * Remove the prepress detection timer.
9945     */
9946    private void removeUnsetPressCallback() {
9947        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9948            setPressed(false);
9949            removeCallbacks(mUnsetPressedState);
9950        }
9951    }
9952
9953    /**
9954     * Remove the tap detection timer.
9955     */
9956    private void removeTapCallback() {
9957        if (mPendingCheckForTap != null) {
9958            mPrivateFlags &= ~PFLAG_PREPRESSED;
9959            removeCallbacks(mPendingCheckForTap);
9960        }
9961    }
9962
9963    /**
9964     * Cancels a pending long press.  Your subclass can use this if you
9965     * want the context menu to come up if the user presses and holds
9966     * at the same place, but you don't want it to come up if they press
9967     * and then move around enough to cause scrolling.
9968     */
9969    public void cancelLongPress() {
9970        removeLongPressCallback();
9971
9972        /*
9973         * The prepressed state handled by the tap callback is a display
9974         * construct, but the tap callback will post a long press callback
9975         * less its own timeout. Remove it here.
9976         */
9977        removeTapCallback();
9978    }
9979
9980    /**
9981     * Remove the pending callback for sending a
9982     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9983     */
9984    private void removeSendViewScrolledAccessibilityEventCallback() {
9985        if (mSendViewScrolledAccessibilityEvent != null) {
9986            removeCallbacks(mSendViewScrolledAccessibilityEvent);
9987            mSendViewScrolledAccessibilityEvent.mIsPending = false;
9988        }
9989    }
9990
9991    /**
9992     * Sets the TouchDelegate for this View.
9993     */
9994    public void setTouchDelegate(TouchDelegate delegate) {
9995        mTouchDelegate = delegate;
9996    }
9997
9998    /**
9999     * Gets the TouchDelegate for this View.
10000     */
10001    public TouchDelegate getTouchDelegate() {
10002        return mTouchDelegate;
10003    }
10004
10005    /**
10006     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10007     *
10008     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10009     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10010     * available. This method should only be called for touch events.
10011     *
10012     * <p class="note">This api is not intended for most applications. Buffered dispatch
10013     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10014     * streams will not improve your input latency. Side effects include: increased latency,
10015     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10016     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10017     * you.</p>
10018     */
10019    public final void requestUnbufferedDispatch(MotionEvent event) {
10020        final int action = event.getAction();
10021        if (mAttachInfo == null
10022                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10023                || !event.isTouchEvent()) {
10024            return;
10025        }
10026        mAttachInfo.mUnbufferedDispatchRequested = true;
10027    }
10028
10029    /**
10030     * Set flags controlling behavior of this view.
10031     *
10032     * @param flags Constant indicating the value which should be set
10033     * @param mask Constant indicating the bit range that should be changed
10034     */
10035    void setFlags(int flags, int mask) {
10036        final boolean accessibilityEnabled =
10037                AccessibilityManager.getInstance(mContext).isEnabled();
10038        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10039
10040        int old = mViewFlags;
10041        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10042
10043        int changed = mViewFlags ^ old;
10044        if (changed == 0) {
10045            return;
10046        }
10047        int privateFlags = mPrivateFlags;
10048
10049        /* Check if the FOCUSABLE bit has changed */
10050        if (((changed & FOCUSABLE_MASK) != 0) &&
10051                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10052            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10053                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10054                /* Give up focus if we are no longer focusable */
10055                clearFocus();
10056            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10057                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10058                /*
10059                 * Tell the view system that we are now available to take focus
10060                 * if no one else already has it.
10061                 */
10062                if (mParent != null) mParent.focusableViewAvailable(this);
10063            }
10064        }
10065
10066        final int newVisibility = flags & VISIBILITY_MASK;
10067        if (newVisibility == VISIBLE) {
10068            if ((changed & VISIBILITY_MASK) != 0) {
10069                /*
10070                 * If this view is becoming visible, invalidate it in case it changed while
10071                 * it was not visible. Marking it drawn ensures that the invalidation will
10072                 * go through.
10073                 */
10074                mPrivateFlags |= PFLAG_DRAWN;
10075                invalidate(true);
10076
10077                needGlobalAttributesUpdate(true);
10078
10079                // a view becoming visible is worth notifying the parent
10080                // about in case nothing has focus.  even if this specific view
10081                // isn't focusable, it may contain something that is, so let
10082                // the root view try to give this focus if nothing else does.
10083                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10084                    mParent.focusableViewAvailable(this);
10085                }
10086            }
10087        }
10088
10089        /* Check if the GONE bit has changed */
10090        if ((changed & GONE) != 0) {
10091            needGlobalAttributesUpdate(false);
10092            requestLayout();
10093
10094            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10095                if (hasFocus()) clearFocus();
10096                clearAccessibilityFocus();
10097                destroyDrawingCache();
10098                if (mParent instanceof View) {
10099                    // GONE views noop invalidation, so invalidate the parent
10100                    ((View) mParent).invalidate(true);
10101                }
10102                // Mark the view drawn to ensure that it gets invalidated properly the next
10103                // time it is visible and gets invalidated
10104                mPrivateFlags |= PFLAG_DRAWN;
10105            }
10106            if (mAttachInfo != null) {
10107                mAttachInfo.mViewVisibilityChanged = true;
10108            }
10109        }
10110
10111        /* Check if the VISIBLE bit has changed */
10112        if ((changed & INVISIBLE) != 0) {
10113            needGlobalAttributesUpdate(false);
10114            /*
10115             * If this view is becoming invisible, set the DRAWN flag so that
10116             * the next invalidate() will not be skipped.
10117             */
10118            mPrivateFlags |= PFLAG_DRAWN;
10119
10120            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10121                // root view becoming invisible shouldn't clear focus and accessibility focus
10122                if (getRootView() != this) {
10123                    if (hasFocus()) clearFocus();
10124                    clearAccessibilityFocus();
10125                }
10126            }
10127            if (mAttachInfo != null) {
10128                mAttachInfo.mViewVisibilityChanged = true;
10129            }
10130        }
10131
10132        if ((changed & VISIBILITY_MASK) != 0) {
10133            // If the view is invisible, cleanup its display list to free up resources
10134            if (newVisibility != VISIBLE && mAttachInfo != null) {
10135                cleanupDraw();
10136            }
10137
10138            if (mParent instanceof ViewGroup) {
10139                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10140                        (changed & VISIBILITY_MASK), newVisibility);
10141                ((View) mParent).invalidate(true);
10142            } else if (mParent != null) {
10143                mParent.invalidateChild(this, null);
10144            }
10145            dispatchVisibilityChanged(this, newVisibility);
10146
10147            notifySubtreeAccessibilityStateChangedIfNeeded();
10148        }
10149
10150        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10151            destroyDrawingCache();
10152        }
10153
10154        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10155            destroyDrawingCache();
10156            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10157            invalidateParentCaches();
10158        }
10159
10160        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10161            destroyDrawingCache();
10162            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10163        }
10164
10165        if ((changed & DRAW_MASK) != 0) {
10166            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10167                if (mBackground != null) {
10168                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10169                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
10170                } else {
10171                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10172                }
10173            } else {
10174                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10175            }
10176            requestLayout();
10177            invalidate(true);
10178        }
10179
10180        if ((changed & KEEP_SCREEN_ON) != 0) {
10181            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10182                mParent.recomputeViewAttributes(this);
10183            }
10184        }
10185
10186        if (accessibilityEnabled) {
10187            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10188                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
10189                if (oldIncludeForAccessibility != includeForAccessibility()) {
10190                    notifySubtreeAccessibilityStateChangedIfNeeded();
10191                } else {
10192                    notifyViewAccessibilityStateChangedIfNeeded(
10193                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10194                }
10195            } else if ((changed & ENABLED_MASK) != 0) {
10196                notifyViewAccessibilityStateChangedIfNeeded(
10197                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10198            }
10199        }
10200    }
10201
10202    /**
10203     * Change the view's z order in the tree, so it's on top of other sibling
10204     * views. This ordering change may affect layout, if the parent container
10205     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10206     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10207     * method should be followed by calls to {@link #requestLayout()} and
10208     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10209     * with the new child ordering.
10210     *
10211     * @see ViewGroup#bringChildToFront(View)
10212     */
10213    public void bringToFront() {
10214        if (mParent != null) {
10215            mParent.bringChildToFront(this);
10216        }
10217    }
10218
10219    /**
10220     * This is called in response to an internal scroll in this view (i.e., the
10221     * view scrolled its own contents). This is typically as a result of
10222     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10223     * called.
10224     *
10225     * @param l Current horizontal scroll origin.
10226     * @param t Current vertical scroll origin.
10227     * @param oldl Previous horizontal scroll origin.
10228     * @param oldt Previous vertical scroll origin.
10229     */
10230    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10231        notifySubtreeAccessibilityStateChangedIfNeeded();
10232
10233        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10234            postSendViewScrolledAccessibilityEventCallback();
10235        }
10236
10237        mBackgroundSizeChanged = true;
10238        if (mForegroundInfo != null) {
10239            mForegroundInfo.mBoundsChanged = true;
10240        }
10241
10242        final AttachInfo ai = mAttachInfo;
10243        if (ai != null) {
10244            ai.mViewScrollChanged = true;
10245        }
10246
10247        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10248            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10249        }
10250    }
10251
10252    /**
10253     * Interface definition for a callback to be invoked when the scroll
10254     * X or Y positions of a view change.
10255     * <p>
10256     * <b>Note:</b> Some views handle scrolling independently from View and may
10257     * have their own separate listeners for scroll-type events. For example,
10258     * {@link android.widget.ListView ListView} allows clients to register an
10259     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10260     * to listen for changes in list scroll position.
10261     *
10262     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10263     */
10264    public interface OnScrollChangeListener {
10265        /**
10266         * Called when the scroll position of a view changes.
10267         *
10268         * @param v The view whose scroll position has changed.
10269         * @param scrollX Current horizontal scroll origin.
10270         * @param scrollY Current vertical scroll origin.
10271         * @param oldScrollX Previous horizontal scroll origin.
10272         * @param oldScrollY Previous vertical scroll origin.
10273         */
10274        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10275    }
10276
10277    /**
10278     * Interface definition for a callback to be invoked when the layout bounds of a view
10279     * changes due to layout processing.
10280     */
10281    public interface OnLayoutChangeListener {
10282        /**
10283         * Called when the layout bounds of a view changes due to layout processing.
10284         *
10285         * @param v The view whose bounds have changed.
10286         * @param left The new value of the view's left property.
10287         * @param top The new value of the view's top property.
10288         * @param right The new value of the view's right property.
10289         * @param bottom The new value of the view's bottom property.
10290         * @param oldLeft The previous value of the view's left property.
10291         * @param oldTop The previous value of the view's top property.
10292         * @param oldRight The previous value of the view's right property.
10293         * @param oldBottom The previous value of the view's bottom property.
10294         */
10295        void onLayoutChange(View v, int left, int top, int right, int bottom,
10296            int oldLeft, int oldTop, int oldRight, int oldBottom);
10297    }
10298
10299    /**
10300     * This is called during layout when the size of this view has changed. If
10301     * you were just added to the view hierarchy, you're called with the old
10302     * values of 0.
10303     *
10304     * @param w Current width of this view.
10305     * @param h Current height of this view.
10306     * @param oldw Old width of this view.
10307     * @param oldh Old height of this view.
10308     */
10309    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10310    }
10311
10312    /**
10313     * Called by draw to draw the child views. This may be overridden
10314     * by derived classes to gain control just before its children are drawn
10315     * (but after its own view has been drawn).
10316     * @param canvas the canvas on which to draw the view
10317     */
10318    protected void dispatchDraw(Canvas canvas) {
10319
10320    }
10321
10322    /**
10323     * Gets the parent of this view. Note that the parent is a
10324     * ViewParent and not necessarily a View.
10325     *
10326     * @return Parent of this view.
10327     */
10328    public final ViewParent getParent() {
10329        return mParent;
10330    }
10331
10332    /**
10333     * Set the horizontal scrolled position of your view. This will cause a call to
10334     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10335     * invalidated.
10336     * @param value the x position to scroll to
10337     */
10338    public void setScrollX(int value) {
10339        scrollTo(value, mScrollY);
10340    }
10341
10342    /**
10343     * Set the vertical scrolled position of your view. This will cause a call to
10344     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10345     * invalidated.
10346     * @param value the y position to scroll to
10347     */
10348    public void setScrollY(int value) {
10349        scrollTo(mScrollX, value);
10350    }
10351
10352    /**
10353     * Return the scrolled left position of this view. This is the left edge of
10354     * the displayed part of your view. You do not need to draw any pixels
10355     * farther left, since those are outside of the frame of your view on
10356     * screen.
10357     *
10358     * @return The left edge of the displayed part of your view, in pixels.
10359     */
10360    public final int getScrollX() {
10361        return mScrollX;
10362    }
10363
10364    /**
10365     * Return the scrolled top position of this view. This is the top edge of
10366     * the displayed part of your view. You do not need to draw any pixels above
10367     * it, since those are outside of the frame of your view on screen.
10368     *
10369     * @return The top edge of the displayed part of your view, in pixels.
10370     */
10371    public final int getScrollY() {
10372        return mScrollY;
10373    }
10374
10375    /**
10376     * Return the width of the your view.
10377     *
10378     * @return The width of your view, in pixels.
10379     */
10380    @ViewDebug.ExportedProperty(category = "layout")
10381    public final int getWidth() {
10382        return mRight - mLeft;
10383    }
10384
10385    /**
10386     * Return the height of your view.
10387     *
10388     * @return The height of your view, in pixels.
10389     */
10390    @ViewDebug.ExportedProperty(category = "layout")
10391    public final int getHeight() {
10392        return mBottom - mTop;
10393    }
10394
10395    /**
10396     * Return the visible drawing bounds of your view. Fills in the output
10397     * rectangle with the values from getScrollX(), getScrollY(),
10398     * getWidth(), and getHeight(). These bounds do not account for any
10399     * transformation properties currently set on the view, such as
10400     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10401     *
10402     * @param outRect The (scrolled) drawing bounds of the view.
10403     */
10404    public void getDrawingRect(Rect outRect) {
10405        outRect.left = mScrollX;
10406        outRect.top = mScrollY;
10407        outRect.right = mScrollX + (mRight - mLeft);
10408        outRect.bottom = mScrollY + (mBottom - mTop);
10409    }
10410
10411    /**
10412     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10413     * raw width component (that is the result is masked by
10414     * {@link #MEASURED_SIZE_MASK}).
10415     *
10416     * @return The raw measured width of this view.
10417     */
10418    public final int getMeasuredWidth() {
10419        return mMeasuredWidth & MEASURED_SIZE_MASK;
10420    }
10421
10422    /**
10423     * Return the full width measurement information for this view as computed
10424     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10425     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10426     * This should be used during measurement and layout calculations only. Use
10427     * {@link #getWidth()} to see how wide a view is after layout.
10428     *
10429     * @return The measured width of this view as a bit mask.
10430     */
10431    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10432            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10433                    name = "MEASURED_STATE_TOO_SMALL"),
10434    })
10435    public final int getMeasuredWidthAndState() {
10436        return mMeasuredWidth;
10437    }
10438
10439    /**
10440     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10441     * raw width component (that is the result is masked by
10442     * {@link #MEASURED_SIZE_MASK}).
10443     *
10444     * @return The raw measured height of this view.
10445     */
10446    public final int getMeasuredHeight() {
10447        return mMeasuredHeight & MEASURED_SIZE_MASK;
10448    }
10449
10450    /**
10451     * Return the full height measurement information for this view as computed
10452     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10453     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10454     * This should be used during measurement and layout calculations only. Use
10455     * {@link #getHeight()} to see how wide a view is after layout.
10456     *
10457     * @return The measured width of this view as a bit mask.
10458     */
10459    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10460            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10461                    name = "MEASURED_STATE_TOO_SMALL"),
10462    })
10463    public final int getMeasuredHeightAndState() {
10464        return mMeasuredHeight;
10465    }
10466
10467    /**
10468     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10469     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10470     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10471     * and the height component is at the shifted bits
10472     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10473     */
10474    public final int getMeasuredState() {
10475        return (mMeasuredWidth&MEASURED_STATE_MASK)
10476                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10477                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10478    }
10479
10480    /**
10481     * The transform matrix of this view, which is calculated based on the current
10482     * rotation, scale, and pivot properties.
10483     *
10484     * @see #getRotation()
10485     * @see #getScaleX()
10486     * @see #getScaleY()
10487     * @see #getPivotX()
10488     * @see #getPivotY()
10489     * @return The current transform matrix for the view
10490     */
10491    public Matrix getMatrix() {
10492        ensureTransformationInfo();
10493        final Matrix matrix = mTransformationInfo.mMatrix;
10494        mRenderNode.getMatrix(matrix);
10495        return matrix;
10496    }
10497
10498    /**
10499     * Returns true if the transform matrix is the identity matrix.
10500     * Recomputes the matrix if necessary.
10501     *
10502     * @return True if the transform matrix is the identity matrix, false otherwise.
10503     */
10504    final boolean hasIdentityMatrix() {
10505        return mRenderNode.hasIdentityMatrix();
10506    }
10507
10508    void ensureTransformationInfo() {
10509        if (mTransformationInfo == null) {
10510            mTransformationInfo = new TransformationInfo();
10511        }
10512    }
10513
10514   /**
10515     * Utility method to retrieve the inverse of the current mMatrix property.
10516     * We cache the matrix to avoid recalculating it when transform properties
10517     * have not changed.
10518     *
10519     * @return The inverse of the current matrix of this view.
10520     * @hide
10521     */
10522    public final Matrix getInverseMatrix() {
10523        ensureTransformationInfo();
10524        if (mTransformationInfo.mInverseMatrix == null) {
10525            mTransformationInfo.mInverseMatrix = new Matrix();
10526        }
10527        final Matrix matrix = mTransformationInfo.mInverseMatrix;
10528        mRenderNode.getInverseMatrix(matrix);
10529        return matrix;
10530    }
10531
10532    /**
10533     * Gets the distance along the Z axis from the camera to this view.
10534     *
10535     * @see #setCameraDistance(float)
10536     *
10537     * @return The distance along the Z axis.
10538     */
10539    public float getCameraDistance() {
10540        final float dpi = mResources.getDisplayMetrics().densityDpi;
10541        return -(mRenderNode.getCameraDistance() * dpi);
10542    }
10543
10544    /**
10545     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10546     * views are drawn) from the camera to this view. The camera's distance
10547     * affects 3D transformations, for instance rotations around the X and Y
10548     * axis. If the rotationX or rotationY properties are changed and this view is
10549     * large (more than half the size of the screen), it is recommended to always
10550     * use a camera distance that's greater than the height (X axis rotation) or
10551     * the width (Y axis rotation) of this view.</p>
10552     *
10553     * <p>The distance of the camera from the view plane can have an affect on the
10554     * perspective distortion of the view when it is rotated around the x or y axis.
10555     * For example, a large distance will result in a large viewing angle, and there
10556     * will not be much perspective distortion of the view as it rotates. A short
10557     * distance may cause much more perspective distortion upon rotation, and can
10558     * also result in some drawing artifacts if the rotated view ends up partially
10559     * behind the camera (which is why the recommendation is to use a distance at
10560     * least as far as the size of the view, if the view is to be rotated.)</p>
10561     *
10562     * <p>The distance is expressed in "depth pixels." The default distance depends
10563     * on the screen density. For instance, on a medium density display, the
10564     * default distance is 1280. On a high density display, the default distance
10565     * is 1920.</p>
10566     *
10567     * <p>If you want to specify a distance that leads to visually consistent
10568     * results across various densities, use the following formula:</p>
10569     * <pre>
10570     * float scale = context.getResources().getDisplayMetrics().density;
10571     * view.setCameraDistance(distance * scale);
10572     * </pre>
10573     *
10574     * <p>The density scale factor of a high density display is 1.5,
10575     * and 1920 = 1280 * 1.5.</p>
10576     *
10577     * @param distance The distance in "depth pixels", if negative the opposite
10578     *        value is used
10579     *
10580     * @see #setRotationX(float)
10581     * @see #setRotationY(float)
10582     */
10583    public void setCameraDistance(float distance) {
10584        final float dpi = mResources.getDisplayMetrics().densityDpi;
10585
10586        invalidateViewProperty(true, false);
10587        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10588        invalidateViewProperty(false, false);
10589
10590        invalidateParentIfNeededAndWasQuickRejected();
10591    }
10592
10593    /**
10594     * The degrees that the view is rotated around the pivot point.
10595     *
10596     * @see #setRotation(float)
10597     * @see #getPivotX()
10598     * @see #getPivotY()
10599     *
10600     * @return The degrees of rotation.
10601     */
10602    @ViewDebug.ExportedProperty(category = "drawing")
10603    public float getRotation() {
10604        return mRenderNode.getRotation();
10605    }
10606
10607    /**
10608     * Sets the degrees that the view is rotated around the pivot point. Increasing values
10609     * result in clockwise rotation.
10610     *
10611     * @param rotation The degrees of rotation.
10612     *
10613     * @see #getRotation()
10614     * @see #getPivotX()
10615     * @see #getPivotY()
10616     * @see #setRotationX(float)
10617     * @see #setRotationY(float)
10618     *
10619     * @attr ref android.R.styleable#View_rotation
10620     */
10621    public void setRotation(float rotation) {
10622        if (rotation != getRotation()) {
10623            // Double-invalidation is necessary to capture view's old and new areas
10624            invalidateViewProperty(true, false);
10625            mRenderNode.setRotation(rotation);
10626            invalidateViewProperty(false, true);
10627
10628            invalidateParentIfNeededAndWasQuickRejected();
10629            notifySubtreeAccessibilityStateChangedIfNeeded();
10630        }
10631    }
10632
10633    /**
10634     * The degrees that the view is rotated around the vertical axis through the pivot point.
10635     *
10636     * @see #getPivotX()
10637     * @see #getPivotY()
10638     * @see #setRotationY(float)
10639     *
10640     * @return The degrees of Y rotation.
10641     */
10642    @ViewDebug.ExportedProperty(category = "drawing")
10643    public float getRotationY() {
10644        return mRenderNode.getRotationY();
10645    }
10646
10647    /**
10648     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10649     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10650     * down the y axis.
10651     *
10652     * When rotating large views, it is recommended to adjust the camera distance
10653     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10654     *
10655     * @param rotationY The degrees of Y rotation.
10656     *
10657     * @see #getRotationY()
10658     * @see #getPivotX()
10659     * @see #getPivotY()
10660     * @see #setRotation(float)
10661     * @see #setRotationX(float)
10662     * @see #setCameraDistance(float)
10663     *
10664     * @attr ref android.R.styleable#View_rotationY
10665     */
10666    public void setRotationY(float rotationY) {
10667        if (rotationY != getRotationY()) {
10668            invalidateViewProperty(true, false);
10669            mRenderNode.setRotationY(rotationY);
10670            invalidateViewProperty(false, true);
10671
10672            invalidateParentIfNeededAndWasQuickRejected();
10673            notifySubtreeAccessibilityStateChangedIfNeeded();
10674        }
10675    }
10676
10677    /**
10678     * The degrees that the view is rotated around the horizontal axis through the pivot point.
10679     *
10680     * @see #getPivotX()
10681     * @see #getPivotY()
10682     * @see #setRotationX(float)
10683     *
10684     * @return The degrees of X rotation.
10685     */
10686    @ViewDebug.ExportedProperty(category = "drawing")
10687    public float getRotationX() {
10688        return mRenderNode.getRotationX();
10689    }
10690
10691    /**
10692     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10693     * Increasing values result in clockwise rotation from the viewpoint of looking down the
10694     * x axis.
10695     *
10696     * When rotating large views, it is recommended to adjust the camera distance
10697     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10698     *
10699     * @param rotationX The degrees of X rotation.
10700     *
10701     * @see #getRotationX()
10702     * @see #getPivotX()
10703     * @see #getPivotY()
10704     * @see #setRotation(float)
10705     * @see #setRotationY(float)
10706     * @see #setCameraDistance(float)
10707     *
10708     * @attr ref android.R.styleable#View_rotationX
10709     */
10710    public void setRotationX(float rotationX) {
10711        if (rotationX != getRotationX()) {
10712            invalidateViewProperty(true, false);
10713            mRenderNode.setRotationX(rotationX);
10714            invalidateViewProperty(false, true);
10715
10716            invalidateParentIfNeededAndWasQuickRejected();
10717            notifySubtreeAccessibilityStateChangedIfNeeded();
10718        }
10719    }
10720
10721    /**
10722     * The amount that the view is scaled in x around the pivot point, as a proportion of
10723     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10724     *
10725     * <p>By default, this is 1.0f.
10726     *
10727     * @see #getPivotX()
10728     * @see #getPivotY()
10729     * @return The scaling factor.
10730     */
10731    @ViewDebug.ExportedProperty(category = "drawing")
10732    public float getScaleX() {
10733        return mRenderNode.getScaleX();
10734    }
10735
10736    /**
10737     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10738     * the view's unscaled width. A value of 1 means that no scaling is applied.
10739     *
10740     * @param scaleX The scaling factor.
10741     * @see #getPivotX()
10742     * @see #getPivotY()
10743     *
10744     * @attr ref android.R.styleable#View_scaleX
10745     */
10746    public void setScaleX(float scaleX) {
10747        if (scaleX != getScaleX()) {
10748            invalidateViewProperty(true, false);
10749            mRenderNode.setScaleX(scaleX);
10750            invalidateViewProperty(false, true);
10751
10752            invalidateParentIfNeededAndWasQuickRejected();
10753            notifySubtreeAccessibilityStateChangedIfNeeded();
10754        }
10755    }
10756
10757    /**
10758     * The amount that the view is scaled in y around the pivot point, as a proportion of
10759     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10760     *
10761     * <p>By default, this is 1.0f.
10762     *
10763     * @see #getPivotX()
10764     * @see #getPivotY()
10765     * @return The scaling factor.
10766     */
10767    @ViewDebug.ExportedProperty(category = "drawing")
10768    public float getScaleY() {
10769        return mRenderNode.getScaleY();
10770    }
10771
10772    /**
10773     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10774     * the view's unscaled width. A value of 1 means that no scaling is applied.
10775     *
10776     * @param scaleY The scaling factor.
10777     * @see #getPivotX()
10778     * @see #getPivotY()
10779     *
10780     * @attr ref android.R.styleable#View_scaleY
10781     */
10782    public void setScaleY(float scaleY) {
10783        if (scaleY != getScaleY()) {
10784            invalidateViewProperty(true, false);
10785            mRenderNode.setScaleY(scaleY);
10786            invalidateViewProperty(false, true);
10787
10788            invalidateParentIfNeededAndWasQuickRejected();
10789            notifySubtreeAccessibilityStateChangedIfNeeded();
10790        }
10791    }
10792
10793    /**
10794     * The x location of the point around which the view is {@link #setRotation(float) rotated}
10795     * and {@link #setScaleX(float) scaled}.
10796     *
10797     * @see #getRotation()
10798     * @see #getScaleX()
10799     * @see #getScaleY()
10800     * @see #getPivotY()
10801     * @return The x location of the pivot point.
10802     *
10803     * @attr ref android.R.styleable#View_transformPivotX
10804     */
10805    @ViewDebug.ExportedProperty(category = "drawing")
10806    public float getPivotX() {
10807        return mRenderNode.getPivotX();
10808    }
10809
10810    /**
10811     * Sets the x location of the point around which the view is
10812     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10813     * By default, the pivot point is centered on the object.
10814     * Setting this property disables this behavior and causes the view to use only the
10815     * explicitly set pivotX and pivotY values.
10816     *
10817     * @param pivotX The x location of the pivot point.
10818     * @see #getRotation()
10819     * @see #getScaleX()
10820     * @see #getScaleY()
10821     * @see #getPivotY()
10822     *
10823     * @attr ref android.R.styleable#View_transformPivotX
10824     */
10825    public void setPivotX(float pivotX) {
10826        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10827            invalidateViewProperty(true, false);
10828            mRenderNode.setPivotX(pivotX);
10829            invalidateViewProperty(false, true);
10830
10831            invalidateParentIfNeededAndWasQuickRejected();
10832        }
10833    }
10834
10835    /**
10836     * The y location of the point around which the view is {@link #setRotation(float) rotated}
10837     * and {@link #setScaleY(float) scaled}.
10838     *
10839     * @see #getRotation()
10840     * @see #getScaleX()
10841     * @see #getScaleY()
10842     * @see #getPivotY()
10843     * @return The y location of the pivot point.
10844     *
10845     * @attr ref android.R.styleable#View_transformPivotY
10846     */
10847    @ViewDebug.ExportedProperty(category = "drawing")
10848    public float getPivotY() {
10849        return mRenderNode.getPivotY();
10850    }
10851
10852    /**
10853     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10854     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10855     * Setting this property disables this behavior and causes the view to use only the
10856     * explicitly set pivotX and pivotY values.
10857     *
10858     * @param pivotY The y location of the pivot point.
10859     * @see #getRotation()
10860     * @see #getScaleX()
10861     * @see #getScaleY()
10862     * @see #getPivotY()
10863     *
10864     * @attr ref android.R.styleable#View_transformPivotY
10865     */
10866    public void setPivotY(float pivotY) {
10867        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10868            invalidateViewProperty(true, false);
10869            mRenderNode.setPivotY(pivotY);
10870            invalidateViewProperty(false, true);
10871
10872            invalidateParentIfNeededAndWasQuickRejected();
10873        }
10874    }
10875
10876    /**
10877     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10878     * completely transparent and 1 means the view is completely opaque.
10879     *
10880     * <p>By default this is 1.0f.
10881     * @return The opacity of the view.
10882     */
10883    @ViewDebug.ExportedProperty(category = "drawing")
10884    public float getAlpha() {
10885        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10886    }
10887
10888    /**
10889     * Returns whether this View has content which overlaps.
10890     *
10891     * <p>This function, intended to be overridden by specific View types, is an optimization when
10892     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10893     * an offscreen buffer and then composited into place, which can be expensive. If the view has
10894     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10895     * directly. An example of overlapping rendering is a TextView with a background image, such as
10896     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10897     * ImageView with only the foreground image. The default implementation returns true; subclasses
10898     * should override if they have cases which can be optimized.</p>
10899     *
10900     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10901     * necessitates that a View return true if it uses the methods internally without passing the
10902     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10903     *
10904     * @return true if the content in this view might overlap, false otherwise.
10905     */
10906    @ViewDebug.ExportedProperty(category = "drawing")
10907    public boolean hasOverlappingRendering() {
10908        return true;
10909    }
10910
10911    /**
10912     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10913     * completely transparent and 1 means the view is completely opaque.</p>
10914     *
10915     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10916     * performance implications, especially for large views. It is best to use the alpha property
10917     * sparingly and transiently, as in the case of fading animations.</p>
10918     *
10919     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10920     * strongly recommended for performance reasons to either override
10921     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10922     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10923     *
10924     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10925     * responsible for applying the opacity itself.</p>
10926     *
10927     * <p>Note that if the view is backed by a
10928     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10929     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10930     * 1.0 will supersede the alpha of the layer paint.</p>
10931     *
10932     * @param alpha The opacity of the view.
10933     *
10934     * @see #hasOverlappingRendering()
10935     * @see #setLayerType(int, android.graphics.Paint)
10936     *
10937     * @attr ref android.R.styleable#View_alpha
10938     */
10939    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
10940        ensureTransformationInfo();
10941        if (mTransformationInfo.mAlpha != alpha) {
10942            mTransformationInfo.mAlpha = alpha;
10943            if (onSetAlpha((int) (alpha * 255))) {
10944                mPrivateFlags |= PFLAG_ALPHA_SET;
10945                // subclass is handling alpha - don't optimize rendering cache invalidation
10946                invalidateParentCaches();
10947                invalidate(true);
10948            } else {
10949                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10950                invalidateViewProperty(true, false);
10951                mRenderNode.setAlpha(getFinalAlpha());
10952                notifyViewAccessibilityStateChangedIfNeeded(
10953                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10954            }
10955        }
10956    }
10957
10958    /**
10959     * Faster version of setAlpha() which performs the same steps except there are
10960     * no calls to invalidate(). The caller of this function should perform proper invalidation
10961     * on the parent and this object. The return value indicates whether the subclass handles
10962     * alpha (the return value for onSetAlpha()).
10963     *
10964     * @param alpha The new value for the alpha property
10965     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10966     *         the new value for the alpha property is different from the old value
10967     */
10968    boolean setAlphaNoInvalidation(float alpha) {
10969        ensureTransformationInfo();
10970        if (mTransformationInfo.mAlpha != alpha) {
10971            mTransformationInfo.mAlpha = alpha;
10972            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10973            if (subclassHandlesAlpha) {
10974                mPrivateFlags |= PFLAG_ALPHA_SET;
10975                return true;
10976            } else {
10977                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10978                mRenderNode.setAlpha(getFinalAlpha());
10979            }
10980        }
10981        return false;
10982    }
10983
10984    /**
10985     * This property is hidden and intended only for use by the Fade transition, which
10986     * animates it to produce a visual translucency that does not side-effect (or get
10987     * affected by) the real alpha property. This value is composited with the other
10988     * alpha value (and the AlphaAnimation value, when that is present) to produce
10989     * a final visual translucency result, which is what is passed into the DisplayList.
10990     *
10991     * @hide
10992     */
10993    public void setTransitionAlpha(float alpha) {
10994        ensureTransformationInfo();
10995        if (mTransformationInfo.mTransitionAlpha != alpha) {
10996            mTransformationInfo.mTransitionAlpha = alpha;
10997            mPrivateFlags &= ~PFLAG_ALPHA_SET;
10998            invalidateViewProperty(true, false);
10999            mRenderNode.setAlpha(getFinalAlpha());
11000        }
11001    }
11002
11003    /**
11004     * Calculates the visual alpha of this view, which is a combination of the actual
11005     * alpha value and the transitionAlpha value (if set).
11006     */
11007    private float getFinalAlpha() {
11008        if (mTransformationInfo != null) {
11009            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11010        }
11011        return 1;
11012    }
11013
11014    /**
11015     * This property is hidden and intended only for use by the Fade transition, which
11016     * animates it to produce a visual translucency that does not side-effect (or get
11017     * affected by) the real alpha property. This value is composited with the other
11018     * alpha value (and the AlphaAnimation value, when that is present) to produce
11019     * a final visual translucency result, which is what is passed into the DisplayList.
11020     *
11021     * @hide
11022     */
11023    @ViewDebug.ExportedProperty(category = "drawing")
11024    public float getTransitionAlpha() {
11025        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11026    }
11027
11028    /**
11029     * Top position of this view relative to its parent.
11030     *
11031     * @return The top of this view, in pixels.
11032     */
11033    @ViewDebug.CapturedViewProperty
11034    public final int getTop() {
11035        return mTop;
11036    }
11037
11038    /**
11039     * Sets the top position of this view relative to its parent. This method is meant to be called
11040     * by the layout system and should not generally be called otherwise, because the property
11041     * may be changed at any time by the layout.
11042     *
11043     * @param top The top of this view, in pixels.
11044     */
11045    public final void setTop(int top) {
11046        if (top != mTop) {
11047            final boolean matrixIsIdentity = hasIdentityMatrix();
11048            if (matrixIsIdentity) {
11049                if (mAttachInfo != null) {
11050                    int minTop;
11051                    int yLoc;
11052                    if (top < mTop) {
11053                        minTop = top;
11054                        yLoc = top - mTop;
11055                    } else {
11056                        minTop = mTop;
11057                        yLoc = 0;
11058                    }
11059                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11060                }
11061            } else {
11062                // Double-invalidation is necessary to capture view's old and new areas
11063                invalidate(true);
11064            }
11065
11066            int width = mRight - mLeft;
11067            int oldHeight = mBottom - mTop;
11068
11069            mTop = top;
11070            mRenderNode.setTop(mTop);
11071
11072            sizeChange(width, mBottom - mTop, width, oldHeight);
11073
11074            if (!matrixIsIdentity) {
11075                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11076                invalidate(true);
11077            }
11078            mBackgroundSizeChanged = true;
11079            if (mForegroundInfo != null) {
11080                mForegroundInfo.mBoundsChanged = true;
11081            }
11082            invalidateParentIfNeeded();
11083            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11084                // View was rejected last time it was drawn by its parent; this may have changed
11085                invalidateParentIfNeeded();
11086            }
11087        }
11088    }
11089
11090    /**
11091     * Bottom position of this view relative to its parent.
11092     *
11093     * @return The bottom of this view, in pixels.
11094     */
11095    @ViewDebug.CapturedViewProperty
11096    public final int getBottom() {
11097        return mBottom;
11098    }
11099
11100    /**
11101     * True if this view has changed since the last time being drawn.
11102     *
11103     * @return The dirty state of this view.
11104     */
11105    public boolean isDirty() {
11106        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11107    }
11108
11109    /**
11110     * Sets the bottom position of this view relative to its parent. This method is meant to be
11111     * called by the layout system and should not generally be called otherwise, because the
11112     * property may be changed at any time by the layout.
11113     *
11114     * @param bottom The bottom of this view, in pixels.
11115     */
11116    public final void setBottom(int bottom) {
11117        if (bottom != mBottom) {
11118            final boolean matrixIsIdentity = hasIdentityMatrix();
11119            if (matrixIsIdentity) {
11120                if (mAttachInfo != null) {
11121                    int maxBottom;
11122                    if (bottom < mBottom) {
11123                        maxBottom = mBottom;
11124                    } else {
11125                        maxBottom = bottom;
11126                    }
11127                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11128                }
11129            } else {
11130                // Double-invalidation is necessary to capture view's old and new areas
11131                invalidate(true);
11132            }
11133
11134            int width = mRight - mLeft;
11135            int oldHeight = mBottom - mTop;
11136
11137            mBottom = bottom;
11138            mRenderNode.setBottom(mBottom);
11139
11140            sizeChange(width, mBottom - mTop, width, oldHeight);
11141
11142            if (!matrixIsIdentity) {
11143                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11144                invalidate(true);
11145            }
11146            mBackgroundSizeChanged = true;
11147            if (mForegroundInfo != null) {
11148                mForegroundInfo.mBoundsChanged = true;
11149            }
11150            invalidateParentIfNeeded();
11151            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11152                // View was rejected last time it was drawn by its parent; this may have changed
11153                invalidateParentIfNeeded();
11154            }
11155        }
11156    }
11157
11158    /**
11159     * Left position of this view relative to its parent.
11160     *
11161     * @return The left edge of this view, in pixels.
11162     */
11163    @ViewDebug.CapturedViewProperty
11164    public final int getLeft() {
11165        return mLeft;
11166    }
11167
11168    /**
11169     * Sets the left position of this view relative to its parent. This method is meant to be called
11170     * by the layout system and should not generally be called otherwise, because the property
11171     * may be changed at any time by the layout.
11172     *
11173     * @param left The left of this view, in pixels.
11174     */
11175    public final void setLeft(int left) {
11176        if (left != mLeft) {
11177            final boolean matrixIsIdentity = hasIdentityMatrix();
11178            if (matrixIsIdentity) {
11179                if (mAttachInfo != null) {
11180                    int minLeft;
11181                    int xLoc;
11182                    if (left < mLeft) {
11183                        minLeft = left;
11184                        xLoc = left - mLeft;
11185                    } else {
11186                        minLeft = mLeft;
11187                        xLoc = 0;
11188                    }
11189                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11190                }
11191            } else {
11192                // Double-invalidation is necessary to capture view's old and new areas
11193                invalidate(true);
11194            }
11195
11196            int oldWidth = mRight - mLeft;
11197            int height = mBottom - mTop;
11198
11199            mLeft = left;
11200            mRenderNode.setLeft(left);
11201
11202            sizeChange(mRight - mLeft, height, oldWidth, height);
11203
11204            if (!matrixIsIdentity) {
11205                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11206                invalidate(true);
11207            }
11208            mBackgroundSizeChanged = true;
11209            if (mForegroundInfo != null) {
11210                mForegroundInfo.mBoundsChanged = true;
11211            }
11212            invalidateParentIfNeeded();
11213            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11214                // View was rejected last time it was drawn by its parent; this may have changed
11215                invalidateParentIfNeeded();
11216            }
11217        }
11218    }
11219
11220    /**
11221     * Right position of this view relative to its parent.
11222     *
11223     * @return The right edge of this view, in pixels.
11224     */
11225    @ViewDebug.CapturedViewProperty
11226    public final int getRight() {
11227        return mRight;
11228    }
11229
11230    /**
11231     * Sets the right position of this view relative to its parent. This method is meant to be called
11232     * by the layout system and should not generally be called otherwise, because the property
11233     * may be changed at any time by the layout.
11234     *
11235     * @param right The right of this view, in pixels.
11236     */
11237    public final void setRight(int right) {
11238        if (right != mRight) {
11239            final boolean matrixIsIdentity = hasIdentityMatrix();
11240            if (matrixIsIdentity) {
11241                if (mAttachInfo != null) {
11242                    int maxRight;
11243                    if (right < mRight) {
11244                        maxRight = mRight;
11245                    } else {
11246                        maxRight = right;
11247                    }
11248                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11249                }
11250            } else {
11251                // Double-invalidation is necessary to capture view's old and new areas
11252                invalidate(true);
11253            }
11254
11255            int oldWidth = mRight - mLeft;
11256            int height = mBottom - mTop;
11257
11258            mRight = right;
11259            mRenderNode.setRight(mRight);
11260
11261            sizeChange(mRight - mLeft, height, oldWidth, height);
11262
11263            if (!matrixIsIdentity) {
11264                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11265                invalidate(true);
11266            }
11267            mBackgroundSizeChanged = true;
11268            if (mForegroundInfo != null) {
11269                mForegroundInfo.mBoundsChanged = true;
11270            }
11271            invalidateParentIfNeeded();
11272            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11273                // View was rejected last time it was drawn by its parent; this may have changed
11274                invalidateParentIfNeeded();
11275            }
11276        }
11277    }
11278
11279    /**
11280     * The visual x position of this view, in pixels. This is equivalent to the
11281     * {@link #setTranslationX(float) translationX} property plus the current
11282     * {@link #getLeft() left} property.
11283     *
11284     * @return The visual x position of this view, in pixels.
11285     */
11286    @ViewDebug.ExportedProperty(category = "drawing")
11287    public float getX() {
11288        return mLeft + getTranslationX();
11289    }
11290
11291    /**
11292     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11293     * {@link #setTranslationX(float) translationX} property to be the difference between
11294     * the x value passed in and the current {@link #getLeft() left} property.
11295     *
11296     * @param x The visual x position of this view, in pixels.
11297     */
11298    public void setX(float x) {
11299        setTranslationX(x - mLeft);
11300    }
11301
11302    /**
11303     * The visual y position of this view, in pixels. This is equivalent to the
11304     * {@link #setTranslationY(float) translationY} property plus the current
11305     * {@link #getTop() top} property.
11306     *
11307     * @return The visual y position of this view, in pixels.
11308     */
11309    @ViewDebug.ExportedProperty(category = "drawing")
11310    public float getY() {
11311        return mTop + getTranslationY();
11312    }
11313
11314    /**
11315     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11316     * {@link #setTranslationY(float) translationY} property to be the difference between
11317     * the y value passed in and the current {@link #getTop() top} property.
11318     *
11319     * @param y The visual y position of this view, in pixels.
11320     */
11321    public void setY(float y) {
11322        setTranslationY(y - mTop);
11323    }
11324
11325    /**
11326     * The visual z position of this view, in pixels. This is equivalent to the
11327     * {@link #setTranslationZ(float) translationZ} property plus the current
11328     * {@link #getElevation() elevation} property.
11329     *
11330     * @return The visual z position of this view, in pixels.
11331     */
11332    @ViewDebug.ExportedProperty(category = "drawing")
11333    public float getZ() {
11334        return getElevation() + getTranslationZ();
11335    }
11336
11337    /**
11338     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11339     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11340     * the x value passed in and the current {@link #getElevation() elevation} property.
11341     *
11342     * @param z The visual z position of this view, in pixels.
11343     */
11344    public void setZ(float z) {
11345        setTranslationZ(z - getElevation());
11346    }
11347
11348    /**
11349     * The base elevation of this view relative to its parent, in pixels.
11350     *
11351     * @return The base depth position of the view, in pixels.
11352     */
11353    @ViewDebug.ExportedProperty(category = "drawing")
11354    public float getElevation() {
11355        return mRenderNode.getElevation();
11356    }
11357
11358    /**
11359     * Sets the base elevation of this view, in pixels.
11360     *
11361     * @attr ref android.R.styleable#View_elevation
11362     */
11363    public void setElevation(float elevation) {
11364        if (elevation != getElevation()) {
11365            invalidateViewProperty(true, false);
11366            mRenderNode.setElevation(elevation);
11367            invalidateViewProperty(false, true);
11368
11369            invalidateParentIfNeededAndWasQuickRejected();
11370        }
11371    }
11372
11373    /**
11374     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11375     * This position is post-layout, in addition to wherever the object's
11376     * layout placed it.
11377     *
11378     * @return The horizontal position of this view relative to its left position, in pixels.
11379     */
11380    @ViewDebug.ExportedProperty(category = "drawing")
11381    public float getTranslationX() {
11382        return mRenderNode.getTranslationX();
11383    }
11384
11385    /**
11386     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11387     * This effectively positions the object post-layout, in addition to wherever the object's
11388     * layout placed it.
11389     *
11390     * @param translationX The horizontal position of this view relative to its left position,
11391     * in pixels.
11392     *
11393     * @attr ref android.R.styleable#View_translationX
11394     */
11395    public void setTranslationX(float translationX) {
11396        if (translationX != getTranslationX()) {
11397            invalidateViewProperty(true, false);
11398            mRenderNode.setTranslationX(translationX);
11399            invalidateViewProperty(false, true);
11400
11401            invalidateParentIfNeededAndWasQuickRejected();
11402            notifySubtreeAccessibilityStateChangedIfNeeded();
11403        }
11404    }
11405
11406    /**
11407     * The vertical location of this view relative to its {@link #getTop() top} position.
11408     * This position is post-layout, in addition to wherever the object's
11409     * layout placed it.
11410     *
11411     * @return The vertical position of this view relative to its top position,
11412     * in pixels.
11413     */
11414    @ViewDebug.ExportedProperty(category = "drawing")
11415    public float getTranslationY() {
11416        return mRenderNode.getTranslationY();
11417    }
11418
11419    /**
11420     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11421     * This effectively positions the object post-layout, in addition to wherever the object's
11422     * layout placed it.
11423     *
11424     * @param translationY The vertical position of this view relative to its top position,
11425     * in pixels.
11426     *
11427     * @attr ref android.R.styleable#View_translationY
11428     */
11429    public void setTranslationY(float translationY) {
11430        if (translationY != getTranslationY()) {
11431            invalidateViewProperty(true, false);
11432            mRenderNode.setTranslationY(translationY);
11433            invalidateViewProperty(false, true);
11434
11435            invalidateParentIfNeededAndWasQuickRejected();
11436            notifySubtreeAccessibilityStateChangedIfNeeded();
11437        }
11438    }
11439
11440    /**
11441     * The depth location of this view relative to its {@link #getElevation() elevation}.
11442     *
11443     * @return The depth of this view relative to its elevation.
11444     */
11445    @ViewDebug.ExportedProperty(category = "drawing")
11446    public float getTranslationZ() {
11447        return mRenderNode.getTranslationZ();
11448    }
11449
11450    /**
11451     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11452     *
11453     * @attr ref android.R.styleable#View_translationZ
11454     */
11455    public void setTranslationZ(float translationZ) {
11456        if (translationZ != getTranslationZ()) {
11457            invalidateViewProperty(true, false);
11458            mRenderNode.setTranslationZ(translationZ);
11459            invalidateViewProperty(false, true);
11460
11461            invalidateParentIfNeededAndWasQuickRejected();
11462        }
11463    }
11464
11465    /** @hide */
11466    public void setAnimationMatrix(Matrix matrix) {
11467        invalidateViewProperty(true, false);
11468        mRenderNode.setAnimationMatrix(matrix);
11469        invalidateViewProperty(false, true);
11470
11471        invalidateParentIfNeededAndWasQuickRejected();
11472    }
11473
11474    /**
11475     * Returns the current StateListAnimator if exists.
11476     *
11477     * @return StateListAnimator or null if it does not exists
11478     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11479     */
11480    public StateListAnimator getStateListAnimator() {
11481        return mStateListAnimator;
11482    }
11483
11484    /**
11485     * Attaches the provided StateListAnimator to this View.
11486     * <p>
11487     * Any previously attached StateListAnimator will be detached.
11488     *
11489     * @param stateListAnimator The StateListAnimator to update the view
11490     * @see {@link android.animation.StateListAnimator}
11491     */
11492    public void setStateListAnimator(StateListAnimator stateListAnimator) {
11493        if (mStateListAnimator == stateListAnimator) {
11494            return;
11495        }
11496        if (mStateListAnimator != null) {
11497            mStateListAnimator.setTarget(null);
11498        }
11499        mStateListAnimator = stateListAnimator;
11500        if (stateListAnimator != null) {
11501            stateListAnimator.setTarget(this);
11502            if (isAttachedToWindow()) {
11503                stateListAnimator.setState(getDrawableState());
11504            }
11505        }
11506    }
11507
11508    /**
11509     * Returns whether the Outline should be used to clip the contents of the View.
11510     * <p>
11511     * Note that this flag will only be respected if the View's Outline returns true from
11512     * {@link Outline#canClip()}.
11513     *
11514     * @see #setOutlineProvider(ViewOutlineProvider)
11515     * @see #setClipToOutline(boolean)
11516     */
11517    public final boolean getClipToOutline() {
11518        return mRenderNode.getClipToOutline();
11519    }
11520
11521    /**
11522     * Sets whether the View's Outline should be used to clip the contents of the View.
11523     * <p>
11524     * Only a single non-rectangular clip can be applied on a View at any time.
11525     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11526     * circular reveal} animation take priority over Outline clipping, and
11527     * child Outline clipping takes priority over Outline clipping done by a
11528     * parent.
11529     * <p>
11530     * Note that this flag will only be respected if the View's Outline returns true from
11531     * {@link Outline#canClip()}.
11532     *
11533     * @see #setOutlineProvider(ViewOutlineProvider)
11534     * @see #getClipToOutline()
11535     */
11536    public void setClipToOutline(boolean clipToOutline) {
11537        damageInParent();
11538        if (getClipToOutline() != clipToOutline) {
11539            mRenderNode.setClipToOutline(clipToOutline);
11540        }
11541    }
11542
11543    // correspond to the enum values of View_outlineProvider
11544    private static final int PROVIDER_BACKGROUND = 0;
11545    private static final int PROVIDER_NONE = 1;
11546    private static final int PROVIDER_BOUNDS = 2;
11547    private static final int PROVIDER_PADDED_BOUNDS = 3;
11548    private void setOutlineProviderFromAttribute(int providerInt) {
11549        switch (providerInt) {
11550            case PROVIDER_BACKGROUND:
11551                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11552                break;
11553            case PROVIDER_NONE:
11554                setOutlineProvider(null);
11555                break;
11556            case PROVIDER_BOUNDS:
11557                setOutlineProvider(ViewOutlineProvider.BOUNDS);
11558                break;
11559            case PROVIDER_PADDED_BOUNDS:
11560                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11561                break;
11562        }
11563    }
11564
11565    /**
11566     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11567     * the shape of the shadow it casts, and enables outline clipping.
11568     * <p>
11569     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11570     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11571     * outline provider with this method allows this behavior to be overridden.
11572     * <p>
11573     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11574     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11575     * <p>
11576     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11577     *
11578     * @see #setClipToOutline(boolean)
11579     * @see #getClipToOutline()
11580     * @see #getOutlineProvider()
11581     */
11582    public void setOutlineProvider(ViewOutlineProvider provider) {
11583        mOutlineProvider = provider;
11584        invalidateOutline();
11585    }
11586
11587    /**
11588     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11589     * that defines the shape of the shadow it casts, and enables outline clipping.
11590     *
11591     * @see #setOutlineProvider(ViewOutlineProvider)
11592     */
11593    public ViewOutlineProvider getOutlineProvider() {
11594        return mOutlineProvider;
11595    }
11596
11597    /**
11598     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11599     *
11600     * @see #setOutlineProvider(ViewOutlineProvider)
11601     */
11602    public void invalidateOutline() {
11603        rebuildOutline();
11604
11605        notifySubtreeAccessibilityStateChangedIfNeeded();
11606        invalidateViewProperty(false, false);
11607    }
11608
11609    /**
11610     * Internal version of {@link #invalidateOutline()} which invalidates the
11611     * outline without invalidating the view itself. This is intended to be called from
11612     * within methods in the View class itself which are the result of the view being
11613     * invalidated already. For example, when we are drawing the background of a View,
11614     * we invalidate the outline in case it changed in the meantime, but we do not
11615     * need to invalidate the view because we're already drawing the background as part
11616     * of drawing the view in response to an earlier invalidation of the view.
11617     */
11618    private void rebuildOutline() {
11619        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11620        if (mAttachInfo == null) return;
11621
11622        if (mOutlineProvider == null) {
11623            // no provider, remove outline
11624            mRenderNode.setOutline(null);
11625        } else {
11626            final Outline outline = mAttachInfo.mTmpOutline;
11627            outline.setEmpty();
11628            outline.setAlpha(1.0f);
11629
11630            mOutlineProvider.getOutline(this, outline);
11631            mRenderNode.setOutline(outline);
11632        }
11633    }
11634
11635    /**
11636     * HierarchyViewer only
11637     *
11638     * @hide
11639     */
11640    @ViewDebug.ExportedProperty(category = "drawing")
11641    public boolean hasShadow() {
11642        return mRenderNode.hasShadow();
11643    }
11644
11645
11646    /** @hide */
11647    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11648        mRenderNode.setRevealClip(shouldClip, x, y, radius);
11649        invalidateViewProperty(false, false);
11650    }
11651
11652    /**
11653     * Hit rectangle in parent's coordinates
11654     *
11655     * @param outRect The hit rectangle of the view.
11656     */
11657    public void getHitRect(Rect outRect) {
11658        if (hasIdentityMatrix() || mAttachInfo == null) {
11659            outRect.set(mLeft, mTop, mRight, mBottom);
11660        } else {
11661            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11662            tmpRect.set(0, 0, getWidth(), getHeight());
11663            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11664            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11665                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11666        }
11667    }
11668
11669    /**
11670     * Determines whether the given point, in local coordinates is inside the view.
11671     */
11672    /*package*/ final boolean pointInView(float localX, float localY) {
11673        return localX >= 0 && localX < (mRight - mLeft)
11674                && localY >= 0 && localY < (mBottom - mTop);
11675    }
11676
11677    /**
11678     * Utility method to determine whether the given point, in local coordinates,
11679     * is inside the view, where the area of the view is expanded by the slop factor.
11680     * This method is called while processing touch-move events to determine if the event
11681     * is still within the view.
11682     *
11683     * @hide
11684     */
11685    public boolean pointInView(float localX, float localY, float slop) {
11686        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11687                localY < ((mBottom - mTop) + slop);
11688    }
11689
11690    /**
11691     * When a view has focus and the user navigates away from it, the next view is searched for
11692     * starting from the rectangle filled in by this method.
11693     *
11694     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11695     * of the view.  However, if your view maintains some idea of internal selection,
11696     * such as a cursor, or a selected row or column, you should override this method and
11697     * fill in a more specific rectangle.
11698     *
11699     * @param r The rectangle to fill in, in this view's coordinates.
11700     */
11701    public void getFocusedRect(Rect r) {
11702        getDrawingRect(r);
11703    }
11704
11705    /**
11706     * If some part of this view is not clipped by any of its parents, then
11707     * return that area in r in global (root) coordinates. To convert r to local
11708     * coordinates (without taking possible View rotations into account), offset
11709     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11710     * If the view is completely clipped or translated out, return false.
11711     *
11712     * @param r If true is returned, r holds the global coordinates of the
11713     *        visible portion of this view.
11714     * @param globalOffset If true is returned, globalOffset holds the dx,dy
11715     *        between this view and its root. globalOffet may be null.
11716     * @return true if r is non-empty (i.e. part of the view is visible at the
11717     *         root level.
11718     */
11719    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11720        int width = mRight - mLeft;
11721        int height = mBottom - mTop;
11722        if (width > 0 && height > 0) {
11723            r.set(0, 0, width, height);
11724            if (globalOffset != null) {
11725                globalOffset.set(-mScrollX, -mScrollY);
11726            }
11727            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11728        }
11729        return false;
11730    }
11731
11732    public final boolean getGlobalVisibleRect(Rect r) {
11733        return getGlobalVisibleRect(r, null);
11734    }
11735
11736    public final boolean getLocalVisibleRect(Rect r) {
11737        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11738        if (getGlobalVisibleRect(r, offset)) {
11739            r.offset(-offset.x, -offset.y); // make r local
11740            return true;
11741        }
11742        return false;
11743    }
11744
11745    /**
11746     * Offset this view's vertical location by the specified number of pixels.
11747     *
11748     * @param offset the number of pixels to offset the view by
11749     */
11750    public void offsetTopAndBottom(int offset) {
11751        if (offset != 0) {
11752            final boolean matrixIsIdentity = hasIdentityMatrix();
11753            if (matrixIsIdentity) {
11754                if (isHardwareAccelerated()) {
11755                    invalidateViewProperty(false, false);
11756                } else {
11757                    final ViewParent p = mParent;
11758                    if (p != null && mAttachInfo != null) {
11759                        final Rect r = mAttachInfo.mTmpInvalRect;
11760                        int minTop;
11761                        int maxBottom;
11762                        int yLoc;
11763                        if (offset < 0) {
11764                            minTop = mTop + offset;
11765                            maxBottom = mBottom;
11766                            yLoc = offset;
11767                        } else {
11768                            minTop = mTop;
11769                            maxBottom = mBottom + offset;
11770                            yLoc = 0;
11771                        }
11772                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11773                        p.invalidateChild(this, r);
11774                    }
11775                }
11776            } else {
11777                invalidateViewProperty(false, false);
11778            }
11779
11780            mTop += offset;
11781            mBottom += offset;
11782            mRenderNode.offsetTopAndBottom(offset);
11783            if (isHardwareAccelerated()) {
11784                invalidateViewProperty(false, false);
11785            } else {
11786                if (!matrixIsIdentity) {
11787                    invalidateViewProperty(false, true);
11788                }
11789                invalidateParentIfNeeded();
11790            }
11791            notifySubtreeAccessibilityStateChangedIfNeeded();
11792        }
11793    }
11794
11795    /**
11796     * Offset this view's horizontal location by the specified amount of pixels.
11797     *
11798     * @param offset the number of pixels to offset the view by
11799     */
11800    public void offsetLeftAndRight(int offset) {
11801        if (offset != 0) {
11802            final boolean matrixIsIdentity = hasIdentityMatrix();
11803            if (matrixIsIdentity) {
11804                if (isHardwareAccelerated()) {
11805                    invalidateViewProperty(false, false);
11806                } else {
11807                    final ViewParent p = mParent;
11808                    if (p != null && mAttachInfo != null) {
11809                        final Rect r = mAttachInfo.mTmpInvalRect;
11810                        int minLeft;
11811                        int maxRight;
11812                        if (offset < 0) {
11813                            minLeft = mLeft + offset;
11814                            maxRight = mRight;
11815                        } else {
11816                            minLeft = mLeft;
11817                            maxRight = mRight + offset;
11818                        }
11819                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11820                        p.invalidateChild(this, r);
11821                    }
11822                }
11823            } else {
11824                invalidateViewProperty(false, false);
11825            }
11826
11827            mLeft += offset;
11828            mRight += offset;
11829            mRenderNode.offsetLeftAndRight(offset);
11830            if (isHardwareAccelerated()) {
11831                invalidateViewProperty(false, false);
11832            } else {
11833                if (!matrixIsIdentity) {
11834                    invalidateViewProperty(false, true);
11835                }
11836                invalidateParentIfNeeded();
11837            }
11838            notifySubtreeAccessibilityStateChangedIfNeeded();
11839        }
11840    }
11841
11842    /**
11843     * Get the LayoutParams associated with this view. All views should have
11844     * layout parameters. These supply parameters to the <i>parent</i> of this
11845     * view specifying how it should be arranged. There are many subclasses of
11846     * ViewGroup.LayoutParams, and these correspond to the different subclasses
11847     * of ViewGroup that are responsible for arranging their children.
11848     *
11849     * This method may return null if this View is not attached to a parent
11850     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11851     * was not invoked successfully. When a View is attached to a parent
11852     * ViewGroup, this method must not return null.
11853     *
11854     * @return The LayoutParams associated with this view, or null if no
11855     *         parameters have been set yet
11856     */
11857    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11858    public ViewGroup.LayoutParams getLayoutParams() {
11859        return mLayoutParams;
11860    }
11861
11862    /**
11863     * Set the layout parameters associated with this view. These supply
11864     * parameters to the <i>parent</i> of this view specifying how it should be
11865     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11866     * correspond to the different subclasses of ViewGroup that are responsible
11867     * for arranging their children.
11868     *
11869     * @param params The layout parameters for this view, cannot be null
11870     */
11871    public void setLayoutParams(ViewGroup.LayoutParams params) {
11872        if (params == null) {
11873            throw new NullPointerException("Layout parameters cannot be null");
11874        }
11875        mLayoutParams = params;
11876        resolveLayoutParams();
11877        if (mParent instanceof ViewGroup) {
11878            ((ViewGroup) mParent).onSetLayoutParams(this, params);
11879        }
11880        requestLayout();
11881    }
11882
11883    /**
11884     * Resolve the layout parameters depending on the resolved layout direction
11885     *
11886     * @hide
11887     */
11888    public void resolveLayoutParams() {
11889        if (mLayoutParams != null) {
11890            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11891        }
11892    }
11893
11894    /**
11895     * Set the scrolled position of your view. This will cause a call to
11896     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11897     * invalidated.
11898     * @param x the x position to scroll to
11899     * @param y the y position to scroll to
11900     */
11901    public void scrollTo(int x, int y) {
11902        if (mScrollX != x || mScrollY != y) {
11903            int oldX = mScrollX;
11904            int oldY = mScrollY;
11905            mScrollX = x;
11906            mScrollY = y;
11907            invalidateParentCaches();
11908            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11909            if (!awakenScrollBars()) {
11910                postInvalidateOnAnimation();
11911            }
11912        }
11913    }
11914
11915    /**
11916     * Move the scrolled position of your view. This will cause a call to
11917     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11918     * invalidated.
11919     * @param x the amount of pixels to scroll by horizontally
11920     * @param y the amount of pixels to scroll by vertically
11921     */
11922    public void scrollBy(int x, int y) {
11923        scrollTo(mScrollX + x, mScrollY + y);
11924    }
11925
11926    /**
11927     * <p>Trigger the scrollbars to draw. When invoked this method starts an
11928     * animation to fade the scrollbars out after a default delay. If a subclass
11929     * provides animated scrolling, the start delay should equal the duration
11930     * of the scrolling animation.</p>
11931     *
11932     * <p>The animation starts only if at least one of the scrollbars is
11933     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11934     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11935     * this method returns true, and false otherwise. If the animation is
11936     * started, this method calls {@link #invalidate()}; in that case the
11937     * caller should not call {@link #invalidate()}.</p>
11938     *
11939     * <p>This method should be invoked every time a subclass directly updates
11940     * the scroll parameters.</p>
11941     *
11942     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11943     * and {@link #scrollTo(int, int)}.</p>
11944     *
11945     * @return true if the animation is played, false otherwise
11946     *
11947     * @see #awakenScrollBars(int)
11948     * @see #scrollBy(int, int)
11949     * @see #scrollTo(int, int)
11950     * @see #isHorizontalScrollBarEnabled()
11951     * @see #isVerticalScrollBarEnabled()
11952     * @see #setHorizontalScrollBarEnabled(boolean)
11953     * @see #setVerticalScrollBarEnabled(boolean)
11954     */
11955    protected boolean awakenScrollBars() {
11956        return mScrollCache != null &&
11957                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11958    }
11959
11960    /**
11961     * Trigger the scrollbars to draw.
11962     * This method differs from awakenScrollBars() only in its default duration.
11963     * initialAwakenScrollBars() will show the scroll bars for longer than
11964     * usual to give the user more of a chance to notice them.
11965     *
11966     * @return true if the animation is played, false otherwise.
11967     */
11968    private boolean initialAwakenScrollBars() {
11969        return mScrollCache != null &&
11970                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11971    }
11972
11973    /**
11974     * <p>
11975     * Trigger the scrollbars to draw. When invoked this method starts an
11976     * animation to fade the scrollbars out after a fixed delay. If a subclass
11977     * provides animated scrolling, the start delay should equal the duration of
11978     * the scrolling animation.
11979     * </p>
11980     *
11981     * <p>
11982     * The animation starts only if at least one of the scrollbars is enabled,
11983     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11984     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11985     * this method returns true, and false otherwise. If the animation is
11986     * started, this method calls {@link #invalidate()}; in that case the caller
11987     * should not call {@link #invalidate()}.
11988     * </p>
11989     *
11990     * <p>
11991     * This method should be invoked every time a subclass directly updates the
11992     * scroll parameters.
11993     * </p>
11994     *
11995     * @param startDelay the delay, in milliseconds, after which the animation
11996     *        should start; when the delay is 0, the animation starts
11997     *        immediately
11998     * @return true if the animation is played, false otherwise
11999     *
12000     * @see #scrollBy(int, int)
12001     * @see #scrollTo(int, int)
12002     * @see #isHorizontalScrollBarEnabled()
12003     * @see #isVerticalScrollBarEnabled()
12004     * @see #setHorizontalScrollBarEnabled(boolean)
12005     * @see #setVerticalScrollBarEnabled(boolean)
12006     */
12007    protected boolean awakenScrollBars(int startDelay) {
12008        return awakenScrollBars(startDelay, true);
12009    }
12010
12011    /**
12012     * <p>
12013     * Trigger the scrollbars to draw. When invoked this method starts an
12014     * animation to fade the scrollbars out after a fixed delay. If a subclass
12015     * provides animated scrolling, the start delay should equal the duration of
12016     * the scrolling animation.
12017     * </p>
12018     *
12019     * <p>
12020     * The animation starts only if at least one of the scrollbars is enabled,
12021     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12022     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12023     * this method returns true, and false otherwise. If the animation is
12024     * started, this method calls {@link #invalidate()} if the invalidate parameter
12025     * is set to true; in that case the caller
12026     * should not call {@link #invalidate()}.
12027     * </p>
12028     *
12029     * <p>
12030     * This method should be invoked every time a subclass directly updates the
12031     * scroll parameters.
12032     * </p>
12033     *
12034     * @param startDelay the delay, in milliseconds, after which the animation
12035     *        should start; when the delay is 0, the animation starts
12036     *        immediately
12037     *
12038     * @param invalidate Whether this method should call invalidate
12039     *
12040     * @return true if the animation is played, false otherwise
12041     *
12042     * @see #scrollBy(int, int)
12043     * @see #scrollTo(int, int)
12044     * @see #isHorizontalScrollBarEnabled()
12045     * @see #isVerticalScrollBarEnabled()
12046     * @see #setHorizontalScrollBarEnabled(boolean)
12047     * @see #setVerticalScrollBarEnabled(boolean)
12048     */
12049    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12050        final ScrollabilityCache scrollCache = mScrollCache;
12051
12052        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12053            return false;
12054        }
12055
12056        if (scrollCache.scrollBar == null) {
12057            scrollCache.scrollBar = new ScrollBarDrawable();
12058            scrollCache.scrollBar.setCallback(this);
12059            scrollCache.scrollBar.setState(getDrawableState());
12060        }
12061
12062        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12063
12064            if (invalidate) {
12065                // Invalidate to show the scrollbars
12066                postInvalidateOnAnimation();
12067            }
12068
12069            if (scrollCache.state == ScrollabilityCache.OFF) {
12070                // FIXME: this is copied from WindowManagerService.
12071                // We should get this value from the system when it
12072                // is possible to do so.
12073                final int KEY_REPEAT_FIRST_DELAY = 750;
12074                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12075            }
12076
12077            // Tell mScrollCache when we should start fading. This may
12078            // extend the fade start time if one was already scheduled
12079            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12080            scrollCache.fadeStartTime = fadeStartTime;
12081            scrollCache.state = ScrollabilityCache.ON;
12082
12083            // Schedule our fader to run, unscheduling any old ones first
12084            if (mAttachInfo != null) {
12085                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12086                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12087            }
12088
12089            return true;
12090        }
12091
12092        return false;
12093    }
12094
12095    /**
12096     * Do not invalidate views which are not visible and which are not running an animation. They
12097     * will not get drawn and they should not set dirty flags as if they will be drawn
12098     */
12099    private boolean skipInvalidate() {
12100        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12101                (!(mParent instanceof ViewGroup) ||
12102                        !((ViewGroup) mParent).isViewTransitioning(this));
12103    }
12104
12105    /**
12106     * Mark the area defined by dirty as needing to be drawn. If the view is
12107     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12108     * point in the future.
12109     * <p>
12110     * This must be called from a UI thread. To call from a non-UI thread, call
12111     * {@link #postInvalidate()}.
12112     * <p>
12113     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12114     * {@code dirty}.
12115     *
12116     * @param dirty the rectangle representing the bounds of the dirty region
12117     */
12118    public void invalidate(Rect dirty) {
12119        final int scrollX = mScrollX;
12120        final int scrollY = mScrollY;
12121        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12122                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12123    }
12124
12125    /**
12126     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12127     * coordinates of the dirty rect are relative to the view. If the view is
12128     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12129     * point in the future.
12130     * <p>
12131     * This must be called from a UI thread. To call from a non-UI thread, call
12132     * {@link #postInvalidate()}.
12133     *
12134     * @param l the left position of the dirty region
12135     * @param t the top position of the dirty region
12136     * @param r the right position of the dirty region
12137     * @param b the bottom position of the dirty region
12138     */
12139    public void invalidate(int l, int t, int r, int b) {
12140        final int scrollX = mScrollX;
12141        final int scrollY = mScrollY;
12142        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12143    }
12144
12145    /**
12146     * Invalidate the whole view. If the view is visible,
12147     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12148     * the future.
12149     * <p>
12150     * This must be called from a UI thread. To call from a non-UI thread, call
12151     * {@link #postInvalidate()}.
12152     */
12153    public void invalidate() {
12154        invalidate(true);
12155    }
12156
12157    /**
12158     * This is where the invalidate() work actually happens. A full invalidate()
12159     * causes the drawing cache to be invalidated, but this function can be
12160     * called with invalidateCache set to false to skip that invalidation step
12161     * for cases that do not need it (for example, a component that remains at
12162     * the same dimensions with the same content).
12163     *
12164     * @param invalidateCache Whether the drawing cache for this view should be
12165     *            invalidated as well. This is usually true for a full
12166     *            invalidate, but may be set to false if the View's contents or
12167     *            dimensions have not changed.
12168     */
12169    void invalidate(boolean invalidateCache) {
12170        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12171    }
12172
12173    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12174            boolean fullInvalidate) {
12175        if (mGhostView != null) {
12176            mGhostView.invalidate(true);
12177            return;
12178        }
12179
12180        if (skipInvalidate()) {
12181            return;
12182        }
12183
12184        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12185                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12186                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12187                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12188            if (fullInvalidate) {
12189                mLastIsOpaque = isOpaque();
12190                mPrivateFlags &= ~PFLAG_DRAWN;
12191            }
12192
12193            mPrivateFlags |= PFLAG_DIRTY;
12194
12195            if (invalidateCache) {
12196                mPrivateFlags |= PFLAG_INVALIDATED;
12197                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12198            }
12199
12200            // Propagate the damage rectangle to the parent view.
12201            final AttachInfo ai = mAttachInfo;
12202            final ViewParent p = mParent;
12203            if (p != null && ai != null && l < r && t < b) {
12204                final Rect damage = ai.mTmpInvalRect;
12205                damage.set(l, t, r, b);
12206                p.invalidateChild(this, damage);
12207            }
12208
12209            // Damage the entire projection receiver, if necessary.
12210            if (mBackground != null && mBackground.isProjected()) {
12211                final View receiver = getProjectionReceiver();
12212                if (receiver != null) {
12213                    receiver.damageInParent();
12214                }
12215            }
12216
12217            // Damage the entire IsolatedZVolume receiving this view's shadow.
12218            if (isHardwareAccelerated() && getZ() != 0) {
12219                damageShadowReceiver();
12220            }
12221        }
12222    }
12223
12224    /**
12225     * @return this view's projection receiver, or {@code null} if none exists
12226     */
12227    private View getProjectionReceiver() {
12228        ViewParent p = getParent();
12229        while (p != null && p instanceof View) {
12230            final View v = (View) p;
12231            if (v.isProjectionReceiver()) {
12232                return v;
12233            }
12234            p = p.getParent();
12235        }
12236
12237        return null;
12238    }
12239
12240    /**
12241     * @return whether the view is a projection receiver
12242     */
12243    private boolean isProjectionReceiver() {
12244        return mBackground != null;
12245    }
12246
12247    /**
12248     * Damage area of the screen that can be covered by this View's shadow.
12249     *
12250     * This method will guarantee that any changes to shadows cast by a View
12251     * are damaged on the screen for future redraw.
12252     */
12253    private void damageShadowReceiver() {
12254        final AttachInfo ai = mAttachInfo;
12255        if (ai != null) {
12256            ViewParent p = getParent();
12257            if (p != null && p instanceof ViewGroup) {
12258                final ViewGroup vg = (ViewGroup) p;
12259                vg.damageInParent();
12260            }
12261        }
12262    }
12263
12264    /**
12265     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12266     * set any flags or handle all of the cases handled by the default invalidation methods.
12267     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12268     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12269     * walk up the hierarchy, transforming the dirty rect as necessary.
12270     *
12271     * The method also handles normal invalidation logic if display list properties are not
12272     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12273     * backup approach, to handle these cases used in the various property-setting methods.
12274     *
12275     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12276     * are not being used in this view
12277     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12278     * list properties are not being used in this view
12279     */
12280    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12281        if (!isHardwareAccelerated()
12282                || !mRenderNode.isValid()
12283                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12284            if (invalidateParent) {
12285                invalidateParentCaches();
12286            }
12287            if (forceRedraw) {
12288                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12289            }
12290            invalidate(false);
12291        } else {
12292            damageInParent();
12293        }
12294        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12295            damageShadowReceiver();
12296        }
12297    }
12298
12299    /**
12300     * Tells the parent view to damage this view's bounds.
12301     *
12302     * @hide
12303     */
12304    protected void damageInParent() {
12305        final AttachInfo ai = mAttachInfo;
12306        final ViewParent p = mParent;
12307        if (p != null && ai != null) {
12308            final Rect r = ai.mTmpInvalRect;
12309            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12310            if (mParent instanceof ViewGroup) {
12311                ((ViewGroup) mParent).damageChild(this, r);
12312            } else {
12313                mParent.invalidateChild(this, r);
12314            }
12315        }
12316    }
12317
12318    /**
12319     * Utility method to transform a given Rect by the current matrix of this view.
12320     */
12321    void transformRect(final Rect rect) {
12322        if (!getMatrix().isIdentity()) {
12323            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12324            boundingRect.set(rect);
12325            getMatrix().mapRect(boundingRect);
12326            rect.set((int) Math.floor(boundingRect.left),
12327                    (int) Math.floor(boundingRect.top),
12328                    (int) Math.ceil(boundingRect.right),
12329                    (int) Math.ceil(boundingRect.bottom));
12330        }
12331    }
12332
12333    /**
12334     * Used to indicate that the parent of this view should clear its caches. This functionality
12335     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12336     * which is necessary when various parent-managed properties of the view change, such as
12337     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12338     * clears the parent caches and does not causes an invalidate event.
12339     *
12340     * @hide
12341     */
12342    protected void invalidateParentCaches() {
12343        if (mParent instanceof View) {
12344            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12345        }
12346    }
12347
12348    /**
12349     * Used to indicate that the parent of this view should be invalidated. This functionality
12350     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12351     * which is necessary when various parent-managed properties of the view change, such as
12352     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12353     * an invalidation event to the parent.
12354     *
12355     * @hide
12356     */
12357    protected void invalidateParentIfNeeded() {
12358        if (isHardwareAccelerated() && mParent instanceof View) {
12359            ((View) mParent).invalidate(true);
12360        }
12361    }
12362
12363    /**
12364     * @hide
12365     */
12366    protected void invalidateParentIfNeededAndWasQuickRejected() {
12367        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12368            // View was rejected last time it was drawn by its parent; this may have changed
12369            invalidateParentIfNeeded();
12370        }
12371    }
12372
12373    /**
12374     * Indicates whether this View is opaque. An opaque View guarantees that it will
12375     * draw all the pixels overlapping its bounds using a fully opaque color.
12376     *
12377     * Subclasses of View should override this method whenever possible to indicate
12378     * whether an instance is opaque. Opaque Views are treated in a special way by
12379     * the View hierarchy, possibly allowing it to perform optimizations during
12380     * invalidate/draw passes.
12381     *
12382     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12383     */
12384    @ViewDebug.ExportedProperty(category = "drawing")
12385    public boolean isOpaque() {
12386        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12387                getFinalAlpha() >= 1.0f;
12388    }
12389
12390    /**
12391     * @hide
12392     */
12393    protected void computeOpaqueFlags() {
12394        // Opaque if:
12395        //   - Has a background
12396        //   - Background is opaque
12397        //   - Doesn't have scrollbars or scrollbars overlay
12398
12399        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12400            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12401        } else {
12402            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12403        }
12404
12405        final int flags = mViewFlags;
12406        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12407                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12408                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12409            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12410        } else {
12411            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12412        }
12413    }
12414
12415    /**
12416     * @hide
12417     */
12418    protected boolean hasOpaqueScrollbars() {
12419        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12420    }
12421
12422    /**
12423     * @return A handler associated with the thread running the View. This
12424     * handler can be used to pump events in the UI events queue.
12425     */
12426    public Handler getHandler() {
12427        final AttachInfo attachInfo = mAttachInfo;
12428        if (attachInfo != null) {
12429            return attachInfo.mHandler;
12430        }
12431        return null;
12432    }
12433
12434    /**
12435     * Gets the view root associated with the View.
12436     * @return The view root, or null if none.
12437     * @hide
12438     */
12439    public ViewRootImpl getViewRootImpl() {
12440        if (mAttachInfo != null) {
12441            return mAttachInfo.mViewRootImpl;
12442        }
12443        return null;
12444    }
12445
12446    /**
12447     * @hide
12448     */
12449    public HardwareRenderer getHardwareRenderer() {
12450        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12451    }
12452
12453    /**
12454     * <p>Causes the Runnable to be added to the message queue.
12455     * The runnable will be run on the user interface thread.</p>
12456     *
12457     * @param action The Runnable that will be executed.
12458     *
12459     * @return Returns true if the Runnable was successfully placed in to the
12460     *         message queue.  Returns false on failure, usually because the
12461     *         looper processing the message queue is exiting.
12462     *
12463     * @see #postDelayed
12464     * @see #removeCallbacks
12465     */
12466    public boolean post(Runnable action) {
12467        final AttachInfo attachInfo = mAttachInfo;
12468        if (attachInfo != null) {
12469            return attachInfo.mHandler.post(action);
12470        }
12471        // Assume that post will succeed later
12472        ViewRootImpl.getRunQueue().post(action);
12473        return true;
12474    }
12475
12476    /**
12477     * <p>Causes the Runnable to be added to the message queue, to be run
12478     * after the specified amount of time elapses.
12479     * The runnable will be run on the user interface thread.</p>
12480     *
12481     * @param action The Runnable that will be executed.
12482     * @param delayMillis The delay (in milliseconds) until the Runnable
12483     *        will be executed.
12484     *
12485     * @return true if the Runnable was successfully placed in to the
12486     *         message queue.  Returns false on failure, usually because the
12487     *         looper processing the message queue is exiting.  Note that a
12488     *         result of true does not mean the Runnable will be processed --
12489     *         if the looper is quit before the delivery time of the message
12490     *         occurs then the message will be dropped.
12491     *
12492     * @see #post
12493     * @see #removeCallbacks
12494     */
12495    public boolean postDelayed(Runnable action, long delayMillis) {
12496        final AttachInfo attachInfo = mAttachInfo;
12497        if (attachInfo != null) {
12498            return attachInfo.mHandler.postDelayed(action, delayMillis);
12499        }
12500        // Assume that post will succeed later
12501        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12502        return true;
12503    }
12504
12505    /**
12506     * <p>Causes the Runnable to execute on the next animation time step.
12507     * The runnable will be run on the user interface thread.</p>
12508     *
12509     * @param action The Runnable that will be executed.
12510     *
12511     * @see #postOnAnimationDelayed
12512     * @see #removeCallbacks
12513     */
12514    public void postOnAnimation(Runnable action) {
12515        final AttachInfo attachInfo = mAttachInfo;
12516        if (attachInfo != null) {
12517            attachInfo.mViewRootImpl.mChoreographer.postCallback(
12518                    Choreographer.CALLBACK_ANIMATION, action, null);
12519        } else {
12520            // Assume that post will succeed later
12521            ViewRootImpl.getRunQueue().post(action);
12522        }
12523    }
12524
12525    /**
12526     * <p>Causes the Runnable to execute on the next animation time step,
12527     * after the specified amount of time elapses.
12528     * The runnable will be run on the user interface thread.</p>
12529     *
12530     * @param action The Runnable that will be executed.
12531     * @param delayMillis The delay (in milliseconds) until the Runnable
12532     *        will be executed.
12533     *
12534     * @see #postOnAnimation
12535     * @see #removeCallbacks
12536     */
12537    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12538        final AttachInfo attachInfo = mAttachInfo;
12539        if (attachInfo != null) {
12540            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12541                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12542        } else {
12543            // Assume that post will succeed later
12544            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12545        }
12546    }
12547
12548    /**
12549     * <p>Removes the specified Runnable from the message queue.</p>
12550     *
12551     * @param action The Runnable to remove from the message handling queue
12552     *
12553     * @return true if this view could ask the Handler to remove the Runnable,
12554     *         false otherwise. When the returned value is true, the Runnable
12555     *         may or may not have been actually removed from the message queue
12556     *         (for instance, if the Runnable was not in the queue already.)
12557     *
12558     * @see #post
12559     * @see #postDelayed
12560     * @see #postOnAnimation
12561     * @see #postOnAnimationDelayed
12562     */
12563    public boolean removeCallbacks(Runnable action) {
12564        if (action != null) {
12565            final AttachInfo attachInfo = mAttachInfo;
12566            if (attachInfo != null) {
12567                attachInfo.mHandler.removeCallbacks(action);
12568                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12569                        Choreographer.CALLBACK_ANIMATION, action, null);
12570            }
12571            // Assume that post will succeed later
12572            ViewRootImpl.getRunQueue().removeCallbacks(action);
12573        }
12574        return true;
12575    }
12576
12577    /**
12578     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12579     * Use this to invalidate the View from a non-UI thread.</p>
12580     *
12581     * <p>This method can be invoked from outside of the UI thread
12582     * only when this View is attached to a window.</p>
12583     *
12584     * @see #invalidate()
12585     * @see #postInvalidateDelayed(long)
12586     */
12587    public void postInvalidate() {
12588        postInvalidateDelayed(0);
12589    }
12590
12591    /**
12592     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12593     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12594     *
12595     * <p>This method can be invoked from outside of the UI thread
12596     * only when this View is attached to a window.</p>
12597     *
12598     * @param left The left coordinate of the rectangle to invalidate.
12599     * @param top The top coordinate of the rectangle to invalidate.
12600     * @param right The right coordinate of the rectangle to invalidate.
12601     * @param bottom The bottom coordinate of the rectangle to invalidate.
12602     *
12603     * @see #invalidate(int, int, int, int)
12604     * @see #invalidate(Rect)
12605     * @see #postInvalidateDelayed(long, int, int, int, int)
12606     */
12607    public void postInvalidate(int left, int top, int right, int bottom) {
12608        postInvalidateDelayed(0, left, top, right, bottom);
12609    }
12610
12611    /**
12612     * <p>Cause an invalidate to happen on a subsequent cycle through the event
12613     * loop. Waits for the specified amount of time.</p>
12614     *
12615     * <p>This method can be invoked from outside of the UI thread
12616     * only when this View is attached to a window.</p>
12617     *
12618     * @param delayMilliseconds the duration in milliseconds to delay the
12619     *         invalidation by
12620     *
12621     * @see #invalidate()
12622     * @see #postInvalidate()
12623     */
12624    public void postInvalidateDelayed(long delayMilliseconds) {
12625        // We try only with the AttachInfo because there's no point in invalidating
12626        // if we are not attached to our window
12627        final AttachInfo attachInfo = mAttachInfo;
12628        if (attachInfo != null) {
12629            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12630        }
12631    }
12632
12633    /**
12634     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12635     * through the event loop. Waits for the specified amount of time.</p>
12636     *
12637     * <p>This method can be invoked from outside of the UI thread
12638     * only when this View is attached to a window.</p>
12639     *
12640     * @param delayMilliseconds the duration in milliseconds to delay the
12641     *         invalidation by
12642     * @param left The left coordinate of the rectangle to invalidate.
12643     * @param top The top coordinate of the rectangle to invalidate.
12644     * @param right The right coordinate of the rectangle to invalidate.
12645     * @param bottom The bottom coordinate of the rectangle to invalidate.
12646     *
12647     * @see #invalidate(int, int, int, int)
12648     * @see #invalidate(Rect)
12649     * @see #postInvalidate(int, int, int, int)
12650     */
12651    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12652            int right, int bottom) {
12653
12654        // We try only with the AttachInfo because there's no point in invalidating
12655        // if we are not attached to our window
12656        final AttachInfo attachInfo = mAttachInfo;
12657        if (attachInfo != null) {
12658            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12659            info.target = this;
12660            info.left = left;
12661            info.top = top;
12662            info.right = right;
12663            info.bottom = bottom;
12664
12665            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12666        }
12667    }
12668
12669    /**
12670     * <p>Cause an invalidate to happen on the next animation time step, typically the
12671     * next display frame.</p>
12672     *
12673     * <p>This method can be invoked from outside of the UI thread
12674     * only when this View is attached to a window.</p>
12675     *
12676     * @see #invalidate()
12677     */
12678    public void postInvalidateOnAnimation() {
12679        // We try only with the AttachInfo because there's no point in invalidating
12680        // if we are not attached to our window
12681        final AttachInfo attachInfo = mAttachInfo;
12682        if (attachInfo != null) {
12683            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12684        }
12685    }
12686
12687    /**
12688     * <p>Cause an invalidate of the specified area to happen on the next animation
12689     * time step, typically the next display frame.</p>
12690     *
12691     * <p>This method can be invoked from outside of the UI thread
12692     * only when this View is attached to a window.</p>
12693     *
12694     * @param left The left coordinate of the rectangle to invalidate.
12695     * @param top The top coordinate of the rectangle to invalidate.
12696     * @param right The right coordinate of the rectangle to invalidate.
12697     * @param bottom The bottom coordinate of the rectangle to invalidate.
12698     *
12699     * @see #invalidate(int, int, int, int)
12700     * @see #invalidate(Rect)
12701     */
12702    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12703        // We try only with the AttachInfo because there's no point in invalidating
12704        // if we are not attached to our window
12705        final AttachInfo attachInfo = mAttachInfo;
12706        if (attachInfo != null) {
12707            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12708            info.target = this;
12709            info.left = left;
12710            info.top = top;
12711            info.right = right;
12712            info.bottom = bottom;
12713
12714            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12715        }
12716    }
12717
12718    /**
12719     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12720     * This event is sent at most once every
12721     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12722     */
12723    private void postSendViewScrolledAccessibilityEventCallback() {
12724        if (mSendViewScrolledAccessibilityEvent == null) {
12725            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12726        }
12727        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12728            mSendViewScrolledAccessibilityEvent.mIsPending = true;
12729            postDelayed(mSendViewScrolledAccessibilityEvent,
12730                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12731        }
12732    }
12733
12734    /**
12735     * Called by a parent to request that a child update its values for mScrollX
12736     * and mScrollY if necessary. This will typically be done if the child is
12737     * animating a scroll using a {@link android.widget.Scroller Scroller}
12738     * object.
12739     */
12740    public void computeScroll() {
12741    }
12742
12743    /**
12744     * <p>Indicate whether the horizontal edges are faded when the view is
12745     * scrolled horizontally.</p>
12746     *
12747     * @return true if the horizontal edges should are faded on scroll, false
12748     *         otherwise
12749     *
12750     * @see #setHorizontalFadingEdgeEnabled(boolean)
12751     *
12752     * @attr ref android.R.styleable#View_requiresFadingEdge
12753     */
12754    public boolean isHorizontalFadingEdgeEnabled() {
12755        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12756    }
12757
12758    /**
12759     * <p>Define whether the horizontal edges should be faded when this view
12760     * is scrolled horizontally.</p>
12761     *
12762     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12763     *                                    be faded when the view is scrolled
12764     *                                    horizontally
12765     *
12766     * @see #isHorizontalFadingEdgeEnabled()
12767     *
12768     * @attr ref android.R.styleable#View_requiresFadingEdge
12769     */
12770    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12771        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12772            if (horizontalFadingEdgeEnabled) {
12773                initScrollCache();
12774            }
12775
12776            mViewFlags ^= FADING_EDGE_HORIZONTAL;
12777        }
12778    }
12779
12780    /**
12781     * <p>Indicate whether the vertical edges are faded when the view is
12782     * scrolled horizontally.</p>
12783     *
12784     * @return true if the vertical edges should are faded on scroll, false
12785     *         otherwise
12786     *
12787     * @see #setVerticalFadingEdgeEnabled(boolean)
12788     *
12789     * @attr ref android.R.styleable#View_requiresFadingEdge
12790     */
12791    public boolean isVerticalFadingEdgeEnabled() {
12792        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12793    }
12794
12795    /**
12796     * <p>Define whether the vertical edges should be faded when this view
12797     * is scrolled vertically.</p>
12798     *
12799     * @param verticalFadingEdgeEnabled true if the vertical edges should
12800     *                                  be faded when the view is scrolled
12801     *                                  vertically
12802     *
12803     * @see #isVerticalFadingEdgeEnabled()
12804     *
12805     * @attr ref android.R.styleable#View_requiresFadingEdge
12806     */
12807    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12808        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12809            if (verticalFadingEdgeEnabled) {
12810                initScrollCache();
12811            }
12812
12813            mViewFlags ^= FADING_EDGE_VERTICAL;
12814        }
12815    }
12816
12817    /**
12818     * Returns the strength, or intensity, of the top faded edge. The strength is
12819     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12820     * returns 0.0 or 1.0 but no value in between.
12821     *
12822     * Subclasses should override this method to provide a smoother fade transition
12823     * when scrolling occurs.
12824     *
12825     * @return the intensity of the top fade as a float between 0.0f and 1.0f
12826     */
12827    protected float getTopFadingEdgeStrength() {
12828        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12829    }
12830
12831    /**
12832     * Returns the strength, or intensity, of the bottom faded edge. The strength is
12833     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12834     * returns 0.0 or 1.0 but no value in between.
12835     *
12836     * Subclasses should override this method to provide a smoother fade transition
12837     * when scrolling occurs.
12838     *
12839     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12840     */
12841    protected float getBottomFadingEdgeStrength() {
12842        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12843                computeVerticalScrollRange() ? 1.0f : 0.0f;
12844    }
12845
12846    /**
12847     * Returns the strength, or intensity, of the left faded edge. The strength is
12848     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12849     * returns 0.0 or 1.0 but no value in between.
12850     *
12851     * Subclasses should override this method to provide a smoother fade transition
12852     * when scrolling occurs.
12853     *
12854     * @return the intensity of the left fade as a float between 0.0f and 1.0f
12855     */
12856    protected float getLeftFadingEdgeStrength() {
12857        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12858    }
12859
12860    /**
12861     * Returns the strength, or intensity, of the right faded edge. The strength is
12862     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12863     * returns 0.0 or 1.0 but no value in between.
12864     *
12865     * Subclasses should override this method to provide a smoother fade transition
12866     * when scrolling occurs.
12867     *
12868     * @return the intensity of the right fade as a float between 0.0f and 1.0f
12869     */
12870    protected float getRightFadingEdgeStrength() {
12871        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12872                computeHorizontalScrollRange() ? 1.0f : 0.0f;
12873    }
12874
12875    /**
12876     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12877     * scrollbar is not drawn by default.</p>
12878     *
12879     * @return true if the horizontal scrollbar should be painted, false
12880     *         otherwise
12881     *
12882     * @see #setHorizontalScrollBarEnabled(boolean)
12883     */
12884    public boolean isHorizontalScrollBarEnabled() {
12885        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12886    }
12887
12888    /**
12889     * <p>Define whether the horizontal scrollbar should be drawn or not. The
12890     * scrollbar is not drawn by default.</p>
12891     *
12892     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12893     *                                   be painted
12894     *
12895     * @see #isHorizontalScrollBarEnabled()
12896     */
12897    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12898        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12899            mViewFlags ^= SCROLLBARS_HORIZONTAL;
12900            computeOpaqueFlags();
12901            resolvePadding();
12902        }
12903    }
12904
12905    /**
12906     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12907     * scrollbar is not drawn by default.</p>
12908     *
12909     * @return true if the vertical scrollbar should be painted, false
12910     *         otherwise
12911     *
12912     * @see #setVerticalScrollBarEnabled(boolean)
12913     */
12914    public boolean isVerticalScrollBarEnabled() {
12915        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12916    }
12917
12918    /**
12919     * <p>Define whether the vertical scrollbar should be drawn or not. The
12920     * scrollbar is not drawn by default.</p>
12921     *
12922     * @param verticalScrollBarEnabled true if the vertical scrollbar should
12923     *                                 be painted
12924     *
12925     * @see #isVerticalScrollBarEnabled()
12926     */
12927    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12928        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12929            mViewFlags ^= SCROLLBARS_VERTICAL;
12930            computeOpaqueFlags();
12931            resolvePadding();
12932        }
12933    }
12934
12935    /**
12936     * @hide
12937     */
12938    protected void recomputePadding() {
12939        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12940    }
12941
12942    /**
12943     * Define whether scrollbars will fade when the view is not scrolling.
12944     *
12945     * @param fadeScrollbars whether to enable fading
12946     *
12947     * @attr ref android.R.styleable#View_fadeScrollbars
12948     */
12949    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12950        initScrollCache();
12951        final ScrollabilityCache scrollabilityCache = mScrollCache;
12952        scrollabilityCache.fadeScrollBars = fadeScrollbars;
12953        if (fadeScrollbars) {
12954            scrollabilityCache.state = ScrollabilityCache.OFF;
12955        } else {
12956            scrollabilityCache.state = ScrollabilityCache.ON;
12957        }
12958    }
12959
12960    /**
12961     *
12962     * Returns true if scrollbars will fade when this view is not scrolling
12963     *
12964     * @return true if scrollbar fading is enabled
12965     *
12966     * @attr ref android.R.styleable#View_fadeScrollbars
12967     */
12968    public boolean isScrollbarFadingEnabled() {
12969        return mScrollCache != null && mScrollCache.fadeScrollBars;
12970    }
12971
12972    /**
12973     *
12974     * Returns the delay before scrollbars fade.
12975     *
12976     * @return the delay before scrollbars fade
12977     *
12978     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12979     */
12980    public int getScrollBarDefaultDelayBeforeFade() {
12981        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12982                mScrollCache.scrollBarDefaultDelayBeforeFade;
12983    }
12984
12985    /**
12986     * Define the delay before scrollbars fade.
12987     *
12988     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12989     *
12990     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12991     */
12992    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12993        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12994    }
12995
12996    /**
12997     *
12998     * Returns the scrollbar fade duration.
12999     *
13000     * @return the scrollbar fade duration
13001     *
13002     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13003     */
13004    public int getScrollBarFadeDuration() {
13005        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13006                mScrollCache.scrollBarFadeDuration;
13007    }
13008
13009    /**
13010     * Define the scrollbar fade duration.
13011     *
13012     * @param scrollBarFadeDuration - the scrollbar fade duration
13013     *
13014     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13015     */
13016    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13017        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13018    }
13019
13020    /**
13021     *
13022     * Returns the scrollbar size.
13023     *
13024     * @return the scrollbar size
13025     *
13026     * @attr ref android.R.styleable#View_scrollbarSize
13027     */
13028    public int getScrollBarSize() {
13029        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13030                mScrollCache.scrollBarSize;
13031    }
13032
13033    /**
13034     * Define the scrollbar size.
13035     *
13036     * @param scrollBarSize - the scrollbar size
13037     *
13038     * @attr ref android.R.styleable#View_scrollbarSize
13039     */
13040    public void setScrollBarSize(int scrollBarSize) {
13041        getScrollCache().scrollBarSize = scrollBarSize;
13042    }
13043
13044    /**
13045     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13046     * inset. When inset, they add to the padding of the view. And the scrollbars
13047     * can be drawn inside the padding area or on the edge of the view. For example,
13048     * if a view has a background drawable and you want to draw the scrollbars
13049     * inside the padding specified by the drawable, you can use
13050     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13051     * appear at the edge of the view, ignoring the padding, then you can use
13052     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13053     * @param style the style of the scrollbars. Should be one of
13054     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13055     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13056     * @see #SCROLLBARS_INSIDE_OVERLAY
13057     * @see #SCROLLBARS_INSIDE_INSET
13058     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13059     * @see #SCROLLBARS_OUTSIDE_INSET
13060     *
13061     * @attr ref android.R.styleable#View_scrollbarStyle
13062     */
13063    public void setScrollBarStyle(@ScrollBarStyle int style) {
13064        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13065            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13066            computeOpaqueFlags();
13067            resolvePadding();
13068        }
13069    }
13070
13071    /**
13072     * <p>Returns the current scrollbar style.</p>
13073     * @return the current scrollbar style
13074     * @see #SCROLLBARS_INSIDE_OVERLAY
13075     * @see #SCROLLBARS_INSIDE_INSET
13076     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13077     * @see #SCROLLBARS_OUTSIDE_INSET
13078     *
13079     * @attr ref android.R.styleable#View_scrollbarStyle
13080     */
13081    @ViewDebug.ExportedProperty(mapping = {
13082            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13083            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13084            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13085            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13086    })
13087    @ScrollBarStyle
13088    public int getScrollBarStyle() {
13089        return mViewFlags & SCROLLBARS_STYLE_MASK;
13090    }
13091
13092    /**
13093     * <p>Compute the horizontal range that the horizontal scrollbar
13094     * represents.</p>
13095     *
13096     * <p>The range is expressed in arbitrary units that must be the same as the
13097     * units used by {@link #computeHorizontalScrollExtent()} and
13098     * {@link #computeHorizontalScrollOffset()}.</p>
13099     *
13100     * <p>The default range is the drawing width of this view.</p>
13101     *
13102     * @return the total horizontal range represented by the horizontal
13103     *         scrollbar
13104     *
13105     * @see #computeHorizontalScrollExtent()
13106     * @see #computeHorizontalScrollOffset()
13107     * @see android.widget.ScrollBarDrawable
13108     */
13109    protected int computeHorizontalScrollRange() {
13110        return getWidth();
13111    }
13112
13113    /**
13114     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13115     * within the horizontal range. This value is used to compute the position
13116     * of the thumb within the scrollbar's track.</p>
13117     *
13118     * <p>The range is expressed in arbitrary units that must be the same as the
13119     * units used by {@link #computeHorizontalScrollRange()} and
13120     * {@link #computeHorizontalScrollExtent()}.</p>
13121     *
13122     * <p>The default offset is the scroll offset of this view.</p>
13123     *
13124     * @return the horizontal offset of the scrollbar's thumb
13125     *
13126     * @see #computeHorizontalScrollRange()
13127     * @see #computeHorizontalScrollExtent()
13128     * @see android.widget.ScrollBarDrawable
13129     */
13130    protected int computeHorizontalScrollOffset() {
13131        return mScrollX;
13132    }
13133
13134    /**
13135     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13136     * within the horizontal range. This value is used to compute the length
13137     * of the thumb within the scrollbar's track.</p>
13138     *
13139     * <p>The range is expressed in arbitrary units that must be the same as the
13140     * units used by {@link #computeHorizontalScrollRange()} and
13141     * {@link #computeHorizontalScrollOffset()}.</p>
13142     *
13143     * <p>The default extent is the drawing width of this view.</p>
13144     *
13145     * @return the horizontal extent of the scrollbar's thumb
13146     *
13147     * @see #computeHorizontalScrollRange()
13148     * @see #computeHorizontalScrollOffset()
13149     * @see android.widget.ScrollBarDrawable
13150     */
13151    protected int computeHorizontalScrollExtent() {
13152        return getWidth();
13153    }
13154
13155    /**
13156     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13157     *
13158     * <p>The range is expressed in arbitrary units that must be the same as the
13159     * units used by {@link #computeVerticalScrollExtent()} and
13160     * {@link #computeVerticalScrollOffset()}.</p>
13161     *
13162     * @return the total vertical range represented by the vertical scrollbar
13163     *
13164     * <p>The default range is the drawing height of this view.</p>
13165     *
13166     * @see #computeVerticalScrollExtent()
13167     * @see #computeVerticalScrollOffset()
13168     * @see android.widget.ScrollBarDrawable
13169     */
13170    protected int computeVerticalScrollRange() {
13171        return getHeight();
13172    }
13173
13174    /**
13175     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13176     * within the horizontal range. This value is used to compute the position
13177     * of the thumb within the scrollbar's track.</p>
13178     *
13179     * <p>The range is expressed in arbitrary units that must be the same as the
13180     * units used by {@link #computeVerticalScrollRange()} and
13181     * {@link #computeVerticalScrollExtent()}.</p>
13182     *
13183     * <p>The default offset is the scroll offset of this view.</p>
13184     *
13185     * @return the vertical offset of the scrollbar's thumb
13186     *
13187     * @see #computeVerticalScrollRange()
13188     * @see #computeVerticalScrollExtent()
13189     * @see android.widget.ScrollBarDrawable
13190     */
13191    protected int computeVerticalScrollOffset() {
13192        return mScrollY;
13193    }
13194
13195    /**
13196     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13197     * within the vertical range. This value is used to compute the length
13198     * of the thumb within the scrollbar's track.</p>
13199     *
13200     * <p>The range is expressed in arbitrary units that must be the same as the
13201     * units used by {@link #computeVerticalScrollRange()} and
13202     * {@link #computeVerticalScrollOffset()}.</p>
13203     *
13204     * <p>The default extent is the drawing height of this view.</p>
13205     *
13206     * @return the vertical extent of the scrollbar's thumb
13207     *
13208     * @see #computeVerticalScrollRange()
13209     * @see #computeVerticalScrollOffset()
13210     * @see android.widget.ScrollBarDrawable
13211     */
13212    protected int computeVerticalScrollExtent() {
13213        return getHeight();
13214    }
13215
13216    /**
13217     * Check if this view can be scrolled horizontally in a certain direction.
13218     *
13219     * @param direction Negative to check scrolling left, positive to check scrolling right.
13220     * @return true if this view can be scrolled in the specified direction, false otherwise.
13221     */
13222    public boolean canScrollHorizontally(int direction) {
13223        final int offset = computeHorizontalScrollOffset();
13224        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13225        if (range == 0) return false;
13226        if (direction < 0) {
13227            return offset > 0;
13228        } else {
13229            return offset < range - 1;
13230        }
13231    }
13232
13233    /**
13234     * Check if this view can be scrolled vertically in a certain direction.
13235     *
13236     * @param direction Negative to check scrolling up, positive to check scrolling down.
13237     * @return true if this view can be scrolled in the specified direction, false otherwise.
13238     */
13239    public boolean canScrollVertically(int direction) {
13240        final int offset = computeVerticalScrollOffset();
13241        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13242        if (range == 0) return false;
13243        if (direction < 0) {
13244            return offset > 0;
13245        } else {
13246            return offset < range - 1;
13247        }
13248    }
13249
13250    /**
13251     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13252     * scrollbars are painted only if they have been awakened first.</p>
13253     *
13254     * @param canvas the canvas on which to draw the scrollbars
13255     *
13256     * @see #awakenScrollBars(int)
13257     */
13258    protected final void onDrawScrollBars(Canvas canvas) {
13259        // scrollbars are drawn only when the animation is running
13260        final ScrollabilityCache cache = mScrollCache;
13261        if (cache != null) {
13262
13263            int state = cache.state;
13264
13265            if (state == ScrollabilityCache.OFF) {
13266                return;
13267            }
13268
13269            boolean invalidate = false;
13270
13271            if (state == ScrollabilityCache.FADING) {
13272                // We're fading -- get our fade interpolation
13273                if (cache.interpolatorValues == null) {
13274                    cache.interpolatorValues = new float[1];
13275                }
13276
13277                float[] values = cache.interpolatorValues;
13278
13279                // Stops the animation if we're done
13280                if (cache.scrollBarInterpolator.timeToValues(values) ==
13281                        Interpolator.Result.FREEZE_END) {
13282                    cache.state = ScrollabilityCache.OFF;
13283                } else {
13284                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13285                }
13286
13287                // This will make the scroll bars inval themselves after
13288                // drawing. We only want this when we're fading so that
13289                // we prevent excessive redraws
13290                invalidate = true;
13291            } else {
13292                // We're just on -- but we may have been fading before so
13293                // reset alpha
13294                cache.scrollBar.mutate().setAlpha(255);
13295            }
13296
13297
13298            final int viewFlags = mViewFlags;
13299
13300            final boolean drawHorizontalScrollBar =
13301                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13302            final boolean drawVerticalScrollBar =
13303                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13304                && !isVerticalScrollBarHidden();
13305
13306            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13307                final int width = mRight - mLeft;
13308                final int height = mBottom - mTop;
13309
13310                final ScrollBarDrawable scrollBar = cache.scrollBar;
13311
13312                final int scrollX = mScrollX;
13313                final int scrollY = mScrollY;
13314                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13315
13316                int left;
13317                int top;
13318                int right;
13319                int bottom;
13320
13321                if (drawHorizontalScrollBar) {
13322                    int size = scrollBar.getSize(false);
13323                    if (size <= 0) {
13324                        size = cache.scrollBarSize;
13325                    }
13326
13327                    scrollBar.setParameters(computeHorizontalScrollRange(),
13328                                            computeHorizontalScrollOffset(),
13329                                            computeHorizontalScrollExtent(), false);
13330                    final int verticalScrollBarGap = drawVerticalScrollBar ?
13331                            getVerticalScrollbarWidth() : 0;
13332                    top = scrollY + height - size - (mUserPaddingBottom & inside);
13333                    left = scrollX + (mPaddingLeft & inside);
13334                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13335                    bottom = top + size;
13336                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13337                    if (invalidate) {
13338                        invalidate(left, top, right, bottom);
13339                    }
13340                }
13341
13342                if (drawVerticalScrollBar) {
13343                    int size = scrollBar.getSize(true);
13344                    if (size <= 0) {
13345                        size = cache.scrollBarSize;
13346                    }
13347
13348                    scrollBar.setParameters(computeVerticalScrollRange(),
13349                                            computeVerticalScrollOffset(),
13350                                            computeVerticalScrollExtent(), true);
13351                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
13352                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13353                        verticalScrollbarPosition = isLayoutRtl() ?
13354                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13355                    }
13356                    switch (verticalScrollbarPosition) {
13357                        default:
13358                        case SCROLLBAR_POSITION_RIGHT:
13359                            left = scrollX + width - size - (mUserPaddingRight & inside);
13360                            break;
13361                        case SCROLLBAR_POSITION_LEFT:
13362                            left = scrollX + (mUserPaddingLeft & inside);
13363                            break;
13364                    }
13365                    top = scrollY + (mPaddingTop & inside);
13366                    right = left + size;
13367                    bottom = scrollY + height - (mUserPaddingBottom & inside);
13368                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13369                    if (invalidate) {
13370                        invalidate(left, top, right, bottom);
13371                    }
13372                }
13373            }
13374        }
13375    }
13376
13377    /**
13378     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13379     * FastScroller is visible.
13380     * @return whether to temporarily hide the vertical scrollbar
13381     * @hide
13382     */
13383    protected boolean isVerticalScrollBarHidden() {
13384        return false;
13385    }
13386
13387    /**
13388     * <p>Draw the horizontal scrollbar if
13389     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13390     *
13391     * @param canvas the canvas on which to draw the scrollbar
13392     * @param scrollBar the scrollbar's drawable
13393     *
13394     * @see #isHorizontalScrollBarEnabled()
13395     * @see #computeHorizontalScrollRange()
13396     * @see #computeHorizontalScrollExtent()
13397     * @see #computeHorizontalScrollOffset()
13398     * @see android.widget.ScrollBarDrawable
13399     * @hide
13400     */
13401    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13402            int l, int t, int r, int b) {
13403        scrollBar.setBounds(l, t, r, b);
13404        scrollBar.draw(canvas);
13405    }
13406
13407    /**
13408     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13409     * returns true.</p>
13410     *
13411     * @param canvas the canvas on which to draw the scrollbar
13412     * @param scrollBar the scrollbar's drawable
13413     *
13414     * @see #isVerticalScrollBarEnabled()
13415     * @see #computeVerticalScrollRange()
13416     * @see #computeVerticalScrollExtent()
13417     * @see #computeVerticalScrollOffset()
13418     * @see android.widget.ScrollBarDrawable
13419     * @hide
13420     */
13421    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13422            int l, int t, int r, int b) {
13423        scrollBar.setBounds(l, t, r, b);
13424        scrollBar.draw(canvas);
13425    }
13426
13427    /**
13428     * Implement this to do your drawing.
13429     *
13430     * @param canvas the canvas on which the background will be drawn
13431     */
13432    protected void onDraw(Canvas canvas) {
13433    }
13434
13435    /*
13436     * Caller is responsible for calling requestLayout if necessary.
13437     * (This allows addViewInLayout to not request a new layout.)
13438     */
13439    void assignParent(ViewParent parent) {
13440        if (mParent == null) {
13441            mParent = parent;
13442        } else if (parent == null) {
13443            mParent = null;
13444        } else {
13445            throw new RuntimeException("view " + this + " being added, but"
13446                    + " it already has a parent");
13447        }
13448    }
13449
13450    /**
13451     * This is called when the view is attached to a window.  At this point it
13452     * has a Surface and will start drawing.  Note that this function is
13453     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13454     * however it may be called any time before the first onDraw -- including
13455     * before or after {@link #onMeasure(int, int)}.
13456     *
13457     * @see #onDetachedFromWindow()
13458     */
13459    @CallSuper
13460    protected void onAttachedToWindow() {
13461        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13462            mParent.requestTransparentRegion(this);
13463        }
13464
13465        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
13466            initialAwakenScrollBars();
13467            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
13468        }
13469
13470        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13471
13472        jumpDrawablesToCurrentState();
13473
13474        resetSubtreeAccessibilityStateChanged();
13475
13476        // rebuild, since Outline not maintained while View is detached
13477        rebuildOutline();
13478
13479        if (isFocused()) {
13480            InputMethodManager imm = InputMethodManager.peekInstance();
13481            if (imm != null) {
13482                imm.focusIn(this);
13483            }
13484        }
13485    }
13486
13487    /**
13488     * Resolve all RTL related properties.
13489     *
13490     * @return true if resolution of RTL properties has been done
13491     *
13492     * @hide
13493     */
13494    public boolean resolveRtlPropertiesIfNeeded() {
13495        if (!needRtlPropertiesResolution()) return false;
13496
13497        // Order is important here: LayoutDirection MUST be resolved first
13498        if (!isLayoutDirectionResolved()) {
13499            resolveLayoutDirection();
13500            resolveLayoutParams();
13501        }
13502        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
13503        if (!isTextDirectionResolved()) {
13504            resolveTextDirection();
13505        }
13506        if (!isTextAlignmentResolved()) {
13507            resolveTextAlignment();
13508        }
13509        // Should resolve Drawables before Padding because we need the layout direction of the
13510        // Drawable to correctly resolve Padding.
13511        if (!areDrawablesResolved()) {
13512            resolveDrawables();
13513        }
13514        if (!isPaddingResolved()) {
13515            resolvePadding();
13516        }
13517        onRtlPropertiesChanged(getLayoutDirection());
13518        return true;
13519    }
13520
13521    /**
13522     * Reset resolution of all RTL related properties.
13523     *
13524     * @hide
13525     */
13526    public void resetRtlProperties() {
13527        resetResolvedLayoutDirection();
13528        resetResolvedTextDirection();
13529        resetResolvedTextAlignment();
13530        resetResolvedPadding();
13531        resetResolvedDrawables();
13532    }
13533
13534    /**
13535     * @see #onScreenStateChanged(int)
13536     */
13537    void dispatchScreenStateChanged(int screenState) {
13538        onScreenStateChanged(screenState);
13539    }
13540
13541    /**
13542     * This method is called whenever the state of the screen this view is
13543     * attached to changes. A state change will usually occurs when the screen
13544     * turns on or off (whether it happens automatically or the user does it
13545     * manually.)
13546     *
13547     * @param screenState The new state of the screen. Can be either
13548     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13549     */
13550    public void onScreenStateChanged(int screenState) {
13551    }
13552
13553    /**
13554     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13555     */
13556    private boolean hasRtlSupport() {
13557        return mContext.getApplicationInfo().hasRtlSupport();
13558    }
13559
13560    /**
13561     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13562     * RTL not supported)
13563     */
13564    private boolean isRtlCompatibilityMode() {
13565        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13566        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13567    }
13568
13569    /**
13570     * @return true if RTL properties need resolution.
13571     *
13572     */
13573    private boolean needRtlPropertiesResolution() {
13574        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13575    }
13576
13577    /**
13578     * Called when any RTL property (layout direction or text direction or text alignment) has
13579     * been changed.
13580     *
13581     * Subclasses need to override this method to take care of cached information that depends on the
13582     * resolved layout direction, or to inform child views that inherit their layout direction.
13583     *
13584     * The default implementation does nothing.
13585     *
13586     * @param layoutDirection the direction of the layout
13587     *
13588     * @see #LAYOUT_DIRECTION_LTR
13589     * @see #LAYOUT_DIRECTION_RTL
13590     */
13591    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13592    }
13593
13594    /**
13595     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13596     * that the parent directionality can and will be resolved before its children.
13597     *
13598     * @return true if resolution has been done, false otherwise.
13599     *
13600     * @hide
13601     */
13602    public boolean resolveLayoutDirection() {
13603        // Clear any previous layout direction resolution
13604        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13605
13606        if (hasRtlSupport()) {
13607            // Set resolved depending on layout direction
13608            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13609                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13610                case LAYOUT_DIRECTION_INHERIT:
13611                    // We cannot resolve yet. LTR is by default and let the resolution happen again
13612                    // later to get the correct resolved value
13613                    if (!canResolveLayoutDirection()) return false;
13614
13615                    // Parent has not yet resolved, LTR is still the default
13616                    try {
13617                        if (!mParent.isLayoutDirectionResolved()) return false;
13618
13619                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13620                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13621                        }
13622                    } catch (AbstractMethodError e) {
13623                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13624                                " does not fully implement ViewParent", e);
13625                    }
13626                    break;
13627                case LAYOUT_DIRECTION_RTL:
13628                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13629                    break;
13630                case LAYOUT_DIRECTION_LOCALE:
13631                    if((LAYOUT_DIRECTION_RTL ==
13632                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13633                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13634                    }
13635                    break;
13636                default:
13637                    // Nothing to do, LTR by default
13638            }
13639        }
13640
13641        // Set to resolved
13642        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13643        return true;
13644    }
13645
13646    /**
13647     * Check if layout direction resolution can be done.
13648     *
13649     * @return true if layout direction resolution can be done otherwise return false.
13650     */
13651    public boolean canResolveLayoutDirection() {
13652        switch (getRawLayoutDirection()) {
13653            case LAYOUT_DIRECTION_INHERIT:
13654                if (mParent != null) {
13655                    try {
13656                        return mParent.canResolveLayoutDirection();
13657                    } catch (AbstractMethodError e) {
13658                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13659                                " does not fully implement ViewParent", e);
13660                    }
13661                }
13662                return false;
13663
13664            default:
13665                return true;
13666        }
13667    }
13668
13669    /**
13670     * Reset the resolved layout direction. Layout direction will be resolved during a call to
13671     * {@link #onMeasure(int, int)}.
13672     *
13673     * @hide
13674     */
13675    public void resetResolvedLayoutDirection() {
13676        // Reset the current resolved bits
13677        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13678    }
13679
13680    /**
13681     * @return true if the layout direction is inherited.
13682     *
13683     * @hide
13684     */
13685    public boolean isLayoutDirectionInherited() {
13686        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13687    }
13688
13689    /**
13690     * @return true if layout direction has been resolved.
13691     */
13692    public boolean isLayoutDirectionResolved() {
13693        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13694    }
13695
13696    /**
13697     * Return if padding has been resolved
13698     *
13699     * @hide
13700     */
13701    boolean isPaddingResolved() {
13702        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13703    }
13704
13705    /**
13706     * Resolves padding depending on layout direction, if applicable, and
13707     * recomputes internal padding values to adjust for scroll bars.
13708     *
13709     * @hide
13710     */
13711    public void resolvePadding() {
13712        final int resolvedLayoutDirection = getLayoutDirection();
13713
13714        if (!isRtlCompatibilityMode()) {
13715            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13716            // If start / end padding are defined, they will be resolved (hence overriding) to
13717            // left / right or right / left depending on the resolved layout direction.
13718            // If start / end padding are not defined, use the left / right ones.
13719            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13720                Rect padding = sThreadLocal.get();
13721                if (padding == null) {
13722                    padding = new Rect();
13723                    sThreadLocal.set(padding);
13724                }
13725                mBackground.getPadding(padding);
13726                if (!mLeftPaddingDefined) {
13727                    mUserPaddingLeftInitial = padding.left;
13728                }
13729                if (!mRightPaddingDefined) {
13730                    mUserPaddingRightInitial = padding.right;
13731                }
13732            }
13733            switch (resolvedLayoutDirection) {
13734                case LAYOUT_DIRECTION_RTL:
13735                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13736                        mUserPaddingRight = mUserPaddingStart;
13737                    } else {
13738                        mUserPaddingRight = mUserPaddingRightInitial;
13739                    }
13740                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13741                        mUserPaddingLeft = mUserPaddingEnd;
13742                    } else {
13743                        mUserPaddingLeft = mUserPaddingLeftInitial;
13744                    }
13745                    break;
13746                case LAYOUT_DIRECTION_LTR:
13747                default:
13748                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13749                        mUserPaddingLeft = mUserPaddingStart;
13750                    } else {
13751                        mUserPaddingLeft = mUserPaddingLeftInitial;
13752                    }
13753                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13754                        mUserPaddingRight = mUserPaddingEnd;
13755                    } else {
13756                        mUserPaddingRight = mUserPaddingRightInitial;
13757                    }
13758            }
13759
13760            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13761        }
13762
13763        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13764        onRtlPropertiesChanged(resolvedLayoutDirection);
13765
13766        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13767    }
13768
13769    /**
13770     * Reset the resolved layout direction.
13771     *
13772     * @hide
13773     */
13774    public void resetResolvedPadding() {
13775        resetResolvedPaddingInternal();
13776    }
13777
13778    /**
13779     * Used when we only want to reset *this* view's padding and not trigger overrides
13780     * in ViewGroup that reset children too.
13781     */
13782    void resetResolvedPaddingInternal() {
13783        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13784    }
13785
13786    /**
13787     * This is called when the view is detached from a window.  At this point it
13788     * no longer has a surface for drawing.
13789     *
13790     * @see #onAttachedToWindow()
13791     */
13792    @CallSuper
13793    protected void onDetachedFromWindow() {
13794    }
13795
13796    /**
13797     * This is a framework-internal mirror of onDetachedFromWindow() that's called
13798     * after onDetachedFromWindow().
13799     *
13800     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13801     * The super method should be called at the end of the overridden method to ensure
13802     * subclasses are destroyed first
13803     *
13804     * @hide
13805     */
13806    @CallSuper
13807    protected void onDetachedFromWindowInternal() {
13808        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13809        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13810
13811        removeUnsetPressCallback();
13812        removeLongPressCallback();
13813        removePerformClickCallback();
13814        removeSendViewScrolledAccessibilityEventCallback();
13815        stopNestedScroll();
13816
13817        // Anything that started animating right before detach should already
13818        // be in its final state when re-attached.
13819        jumpDrawablesToCurrentState();
13820
13821        destroyDrawingCache();
13822
13823        cleanupDraw();
13824        mCurrentAnimation = null;
13825    }
13826
13827    private void cleanupDraw() {
13828        resetDisplayList();
13829        if (mAttachInfo != null) {
13830            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13831        }
13832    }
13833
13834    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13835    }
13836
13837    /**
13838     * @return The number of times this view has been attached to a window
13839     */
13840    protected int getWindowAttachCount() {
13841        return mWindowAttachCount;
13842    }
13843
13844    /**
13845     * Retrieve a unique token identifying the window this view is attached to.
13846     * @return Return the window's token for use in
13847     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13848     */
13849    public IBinder getWindowToken() {
13850        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13851    }
13852
13853    /**
13854     * Retrieve the {@link WindowId} for the window this view is
13855     * currently attached to.
13856     */
13857    public WindowId getWindowId() {
13858        if (mAttachInfo == null) {
13859            return null;
13860        }
13861        if (mAttachInfo.mWindowId == null) {
13862            try {
13863                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13864                        mAttachInfo.mWindowToken);
13865                mAttachInfo.mWindowId = new WindowId(
13866                        mAttachInfo.mIWindowId);
13867            } catch (RemoteException e) {
13868            }
13869        }
13870        return mAttachInfo.mWindowId;
13871    }
13872
13873    /**
13874     * Retrieve a unique token identifying the top-level "real" window of
13875     * the window that this view is attached to.  That is, this is like
13876     * {@link #getWindowToken}, except if the window this view in is a panel
13877     * window (attached to another containing window), then the token of
13878     * the containing window is returned instead.
13879     *
13880     * @return Returns the associated window token, either
13881     * {@link #getWindowToken()} or the containing window's token.
13882     */
13883    public IBinder getApplicationWindowToken() {
13884        AttachInfo ai = mAttachInfo;
13885        if (ai != null) {
13886            IBinder appWindowToken = ai.mPanelParentWindowToken;
13887            if (appWindowToken == null) {
13888                appWindowToken = ai.mWindowToken;
13889            }
13890            return appWindowToken;
13891        }
13892        return null;
13893    }
13894
13895    /**
13896     * Gets the logical display to which the view's window has been attached.
13897     *
13898     * @return The logical display, or null if the view is not currently attached to a window.
13899     */
13900    public Display getDisplay() {
13901        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13902    }
13903
13904    /**
13905     * Retrieve private session object this view hierarchy is using to
13906     * communicate with the window manager.
13907     * @return the session object to communicate with the window manager
13908     */
13909    /*package*/ IWindowSession getWindowSession() {
13910        return mAttachInfo != null ? mAttachInfo.mSession : null;
13911    }
13912
13913    /**
13914     * @param info the {@link android.view.View.AttachInfo} to associated with
13915     *        this view
13916     */
13917    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13918        //System.out.println("Attached! " + this);
13919        mAttachInfo = info;
13920        if (mOverlay != null) {
13921            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13922        }
13923        mWindowAttachCount++;
13924        // We will need to evaluate the drawable state at least once.
13925        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13926        if (mFloatingTreeObserver != null) {
13927            info.mTreeObserver.merge(mFloatingTreeObserver);
13928            mFloatingTreeObserver = null;
13929        }
13930        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13931            mAttachInfo.mScrollContainers.add(this);
13932            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13933        }
13934        performCollectViewAttributes(mAttachInfo, visibility);
13935        onAttachedToWindow();
13936
13937        ListenerInfo li = mListenerInfo;
13938        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13939                li != null ? li.mOnAttachStateChangeListeners : null;
13940        if (listeners != null && listeners.size() > 0) {
13941            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13942            // perform the dispatching. The iterator is a safe guard against listeners that
13943            // could mutate the list by calling the various add/remove methods. This prevents
13944            // the array from being modified while we iterate it.
13945            for (OnAttachStateChangeListener listener : listeners) {
13946                listener.onViewAttachedToWindow(this);
13947            }
13948        }
13949
13950        int vis = info.mWindowVisibility;
13951        if (vis != GONE) {
13952            onWindowVisibilityChanged(vis);
13953        }
13954        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13955            // If nobody has evaluated the drawable state yet, then do it now.
13956            refreshDrawableState();
13957        }
13958        needGlobalAttributesUpdate(false);
13959    }
13960
13961    void dispatchDetachedFromWindow() {
13962        AttachInfo info = mAttachInfo;
13963        if (info != null) {
13964            int vis = info.mWindowVisibility;
13965            if (vis != GONE) {
13966                onWindowVisibilityChanged(GONE);
13967            }
13968        }
13969
13970        onDetachedFromWindow();
13971        onDetachedFromWindowInternal();
13972
13973        ListenerInfo li = mListenerInfo;
13974        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13975                li != null ? li.mOnAttachStateChangeListeners : null;
13976        if (listeners != null && listeners.size() > 0) {
13977            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13978            // perform the dispatching. The iterator is a safe guard against listeners that
13979            // could mutate the list by calling the various add/remove methods. This prevents
13980            // the array from being modified while we iterate it.
13981            for (OnAttachStateChangeListener listener : listeners) {
13982                listener.onViewDetachedFromWindow(this);
13983            }
13984        }
13985
13986        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13987            mAttachInfo.mScrollContainers.remove(this);
13988            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13989        }
13990
13991        mAttachInfo = null;
13992        if (mOverlay != null) {
13993            mOverlay.getOverlayView().dispatchDetachedFromWindow();
13994        }
13995    }
13996
13997    /**
13998     * Cancel any deferred high-level input events that were previously posted to the event queue.
13999     *
14000     * <p>Many views post high-level events such as click handlers to the event queue
14001     * to run deferred in order to preserve a desired user experience - clearing visible
14002     * pressed states before executing, etc. This method will abort any events of this nature
14003     * that are currently in flight.</p>
14004     *
14005     * <p>Custom views that generate their own high-level deferred input events should override
14006     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14007     *
14008     * <p>This will also cancel pending input events for any child views.</p>
14009     *
14010     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14011     * This will not impact newer events posted after this call that may occur as a result of
14012     * lower-level input events still waiting in the queue. If you are trying to prevent
14013     * double-submitted  events for the duration of some sort of asynchronous transaction
14014     * you should also take other steps to protect against unexpected double inputs e.g. calling
14015     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14016     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14017     */
14018    public final void cancelPendingInputEvents() {
14019        dispatchCancelPendingInputEvents();
14020    }
14021
14022    /**
14023     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14024     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14025     */
14026    void dispatchCancelPendingInputEvents() {
14027        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14028        onCancelPendingInputEvents();
14029        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14030            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14031                    " did not call through to super.onCancelPendingInputEvents()");
14032        }
14033    }
14034
14035    /**
14036     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14037     * a parent view.
14038     *
14039     * <p>This method is responsible for removing any pending high-level input events that were
14040     * posted to the event queue to run later. Custom view classes that post their own deferred
14041     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14042     * {@link android.os.Handler} should override this method, call
14043     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14044     * </p>
14045     */
14046    public void onCancelPendingInputEvents() {
14047        removePerformClickCallback();
14048        cancelLongPress();
14049        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14050    }
14051
14052    /**
14053     * Store this view hierarchy's frozen state into the given container.
14054     *
14055     * @param container The SparseArray in which to save the view's state.
14056     *
14057     * @see #restoreHierarchyState(android.util.SparseArray)
14058     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14059     * @see #onSaveInstanceState()
14060     */
14061    public void saveHierarchyState(SparseArray<Parcelable> container) {
14062        dispatchSaveInstanceState(container);
14063    }
14064
14065    /**
14066     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14067     * this view and its children. May be overridden to modify how freezing happens to a
14068     * view's children; for example, some views may want to not store state for their children.
14069     *
14070     * @param container The SparseArray in which to save the view's state.
14071     *
14072     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14073     * @see #saveHierarchyState(android.util.SparseArray)
14074     * @see #onSaveInstanceState()
14075     */
14076    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14077        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14078            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14079            Parcelable state = onSaveInstanceState();
14080            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14081                throw new IllegalStateException(
14082                        "Derived class did not call super.onSaveInstanceState()");
14083            }
14084            if (state != null) {
14085                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14086                // + ": " + state);
14087                container.put(mID, state);
14088            }
14089        }
14090    }
14091
14092    /**
14093     * Hook allowing a view to generate a representation of its internal state
14094     * that can later be used to create a new instance with that same state.
14095     * This state should only contain information that is not persistent or can
14096     * not be reconstructed later. For example, you will never store your
14097     * current position on screen because that will be computed again when a
14098     * new instance of the view is placed in its view hierarchy.
14099     * <p>
14100     * Some examples of things you may store here: the current cursor position
14101     * in a text view (but usually not the text itself since that is stored in a
14102     * content provider or other persistent storage), the currently selected
14103     * item in a list view.
14104     *
14105     * @return Returns a Parcelable object containing the view's current dynamic
14106     *         state, or null if there is nothing interesting to save. The
14107     *         default implementation returns null.
14108     * @see #onRestoreInstanceState(android.os.Parcelable)
14109     * @see #saveHierarchyState(android.util.SparseArray)
14110     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14111     * @see #setSaveEnabled(boolean)
14112     */
14113    @CallSuper
14114    protected Parcelable onSaveInstanceState() {
14115        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14116        if (mStartActivityRequestWho != null) {
14117            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14118            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14119            return state;
14120        }
14121        return BaseSavedState.EMPTY_STATE;
14122    }
14123
14124    /**
14125     * Restore this view hierarchy's frozen state from the given container.
14126     *
14127     * @param container The SparseArray which holds previously frozen states.
14128     *
14129     * @see #saveHierarchyState(android.util.SparseArray)
14130     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14131     * @see #onRestoreInstanceState(android.os.Parcelable)
14132     */
14133    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14134        dispatchRestoreInstanceState(container);
14135    }
14136
14137    /**
14138     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14139     * state for this view and its children. May be overridden to modify how restoring
14140     * happens to a view's children; for example, some views may want to not store state
14141     * for their children.
14142     *
14143     * @param container The SparseArray which holds previously saved state.
14144     *
14145     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14146     * @see #restoreHierarchyState(android.util.SparseArray)
14147     * @see #onRestoreInstanceState(android.os.Parcelable)
14148     */
14149    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14150        if (mID != NO_ID) {
14151            Parcelable state = container.get(mID);
14152            if (state != null) {
14153                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14154                // + ": " + state);
14155                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14156                onRestoreInstanceState(state);
14157                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14158                    throw new IllegalStateException(
14159                            "Derived class did not call super.onRestoreInstanceState()");
14160                }
14161            }
14162        }
14163    }
14164
14165    /**
14166     * Hook allowing a view to re-apply a representation of its internal state that had previously
14167     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14168     * null state.
14169     *
14170     * @param state The frozen state that had previously been returned by
14171     *        {@link #onSaveInstanceState}.
14172     *
14173     * @see #onSaveInstanceState()
14174     * @see #restoreHierarchyState(android.util.SparseArray)
14175     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14176     */
14177    @CallSuper
14178    protected void onRestoreInstanceState(Parcelable state) {
14179        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14180        if (state != null && !(state instanceof AbsSavedState)) {
14181            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14182                    + "received " + state.getClass().toString() + " instead. This usually happens "
14183                    + "when two views of different type have the same id in the same hierarchy. "
14184                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14185                    + "other views do not use the same id.");
14186        }
14187        if (state != null && state instanceof BaseSavedState) {
14188            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14189        }
14190    }
14191
14192    /**
14193     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14194     *
14195     * @return the drawing start time in milliseconds
14196     */
14197    public long getDrawingTime() {
14198        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14199    }
14200
14201    /**
14202     * <p>Enables or disables the duplication of the parent's state into this view. When
14203     * duplication is enabled, this view gets its drawable state from its parent rather
14204     * than from its own internal properties.</p>
14205     *
14206     * <p>Note: in the current implementation, setting this property to true after the
14207     * view was added to a ViewGroup might have no effect at all. This property should
14208     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14209     *
14210     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14211     * property is enabled, an exception will be thrown.</p>
14212     *
14213     * <p>Note: if the child view uses and updates additional states which are unknown to the
14214     * parent, these states should not be affected by this method.</p>
14215     *
14216     * @param enabled True to enable duplication of the parent's drawable state, false
14217     *                to disable it.
14218     *
14219     * @see #getDrawableState()
14220     * @see #isDuplicateParentStateEnabled()
14221     */
14222    public void setDuplicateParentStateEnabled(boolean enabled) {
14223        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14224    }
14225
14226    /**
14227     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14228     *
14229     * @return True if this view's drawable state is duplicated from the parent,
14230     *         false otherwise
14231     *
14232     * @see #getDrawableState()
14233     * @see #setDuplicateParentStateEnabled(boolean)
14234     */
14235    public boolean isDuplicateParentStateEnabled() {
14236        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14237    }
14238
14239    /**
14240     * <p>Specifies the type of layer backing this view. The layer can be
14241     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14242     * {@link #LAYER_TYPE_HARDWARE}.</p>
14243     *
14244     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14245     * instance that controls how the layer is composed on screen. The following
14246     * properties of the paint are taken into account when composing the layer:</p>
14247     * <ul>
14248     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14249     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14250     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14251     * </ul>
14252     *
14253     * <p>If this view has an alpha value set to < 1.0 by calling
14254     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14255     * by this view's alpha value.</p>
14256     *
14257     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14258     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14259     * for more information on when and how to use layers.</p>
14260     *
14261     * @param layerType The type of layer to use with this view, must be one of
14262     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14263     *        {@link #LAYER_TYPE_HARDWARE}
14264     * @param paint The paint used to compose the layer. This argument is optional
14265     *        and can be null. It is ignored when the layer type is
14266     *        {@link #LAYER_TYPE_NONE}
14267     *
14268     * @see #getLayerType()
14269     * @see #LAYER_TYPE_NONE
14270     * @see #LAYER_TYPE_SOFTWARE
14271     * @see #LAYER_TYPE_HARDWARE
14272     * @see #setAlpha(float)
14273     *
14274     * @attr ref android.R.styleable#View_layerType
14275     */
14276    public void setLayerType(int layerType, Paint paint) {
14277        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14278            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14279                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14280        }
14281
14282        boolean typeChanged = mRenderNode.setLayerType(layerType);
14283
14284        if (!typeChanged) {
14285            setLayerPaint(paint);
14286            return;
14287        }
14288
14289        // Destroy any previous software drawing cache if needed
14290        if (mLayerType == LAYER_TYPE_SOFTWARE) {
14291            destroyDrawingCache();
14292        }
14293
14294        mLayerType = layerType;
14295        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14296        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14297        mRenderNode.setLayerPaint(mLayerPaint);
14298
14299        // draw() behaves differently if we are on a layer, so we need to
14300        // invalidate() here
14301        invalidateParentCaches();
14302        invalidate(true);
14303    }
14304
14305    /**
14306     * Updates the {@link Paint} object used with the current layer (used only if the current
14307     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14308     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14309     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14310     * ensure that the view gets redrawn immediately.
14311     *
14312     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14313     * instance that controls how the layer is composed on screen. The following
14314     * properties of the paint are taken into account when composing the layer:</p>
14315     * <ul>
14316     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14317     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14318     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14319     * </ul>
14320     *
14321     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14322     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14323     *
14324     * @param paint The paint used to compose the layer. This argument is optional
14325     *        and can be null. It is ignored when the layer type is
14326     *        {@link #LAYER_TYPE_NONE}
14327     *
14328     * @see #setLayerType(int, android.graphics.Paint)
14329     */
14330    public void setLayerPaint(Paint paint) {
14331        int layerType = getLayerType();
14332        if (layerType != LAYER_TYPE_NONE) {
14333            mLayerPaint = paint == null ? new Paint() : paint;
14334            if (layerType == LAYER_TYPE_HARDWARE) {
14335                if (mRenderNode.setLayerPaint(mLayerPaint)) {
14336                    invalidateViewProperty(false, false);
14337                }
14338            } else {
14339                invalidate();
14340            }
14341        }
14342    }
14343
14344    /**
14345     * Indicates whether this view has a static layer. A view with layer type
14346     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
14347     * dynamic.
14348     */
14349    boolean hasStaticLayer() {
14350        return true;
14351    }
14352
14353    /**
14354     * Indicates what type of layer is currently associated with this view. By default
14355     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14356     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14357     * for more information on the different types of layers.
14358     *
14359     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14360     *         {@link #LAYER_TYPE_HARDWARE}
14361     *
14362     * @see #setLayerType(int, android.graphics.Paint)
14363     * @see #buildLayer()
14364     * @see #LAYER_TYPE_NONE
14365     * @see #LAYER_TYPE_SOFTWARE
14366     * @see #LAYER_TYPE_HARDWARE
14367     */
14368    public int getLayerType() {
14369        return mLayerType;
14370    }
14371
14372    /**
14373     * Forces this view's layer to be created and this view to be rendered
14374     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14375     * invoking this method will have no effect.
14376     *
14377     * This method can for instance be used to render a view into its layer before
14378     * starting an animation. If this view is complex, rendering into the layer
14379     * before starting the animation will avoid skipping frames.
14380     *
14381     * @throws IllegalStateException If this view is not attached to a window
14382     *
14383     * @see #setLayerType(int, android.graphics.Paint)
14384     */
14385    public void buildLayer() {
14386        if (mLayerType == LAYER_TYPE_NONE) return;
14387
14388        final AttachInfo attachInfo = mAttachInfo;
14389        if (attachInfo == null) {
14390            throw new IllegalStateException("This view must be attached to a window first");
14391        }
14392
14393        if (getWidth() == 0 || getHeight() == 0) {
14394            return;
14395        }
14396
14397        switch (mLayerType) {
14398            case LAYER_TYPE_HARDWARE:
14399                updateDisplayListIfDirty();
14400                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14401                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14402                }
14403                break;
14404            case LAYER_TYPE_SOFTWARE:
14405                buildDrawingCache(true);
14406                break;
14407        }
14408    }
14409
14410    /**
14411     * If this View draws with a HardwareLayer, returns it.
14412     * Otherwise returns null
14413     *
14414     * TODO: Only TextureView uses this, can we eliminate it?
14415     */
14416    HardwareLayer getHardwareLayer() {
14417        return null;
14418    }
14419
14420    /**
14421     * Destroys all hardware rendering resources. This method is invoked
14422     * when the system needs to reclaim resources. Upon execution of this
14423     * method, you should free any OpenGL resources created by the view.
14424     *
14425     * Note: you <strong>must</strong> call
14426     * <code>super.destroyHardwareResources()</code> when overriding
14427     * this method.
14428     *
14429     * @hide
14430     */
14431    @CallSuper
14432    protected void destroyHardwareResources() {
14433        // Although the Layer will be destroyed by RenderNode, we want to release
14434        // the staging display list, which is also a signal to RenderNode that it's
14435        // safe to free its copy of the display list as it knows that we will
14436        // push an updated DisplayList if we try to draw again
14437        resetDisplayList();
14438    }
14439
14440    /**
14441     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14442     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14443     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14444     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14445     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14446     * null.</p>
14447     *
14448     * <p>Enabling the drawing cache is similar to
14449     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14450     * acceleration is turned off. When hardware acceleration is turned on, enabling the
14451     * drawing cache has no effect on rendering because the system uses a different mechanism
14452     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14453     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14454     * for information on how to enable software and hardware layers.</p>
14455     *
14456     * <p>This API can be used to manually generate
14457     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14458     * {@link #getDrawingCache()}.</p>
14459     *
14460     * @param enabled true to enable the drawing cache, false otherwise
14461     *
14462     * @see #isDrawingCacheEnabled()
14463     * @see #getDrawingCache()
14464     * @see #buildDrawingCache()
14465     * @see #setLayerType(int, android.graphics.Paint)
14466     */
14467    public void setDrawingCacheEnabled(boolean enabled) {
14468        mCachingFailed = false;
14469        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14470    }
14471
14472    /**
14473     * <p>Indicates whether the drawing cache is enabled for this view.</p>
14474     *
14475     * @return true if the drawing cache is enabled
14476     *
14477     * @see #setDrawingCacheEnabled(boolean)
14478     * @see #getDrawingCache()
14479     */
14480    @ViewDebug.ExportedProperty(category = "drawing")
14481    public boolean isDrawingCacheEnabled() {
14482        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
14483    }
14484
14485    /**
14486     * Debugging utility which recursively outputs the dirty state of a view and its
14487     * descendants.
14488     *
14489     * @hide
14490     */
14491    @SuppressWarnings({"UnusedDeclaration"})
14492    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
14493        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
14494                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
14495                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
14496                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
14497        if (clear) {
14498            mPrivateFlags &= clearMask;
14499        }
14500        if (this instanceof ViewGroup) {
14501            ViewGroup parent = (ViewGroup) this;
14502            final int count = parent.getChildCount();
14503            for (int i = 0; i < count; i++) {
14504                final View child = parent.getChildAt(i);
14505                child.outputDirtyFlags(indent + "  ", clear, clearMask);
14506            }
14507        }
14508    }
14509
14510    /**
14511     * This method is used by ViewGroup to cause its children to restore or recreate their
14512     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
14513     * to recreate its own display list, which would happen if it went through the normal
14514     * draw/dispatchDraw mechanisms.
14515     *
14516     * @hide
14517     */
14518    protected void dispatchGetDisplayList() {}
14519
14520    /**
14521     * A view that is not attached or hardware accelerated cannot create a display list.
14522     * This method checks these conditions and returns the appropriate result.
14523     *
14524     * @return true if view has the ability to create a display list, false otherwise.
14525     *
14526     * @hide
14527     */
14528    public boolean canHaveDisplayList() {
14529        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
14530    }
14531
14532    private void updateDisplayListIfDirty() {
14533        final RenderNode renderNode = mRenderNode;
14534        if (!canHaveDisplayList()) {
14535            // can't populate RenderNode, don't try
14536            return;
14537        }
14538
14539        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14540                || !renderNode.isValid()
14541                || (mRecreateDisplayList)) {
14542            // Don't need to recreate the display list, just need to tell our
14543            // children to restore/recreate theirs
14544            if (renderNode.isValid()
14545                    && !mRecreateDisplayList) {
14546                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14547                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14548                dispatchGetDisplayList();
14549
14550                return; // no work needed
14551            }
14552
14553            // If we got here, we're recreating it. Mark it as such to ensure that
14554            // we copy in child display lists into ours in drawChild()
14555            mRecreateDisplayList = true;
14556
14557            int width = mRight - mLeft;
14558            int height = mBottom - mTop;
14559            int layerType = getLayerType();
14560
14561            final DisplayListCanvas canvas = renderNode.start(width, height);
14562            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14563
14564            try {
14565                final HardwareLayer layer = getHardwareLayer();
14566                if (layer != null && layer.isValid()) {
14567                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14568                } else if (layerType == LAYER_TYPE_SOFTWARE) {
14569                    buildDrawingCache(true);
14570                    Bitmap cache = getDrawingCache(true);
14571                    if (cache != null) {
14572                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14573                    }
14574                } else {
14575                    computeScroll();
14576
14577                    canvas.translate(-mScrollX, -mScrollY);
14578                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14579                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14580
14581                    // Fast path for layouts with no backgrounds
14582                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14583                        dispatchDraw(canvas);
14584                        if (mOverlay != null && !mOverlay.isEmpty()) {
14585                            mOverlay.getOverlayView().draw(canvas);
14586                        }
14587                    } else {
14588                        draw(canvas);
14589                    }
14590                }
14591            } finally {
14592                renderNode.end(canvas);
14593                setDisplayListProperties(renderNode);
14594            }
14595        } else {
14596            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14597            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14598        }
14599    }
14600
14601    /**
14602     * Returns a RenderNode with View draw content recorded, which can be
14603     * used to draw this view again without executing its draw method.
14604     *
14605     * @return A RenderNode ready to replay, or null if caching is not enabled.
14606     *
14607     * @hide
14608     */
14609    public RenderNode getDisplayList() {
14610        updateDisplayListIfDirty();
14611        return mRenderNode;
14612    }
14613
14614    private void resetDisplayList() {
14615        if (mRenderNode.isValid()) {
14616            mRenderNode.destroyDisplayListData();
14617        }
14618
14619        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14620            mBackgroundRenderNode.destroyDisplayListData();
14621        }
14622    }
14623
14624    /**
14625     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14626     *
14627     * @return A non-scaled bitmap representing this view or null if cache is disabled.
14628     *
14629     * @see #getDrawingCache(boolean)
14630     */
14631    public Bitmap getDrawingCache() {
14632        return getDrawingCache(false);
14633    }
14634
14635    /**
14636     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14637     * is null when caching is disabled. If caching is enabled and the cache is not ready,
14638     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14639     * draw from the cache when the cache is enabled. To benefit from the cache, you must
14640     * request the drawing cache by calling this method and draw it on screen if the
14641     * returned bitmap is not null.</p>
14642     *
14643     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14644     * this method will create a bitmap of the same size as this view. Because this bitmap
14645     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14646     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14647     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14648     * size than the view. This implies that your application must be able to handle this
14649     * size.</p>
14650     *
14651     * @param autoScale Indicates whether the generated bitmap should be scaled based on
14652     *        the current density of the screen when the application is in compatibility
14653     *        mode.
14654     *
14655     * @return A bitmap representing this view or null if cache is disabled.
14656     *
14657     * @see #setDrawingCacheEnabled(boolean)
14658     * @see #isDrawingCacheEnabled()
14659     * @see #buildDrawingCache(boolean)
14660     * @see #destroyDrawingCache()
14661     */
14662    public Bitmap getDrawingCache(boolean autoScale) {
14663        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14664            return null;
14665        }
14666        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14667            buildDrawingCache(autoScale);
14668        }
14669        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14670    }
14671
14672    /**
14673     * <p>Frees the resources used by the drawing cache. If you call
14674     * {@link #buildDrawingCache()} manually without calling
14675     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14676     * should cleanup the cache with this method afterwards.</p>
14677     *
14678     * @see #setDrawingCacheEnabled(boolean)
14679     * @see #buildDrawingCache()
14680     * @see #getDrawingCache()
14681     */
14682    public void destroyDrawingCache() {
14683        if (mDrawingCache != null) {
14684            mDrawingCache.recycle();
14685            mDrawingCache = null;
14686        }
14687        if (mUnscaledDrawingCache != null) {
14688            mUnscaledDrawingCache.recycle();
14689            mUnscaledDrawingCache = null;
14690        }
14691    }
14692
14693    /**
14694     * Setting a solid background color for the drawing cache's bitmaps will improve
14695     * performance and memory usage. Note, though that this should only be used if this
14696     * view will always be drawn on top of a solid color.
14697     *
14698     * @param color The background color to use for the drawing cache's bitmap
14699     *
14700     * @see #setDrawingCacheEnabled(boolean)
14701     * @see #buildDrawingCache()
14702     * @see #getDrawingCache()
14703     */
14704    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
14705        if (color != mDrawingCacheBackgroundColor) {
14706            mDrawingCacheBackgroundColor = color;
14707            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14708        }
14709    }
14710
14711    /**
14712     * @see #setDrawingCacheBackgroundColor(int)
14713     *
14714     * @return The background color to used for the drawing cache's bitmap
14715     */
14716    @ColorInt
14717    public int getDrawingCacheBackgroundColor() {
14718        return mDrawingCacheBackgroundColor;
14719    }
14720
14721    /**
14722     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14723     *
14724     * @see #buildDrawingCache(boolean)
14725     */
14726    public void buildDrawingCache() {
14727        buildDrawingCache(false);
14728    }
14729
14730    /**
14731     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14732     *
14733     * <p>If you call {@link #buildDrawingCache()} manually without calling
14734     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14735     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14736     *
14737     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14738     * this method will create a bitmap of the same size as this view. Because this bitmap
14739     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14740     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14741     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14742     * size than the view. This implies that your application must be able to handle this
14743     * size.</p>
14744     *
14745     * <p>You should avoid calling this method when hardware acceleration is enabled. If
14746     * you do not need the drawing cache bitmap, calling this method will increase memory
14747     * usage and cause the view to be rendered in software once, thus negatively impacting
14748     * performance.</p>
14749     *
14750     * @see #getDrawingCache()
14751     * @see #destroyDrawingCache()
14752     */
14753    public void buildDrawingCache(boolean autoScale) {
14754        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14755                mDrawingCache == null : mUnscaledDrawingCache == null)) {
14756            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
14757                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
14758                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
14759            }
14760            try {
14761                buildDrawingCacheImpl(autoScale);
14762            } finally {
14763                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
14764            }
14765        }
14766    }
14767
14768    /**
14769     * private, internal implementation of buildDrawingCache, used to enable tracing
14770     */
14771    private void buildDrawingCacheImpl(boolean autoScale) {
14772        mCachingFailed = false;
14773
14774        int width = mRight - mLeft;
14775        int height = mBottom - mTop;
14776
14777        final AttachInfo attachInfo = mAttachInfo;
14778        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14779
14780        if (autoScale && scalingRequired) {
14781            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14782            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14783        }
14784
14785        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14786        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14787        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14788
14789        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14790        final long drawingCacheSize =
14791                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14792        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14793            if (width > 0 && height > 0) {
14794                Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14795                        + projectedBitmapSize + " bytes, only "
14796                        + drawingCacheSize + " available");
14797            }
14798            destroyDrawingCache();
14799            mCachingFailed = true;
14800            return;
14801        }
14802
14803        boolean clear = true;
14804        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14805
14806        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14807            Bitmap.Config quality;
14808            if (!opaque) {
14809                // Never pick ARGB_4444 because it looks awful
14810                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14811                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14812                    case DRAWING_CACHE_QUALITY_AUTO:
14813                    case DRAWING_CACHE_QUALITY_LOW:
14814                    case DRAWING_CACHE_QUALITY_HIGH:
14815                    default:
14816                        quality = Bitmap.Config.ARGB_8888;
14817                        break;
14818                }
14819            } else {
14820                // Optimization for translucent windows
14821                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14822                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14823            }
14824
14825            // Try to cleanup memory
14826            if (bitmap != null) bitmap.recycle();
14827
14828            try {
14829                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14830                        width, height, quality);
14831                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14832                if (autoScale) {
14833                    mDrawingCache = bitmap;
14834                } else {
14835                    mUnscaledDrawingCache = bitmap;
14836                }
14837                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14838            } catch (OutOfMemoryError e) {
14839                // If there is not enough memory to create the bitmap cache, just
14840                // ignore the issue as bitmap caches are not required to draw the
14841                // view hierarchy
14842                if (autoScale) {
14843                    mDrawingCache = null;
14844                } else {
14845                    mUnscaledDrawingCache = null;
14846                }
14847                mCachingFailed = true;
14848                return;
14849            }
14850
14851            clear = drawingCacheBackgroundColor != 0;
14852        }
14853
14854        Canvas canvas;
14855        if (attachInfo != null) {
14856            canvas = attachInfo.mCanvas;
14857            if (canvas == null) {
14858                canvas = new Canvas();
14859            }
14860            canvas.setBitmap(bitmap);
14861            // Temporarily clobber the cached Canvas in case one of our children
14862            // is also using a drawing cache. Without this, the children would
14863            // steal the canvas by attaching their own bitmap to it and bad, bad
14864            // thing would happen (invisible views, corrupted drawings, etc.)
14865            attachInfo.mCanvas = null;
14866        } else {
14867            // This case should hopefully never or seldom happen
14868            canvas = new Canvas(bitmap);
14869        }
14870
14871        if (clear) {
14872            bitmap.eraseColor(drawingCacheBackgroundColor);
14873        }
14874
14875        computeScroll();
14876        final int restoreCount = canvas.save();
14877
14878        if (autoScale && scalingRequired) {
14879            final float scale = attachInfo.mApplicationScale;
14880            canvas.scale(scale, scale);
14881        }
14882
14883        canvas.translate(-mScrollX, -mScrollY);
14884
14885        mPrivateFlags |= PFLAG_DRAWN;
14886        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14887                mLayerType != LAYER_TYPE_NONE) {
14888            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14889        }
14890
14891        // Fast path for layouts with no backgrounds
14892        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14893            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14894            dispatchDraw(canvas);
14895            if (mOverlay != null && !mOverlay.isEmpty()) {
14896                mOverlay.getOverlayView().draw(canvas);
14897            }
14898        } else {
14899            draw(canvas);
14900        }
14901
14902        canvas.restoreToCount(restoreCount);
14903        canvas.setBitmap(null);
14904
14905        if (attachInfo != null) {
14906            // Restore the cached Canvas for our siblings
14907            attachInfo.mCanvas = canvas;
14908        }
14909    }
14910
14911    /**
14912     * Create a snapshot of the view into a bitmap.  We should probably make
14913     * some form of this public, but should think about the API.
14914     */
14915    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14916        int width = mRight - mLeft;
14917        int height = mBottom - mTop;
14918
14919        final AttachInfo attachInfo = mAttachInfo;
14920        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14921        width = (int) ((width * scale) + 0.5f);
14922        height = (int) ((height * scale) + 0.5f);
14923
14924        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14925                width > 0 ? width : 1, height > 0 ? height : 1, quality);
14926        if (bitmap == null) {
14927            throw new OutOfMemoryError();
14928        }
14929
14930        Resources resources = getResources();
14931        if (resources != null) {
14932            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14933        }
14934
14935        Canvas canvas;
14936        if (attachInfo != null) {
14937            canvas = attachInfo.mCanvas;
14938            if (canvas == null) {
14939                canvas = new Canvas();
14940            }
14941            canvas.setBitmap(bitmap);
14942            // Temporarily clobber the cached Canvas in case one of our children
14943            // is also using a drawing cache. Without this, the children would
14944            // steal the canvas by attaching their own bitmap to it and bad, bad
14945            // things would happen (invisible views, corrupted drawings, etc.)
14946            attachInfo.mCanvas = null;
14947        } else {
14948            // This case should hopefully never or seldom happen
14949            canvas = new Canvas(bitmap);
14950        }
14951
14952        if ((backgroundColor & 0xff000000) != 0) {
14953            bitmap.eraseColor(backgroundColor);
14954        }
14955
14956        computeScroll();
14957        final int restoreCount = canvas.save();
14958        canvas.scale(scale, scale);
14959        canvas.translate(-mScrollX, -mScrollY);
14960
14961        // Temporarily remove the dirty mask
14962        int flags = mPrivateFlags;
14963        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14964
14965        // Fast path for layouts with no backgrounds
14966        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14967            dispatchDraw(canvas);
14968            if (mOverlay != null && !mOverlay.isEmpty()) {
14969                mOverlay.getOverlayView().draw(canvas);
14970            }
14971        } else {
14972            draw(canvas);
14973        }
14974
14975        mPrivateFlags = flags;
14976
14977        canvas.restoreToCount(restoreCount);
14978        canvas.setBitmap(null);
14979
14980        if (attachInfo != null) {
14981            // Restore the cached Canvas for our siblings
14982            attachInfo.mCanvas = canvas;
14983        }
14984
14985        return bitmap;
14986    }
14987
14988    /**
14989     * Indicates whether this View is currently in edit mode. A View is usually
14990     * in edit mode when displayed within a developer tool. For instance, if
14991     * this View is being drawn by a visual user interface builder, this method
14992     * should return true.
14993     *
14994     * Subclasses should check the return value of this method to provide
14995     * different behaviors if their normal behavior might interfere with the
14996     * host environment. For instance: the class spawns a thread in its
14997     * constructor, the drawing code relies on device-specific features, etc.
14998     *
14999     * This method is usually checked in the drawing code of custom widgets.
15000     *
15001     * @return True if this View is in edit mode, false otherwise.
15002     */
15003    public boolean isInEditMode() {
15004        return false;
15005    }
15006
15007    /**
15008     * If the View draws content inside its padding and enables fading edges,
15009     * it needs to support padding offsets. Padding offsets are added to the
15010     * fading edges to extend the length of the fade so that it covers pixels
15011     * drawn inside the padding.
15012     *
15013     * Subclasses of this class should override this method if they need
15014     * to draw content inside the padding.
15015     *
15016     * @return True if padding offset must be applied, false otherwise.
15017     *
15018     * @see #getLeftPaddingOffset()
15019     * @see #getRightPaddingOffset()
15020     * @see #getTopPaddingOffset()
15021     * @see #getBottomPaddingOffset()
15022     *
15023     * @since CURRENT
15024     */
15025    protected boolean isPaddingOffsetRequired() {
15026        return false;
15027    }
15028
15029    /**
15030     * Amount by which to extend the left fading region. Called only when
15031     * {@link #isPaddingOffsetRequired()} returns true.
15032     *
15033     * @return The left padding offset in pixels.
15034     *
15035     * @see #isPaddingOffsetRequired()
15036     *
15037     * @since CURRENT
15038     */
15039    protected int getLeftPaddingOffset() {
15040        return 0;
15041    }
15042
15043    /**
15044     * Amount by which to extend the right fading region. Called only when
15045     * {@link #isPaddingOffsetRequired()} returns true.
15046     *
15047     * @return The right padding offset in pixels.
15048     *
15049     * @see #isPaddingOffsetRequired()
15050     *
15051     * @since CURRENT
15052     */
15053    protected int getRightPaddingOffset() {
15054        return 0;
15055    }
15056
15057    /**
15058     * Amount by which to extend the top fading region. Called only when
15059     * {@link #isPaddingOffsetRequired()} returns true.
15060     *
15061     * @return The top padding offset in pixels.
15062     *
15063     * @see #isPaddingOffsetRequired()
15064     *
15065     * @since CURRENT
15066     */
15067    protected int getTopPaddingOffset() {
15068        return 0;
15069    }
15070
15071    /**
15072     * Amount by which to extend the bottom fading region. Called only when
15073     * {@link #isPaddingOffsetRequired()} returns true.
15074     *
15075     * @return The bottom padding offset in pixels.
15076     *
15077     * @see #isPaddingOffsetRequired()
15078     *
15079     * @since CURRENT
15080     */
15081    protected int getBottomPaddingOffset() {
15082        return 0;
15083    }
15084
15085    /**
15086     * @hide
15087     * @param offsetRequired
15088     */
15089    protected int getFadeTop(boolean offsetRequired) {
15090        int top = mPaddingTop;
15091        if (offsetRequired) top += getTopPaddingOffset();
15092        return top;
15093    }
15094
15095    /**
15096     * @hide
15097     * @param offsetRequired
15098     */
15099    protected int getFadeHeight(boolean offsetRequired) {
15100        int padding = mPaddingTop;
15101        if (offsetRequired) padding += getTopPaddingOffset();
15102        return mBottom - mTop - mPaddingBottom - padding;
15103    }
15104
15105    /**
15106     * <p>Indicates whether this view is attached to a hardware accelerated
15107     * window or not.</p>
15108     *
15109     * <p>Even if this method returns true, it does not mean that every call
15110     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15111     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15112     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15113     * window is hardware accelerated,
15114     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15115     * return false, and this method will return true.</p>
15116     *
15117     * @return True if the view is attached to a window and the window is
15118     *         hardware accelerated; false in any other case.
15119     */
15120    @ViewDebug.ExportedProperty(category = "drawing")
15121    public boolean isHardwareAccelerated() {
15122        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15123    }
15124
15125    /**
15126     * Sets a rectangular area on this view to which the view will be clipped
15127     * when it is drawn. Setting the value to null will remove the clip bounds
15128     * and the view will draw normally, using its full bounds.
15129     *
15130     * @param clipBounds The rectangular area, in the local coordinates of
15131     * this view, to which future drawing operations will be clipped.
15132     */
15133    public void setClipBounds(Rect clipBounds) {
15134        if (clipBounds == mClipBounds
15135                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15136            return;
15137        }
15138        if (clipBounds != null) {
15139            if (mClipBounds == null) {
15140                mClipBounds = new Rect(clipBounds);
15141            } else {
15142                mClipBounds.set(clipBounds);
15143            }
15144        } else {
15145            mClipBounds = null;
15146        }
15147        mRenderNode.setClipBounds(mClipBounds);
15148        invalidateViewProperty(false, false);
15149    }
15150
15151    /**
15152     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15153     *
15154     * @return A copy of the current clip bounds if clip bounds are set,
15155     * otherwise null.
15156     */
15157    public Rect getClipBounds() {
15158        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15159    }
15160
15161
15162    /**
15163     * Populates an output rectangle with the clip bounds of the view,
15164     * returning {@code true} if successful or {@code false} if the view's
15165     * clip bounds are {@code null}.
15166     *
15167     * @param outRect rectangle in which to place the clip bounds of the view
15168     * @return {@code true} if successful or {@code false} if the view's
15169     *         clip bounds are {@code null}
15170     */
15171    public boolean getClipBounds(Rect outRect) {
15172        if (mClipBounds != null) {
15173            outRect.set(mClipBounds);
15174            return true;
15175        }
15176        return false;
15177    }
15178
15179    /**
15180     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15181     * case of an active Animation being run on the view.
15182     */
15183    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15184            Animation a, boolean scalingRequired) {
15185        Transformation invalidationTransform;
15186        final int flags = parent.mGroupFlags;
15187        final boolean initialized = a.isInitialized();
15188        if (!initialized) {
15189            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15190            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15191            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15192            onAnimationStart();
15193        }
15194
15195        final Transformation t = parent.getChildTransformation();
15196        boolean more = a.getTransformation(drawingTime, t, 1f);
15197        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15198            if (parent.mInvalidationTransformation == null) {
15199                parent.mInvalidationTransformation = new Transformation();
15200            }
15201            invalidationTransform = parent.mInvalidationTransformation;
15202            a.getTransformation(drawingTime, invalidationTransform, 1f);
15203        } else {
15204            invalidationTransform = t;
15205        }
15206
15207        if (more) {
15208            if (!a.willChangeBounds()) {
15209                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15210                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15211                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15212                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15213                    // The child need to draw an animation, potentially offscreen, so
15214                    // make sure we do not cancel invalidate requests
15215                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15216                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15217                }
15218            } else {
15219                if (parent.mInvalidateRegion == null) {
15220                    parent.mInvalidateRegion = new RectF();
15221                }
15222                final RectF region = parent.mInvalidateRegion;
15223                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15224                        invalidationTransform);
15225
15226                // The child need to draw an animation, potentially offscreen, so
15227                // make sure we do not cancel invalidate requests
15228                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15229
15230                final int left = mLeft + (int) region.left;
15231                final int top = mTop + (int) region.top;
15232                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15233                        top + (int) (region.height() + .5f));
15234            }
15235        }
15236        return more;
15237    }
15238
15239    /**
15240     * This method is called by getDisplayList() when a display list is recorded for a View.
15241     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15242     */
15243    void setDisplayListProperties(RenderNode renderNode) {
15244        if (renderNode != null) {
15245            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15246            renderNode.setClipToBounds(mParent instanceof ViewGroup
15247                    && ((ViewGroup) mParent).getClipChildren());
15248
15249            float alpha = 1;
15250            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15251                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15252                ViewGroup parentVG = (ViewGroup) mParent;
15253                final Transformation t = parentVG.getChildTransformation();
15254                if (parentVG.getChildStaticTransformation(this, t)) {
15255                    final int transformType = t.getTransformationType();
15256                    if (transformType != Transformation.TYPE_IDENTITY) {
15257                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15258                            alpha = t.getAlpha();
15259                        }
15260                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15261                            renderNode.setStaticMatrix(t.getMatrix());
15262                        }
15263                    }
15264                }
15265            }
15266            if (mTransformationInfo != null) {
15267                alpha *= getFinalAlpha();
15268                if (alpha < 1) {
15269                    final int multipliedAlpha = (int) (255 * alpha);
15270                    if (onSetAlpha(multipliedAlpha)) {
15271                        alpha = 1;
15272                    }
15273                }
15274                renderNode.setAlpha(alpha);
15275            } else if (alpha < 1) {
15276                renderNode.setAlpha(alpha);
15277            }
15278        }
15279    }
15280
15281    /**
15282     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15283     *
15284     * This is where the View specializes rendering behavior based on layer type,
15285     * and hardware acceleration.
15286     */
15287    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15288        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15289        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15290         *
15291         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15292         * HW accelerated, it can't handle drawing RenderNodes.
15293         */
15294        boolean drawingWithRenderNode = mAttachInfo != null
15295                && mAttachInfo.mHardwareAccelerated
15296                && hardwareAcceleratedCanvas;
15297
15298        boolean more = false;
15299        final boolean childHasIdentityMatrix = hasIdentityMatrix();
15300        final int parentFlags = parent.mGroupFlags;
15301
15302        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15303            parent.getChildTransformation().clear();
15304            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15305        }
15306
15307        Transformation transformToApply = null;
15308        boolean concatMatrix = false;
15309        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15310        final Animation a = getAnimation();
15311        if (a != null) {
15312            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15313            concatMatrix = a.willChangeTransformationMatrix();
15314            if (concatMatrix) {
15315                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15316            }
15317            transformToApply = parent.getChildTransformation();
15318        } else {
15319            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15320                // No longer animating: clear out old animation matrix
15321                mRenderNode.setAnimationMatrix(null);
15322                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15323            }
15324            if (!drawingWithRenderNode
15325                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15326                final Transformation t = parent.getChildTransformation();
15327                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15328                if (hasTransform) {
15329                    final int transformType = t.getTransformationType();
15330                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15331                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15332                }
15333            }
15334        }
15335
15336        concatMatrix |= !childHasIdentityMatrix;
15337
15338        // Sets the flag as early as possible to allow draw() implementations
15339        // to call invalidate() successfully when doing animations
15340        mPrivateFlags |= PFLAG_DRAWN;
15341
15342        if (!concatMatrix &&
15343                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15344                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15345                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15346                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15347            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15348            return more;
15349        }
15350        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15351
15352        if (hardwareAcceleratedCanvas) {
15353            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15354            // retain the flag's value temporarily in the mRecreateDisplayList flag
15355            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15356            mPrivateFlags &= ~PFLAG_INVALIDATED;
15357        }
15358
15359        RenderNode renderNode = null;
15360        Bitmap cache = null;
15361        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15362        if (layerType == LAYER_TYPE_SOFTWARE
15363                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15364            // If not drawing with RenderNode, treat HW layers as SW
15365            layerType = LAYER_TYPE_SOFTWARE;
15366            buildDrawingCache(true);
15367            cache = getDrawingCache(true);
15368        }
15369
15370        if (drawingWithRenderNode) {
15371            // Delay getting the display list until animation-driven alpha values are
15372            // set up and possibly passed on to the view
15373            renderNode = getDisplayList();
15374            if (!renderNode.isValid()) {
15375                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15376                // to getDisplayList(), the display list will be marked invalid and we should not
15377                // try to use it again.
15378                renderNode = null;
15379                drawingWithRenderNode = false;
15380            }
15381        }
15382
15383        int sx = 0;
15384        int sy = 0;
15385        if (!drawingWithRenderNode) {
15386            computeScroll();
15387            sx = mScrollX;
15388            sy = mScrollY;
15389        }
15390
15391        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15392        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15393
15394        int restoreTo = -1;
15395        if (!drawingWithRenderNode || transformToApply != null) {
15396            restoreTo = canvas.save();
15397        }
15398        if (offsetForScroll) {
15399            canvas.translate(mLeft - sx, mTop - sy);
15400        } else {
15401            if (!drawingWithRenderNode) {
15402                canvas.translate(mLeft, mTop);
15403            }
15404            if (scalingRequired) {
15405                if (drawingWithRenderNode) {
15406                    // TODO: Might not need this if we put everything inside the DL
15407                    restoreTo = canvas.save();
15408                }
15409                // mAttachInfo cannot be null, otherwise scalingRequired == false
15410                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15411                canvas.scale(scale, scale);
15412            }
15413        }
15414
15415        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
15416        if (transformToApply != null
15417                || alpha < 1
15418                || !hasIdentityMatrix()
15419                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15420            if (transformToApply != null || !childHasIdentityMatrix) {
15421                int transX = 0;
15422                int transY = 0;
15423
15424                if (offsetForScroll) {
15425                    transX = -sx;
15426                    transY = -sy;
15427                }
15428
15429                if (transformToApply != null) {
15430                    if (concatMatrix) {
15431                        if (drawingWithRenderNode) {
15432                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
15433                        } else {
15434                            // Undo the scroll translation, apply the transformation matrix,
15435                            // then redo the scroll translate to get the correct result.
15436                            canvas.translate(-transX, -transY);
15437                            canvas.concat(transformToApply.getMatrix());
15438                            canvas.translate(transX, transY);
15439                        }
15440                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15441                    }
15442
15443                    float transformAlpha = transformToApply.getAlpha();
15444                    if (transformAlpha < 1) {
15445                        alpha *= transformAlpha;
15446                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15447                    }
15448                }
15449
15450                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
15451                    canvas.translate(-transX, -transY);
15452                    canvas.concat(getMatrix());
15453                    canvas.translate(transX, transY);
15454                }
15455            }
15456
15457            // Deal with alpha if it is or used to be <1
15458            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
15459                if (alpha < 1) {
15460                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15461                } else {
15462                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15463                }
15464                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15465                if (!drawingWithDrawingCache) {
15466                    final int multipliedAlpha = (int) (255 * alpha);
15467                    if (!onSetAlpha(multipliedAlpha)) {
15468                        if (drawingWithRenderNode) {
15469                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15470                        } else if (layerType == LAYER_TYPE_NONE) {
15471                            int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15472                            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0) {
15473                                layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
15474                            }
15475                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
15476                                    multipliedAlpha, layerFlags);
15477                        }
15478                    } else {
15479                        // Alpha is handled by the child directly, clobber the layer's alpha
15480                        mPrivateFlags |= PFLAG_ALPHA_SET;
15481                    }
15482                }
15483            }
15484        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15485            onSetAlpha(255);
15486            mPrivateFlags &= ~PFLAG_ALPHA_SET;
15487        }
15488
15489        if (!drawingWithRenderNode) {
15490            // apply clips directly, since RenderNode won't do it for this draw
15491            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
15492                if (offsetForScroll) {
15493                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
15494                } else {
15495                    if (!scalingRequired || cache == null) {
15496                        canvas.clipRect(0, 0, getWidth(), getHeight());
15497                    } else {
15498                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
15499                    }
15500                }
15501            }
15502
15503            if (mClipBounds != null) {
15504                // clip bounds ignore scroll
15505                canvas.clipRect(mClipBounds);
15506            }
15507        }
15508
15509        if (!drawingWithDrawingCache) {
15510            if (drawingWithRenderNode) {
15511                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15512                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
15513            } else {
15514                // Fast path for layouts with no backgrounds
15515                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15516                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15517                    dispatchDraw(canvas);
15518                } else {
15519                    draw(canvas);
15520                }
15521            }
15522        } else if (cache != null) {
15523            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15524            Paint cachePaint;
15525            int restoreAlpha = 0;
15526
15527            if (layerType == LAYER_TYPE_NONE) {
15528                cachePaint = parent.mCachePaint;
15529                if (cachePaint == null) {
15530                    cachePaint = new Paint();
15531                    cachePaint.setDither(false);
15532                    parent.mCachePaint = cachePaint;
15533                }
15534            } else {
15535                cachePaint = mLayerPaint;
15536                restoreAlpha = mLayerPaint.getAlpha();
15537            }
15538            cachePaint.setAlpha((int) (alpha * 255));
15539            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15540            cachePaint.setAlpha(restoreAlpha);
15541        }
15542
15543        if (restoreTo >= 0) {
15544            canvas.restoreToCount(restoreTo);
15545        }
15546
15547        if (a != null && !more) {
15548            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
15549                onSetAlpha(255);
15550            }
15551            parent.finishAnimatingView(this, a);
15552        }
15553
15554        if (more && hardwareAcceleratedCanvas) {
15555            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15556                // alpha animations should cause the child to recreate its display list
15557                invalidate(true);
15558            }
15559        }
15560
15561        mRecreateDisplayList = false;
15562
15563        return more;
15564    }
15565
15566    /**
15567     * Manually render this view (and all of its children) to the given Canvas.
15568     * The view must have already done a full layout before this function is
15569     * called.  When implementing a view, implement
15570     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15571     * If you do need to override this method, call the superclass version.
15572     *
15573     * @param canvas The Canvas to which the View is rendered.
15574     */
15575    @CallSuper
15576    public void draw(Canvas canvas) {
15577        final int privateFlags = mPrivateFlags;
15578        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15579                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15580        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15581
15582        /*
15583         * Draw traversal performs several drawing steps which must be executed
15584         * in the appropriate order:
15585         *
15586         *      1. Draw the background
15587         *      2. If necessary, save the canvas' layers to prepare for fading
15588         *      3. Draw view's content
15589         *      4. Draw children
15590         *      5. If necessary, draw the fading edges and restore layers
15591         *      6. Draw decorations (scrollbars for instance)
15592         */
15593
15594        // Step 1, draw the background, if needed
15595        int saveCount;
15596
15597        if (!dirtyOpaque) {
15598            drawBackground(canvas);
15599        }
15600
15601        // skip step 2 & 5 if possible (common case)
15602        final int viewFlags = mViewFlags;
15603        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15604        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15605        if (!verticalEdges && !horizontalEdges) {
15606            // Step 3, draw the content
15607            if (!dirtyOpaque) onDraw(canvas);
15608
15609            // Step 4, draw the children
15610            dispatchDraw(canvas);
15611
15612            // Overlay is part of the content and draws beneath Foreground
15613            if (mOverlay != null && !mOverlay.isEmpty()) {
15614                mOverlay.getOverlayView().dispatchDraw(canvas);
15615            }
15616
15617            // Step 6, draw decorations (foreground, scrollbars)
15618            onDrawForeground(canvas);
15619
15620            // we're done...
15621            return;
15622        }
15623
15624        /*
15625         * Here we do the full fledged routine...
15626         * (this is an uncommon case where speed matters less,
15627         * this is why we repeat some of the tests that have been
15628         * done above)
15629         */
15630
15631        boolean drawTop = false;
15632        boolean drawBottom = false;
15633        boolean drawLeft = false;
15634        boolean drawRight = false;
15635
15636        float topFadeStrength = 0.0f;
15637        float bottomFadeStrength = 0.0f;
15638        float leftFadeStrength = 0.0f;
15639        float rightFadeStrength = 0.0f;
15640
15641        // Step 2, save the canvas' layers
15642        int paddingLeft = mPaddingLeft;
15643
15644        final boolean offsetRequired = isPaddingOffsetRequired();
15645        if (offsetRequired) {
15646            paddingLeft += getLeftPaddingOffset();
15647        }
15648
15649        int left = mScrollX + paddingLeft;
15650        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15651        int top = mScrollY + getFadeTop(offsetRequired);
15652        int bottom = top + getFadeHeight(offsetRequired);
15653
15654        if (offsetRequired) {
15655            right += getRightPaddingOffset();
15656            bottom += getBottomPaddingOffset();
15657        }
15658
15659        final ScrollabilityCache scrollabilityCache = mScrollCache;
15660        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15661        int length = (int) fadeHeight;
15662
15663        // clip the fade length if top and bottom fades overlap
15664        // overlapping fades produce odd-looking artifacts
15665        if (verticalEdges && (top + length > bottom - length)) {
15666            length = (bottom - top) / 2;
15667        }
15668
15669        // also clip horizontal fades if necessary
15670        if (horizontalEdges && (left + length > right - length)) {
15671            length = (right - left) / 2;
15672        }
15673
15674        if (verticalEdges) {
15675            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15676            drawTop = topFadeStrength * fadeHeight > 1.0f;
15677            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15678            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15679        }
15680
15681        if (horizontalEdges) {
15682            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15683            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15684            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15685            drawRight = rightFadeStrength * fadeHeight > 1.0f;
15686        }
15687
15688        saveCount = canvas.getSaveCount();
15689
15690        int solidColor = getSolidColor();
15691        if (solidColor == 0) {
15692            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15693
15694            if (drawTop) {
15695                canvas.saveLayer(left, top, right, top + length, null, flags);
15696            }
15697
15698            if (drawBottom) {
15699                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15700            }
15701
15702            if (drawLeft) {
15703                canvas.saveLayer(left, top, left + length, bottom, null, flags);
15704            }
15705
15706            if (drawRight) {
15707                canvas.saveLayer(right - length, top, right, bottom, null, flags);
15708            }
15709        } else {
15710            scrollabilityCache.setFadeColor(solidColor);
15711        }
15712
15713        // Step 3, draw the content
15714        if (!dirtyOpaque) onDraw(canvas);
15715
15716        // Step 4, draw the children
15717        dispatchDraw(canvas);
15718
15719        // Step 5, draw the fade effect and restore layers
15720        final Paint p = scrollabilityCache.paint;
15721        final Matrix matrix = scrollabilityCache.matrix;
15722        final Shader fade = scrollabilityCache.shader;
15723
15724        if (drawTop) {
15725            matrix.setScale(1, fadeHeight * topFadeStrength);
15726            matrix.postTranslate(left, top);
15727            fade.setLocalMatrix(matrix);
15728            p.setShader(fade);
15729            canvas.drawRect(left, top, right, top + length, p);
15730        }
15731
15732        if (drawBottom) {
15733            matrix.setScale(1, fadeHeight * bottomFadeStrength);
15734            matrix.postRotate(180);
15735            matrix.postTranslate(left, bottom);
15736            fade.setLocalMatrix(matrix);
15737            p.setShader(fade);
15738            canvas.drawRect(left, bottom - length, right, bottom, p);
15739        }
15740
15741        if (drawLeft) {
15742            matrix.setScale(1, fadeHeight * leftFadeStrength);
15743            matrix.postRotate(-90);
15744            matrix.postTranslate(left, top);
15745            fade.setLocalMatrix(matrix);
15746            p.setShader(fade);
15747            canvas.drawRect(left, top, left + length, bottom, p);
15748        }
15749
15750        if (drawRight) {
15751            matrix.setScale(1, fadeHeight * rightFadeStrength);
15752            matrix.postRotate(90);
15753            matrix.postTranslate(right, top);
15754            fade.setLocalMatrix(matrix);
15755            p.setShader(fade);
15756            canvas.drawRect(right - length, top, right, bottom, p);
15757        }
15758
15759        canvas.restoreToCount(saveCount);
15760
15761        // Overlay is part of the content and draws beneath Foreground
15762        if (mOverlay != null && !mOverlay.isEmpty()) {
15763            mOverlay.getOverlayView().dispatchDraw(canvas);
15764        }
15765
15766        // Step 6, draw decorations (foreground, scrollbars)
15767        onDrawForeground(canvas);
15768    }
15769
15770    /**
15771     * Draws the background onto the specified canvas.
15772     *
15773     * @param canvas Canvas on which to draw the background
15774     */
15775    private void drawBackground(Canvas canvas) {
15776        final Drawable background = mBackground;
15777        if (background == null) {
15778            return;
15779        }
15780
15781        setBackgroundBounds();
15782
15783        // Attempt to use a display list if requested.
15784        if (canvas.isHardwareAccelerated() && mAttachInfo != null
15785                && mAttachInfo.mHardwareRenderer != null) {
15786            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15787
15788            final RenderNode renderNode = mBackgroundRenderNode;
15789            if (renderNode != null && renderNode.isValid()) {
15790                setBackgroundRenderNodeProperties(renderNode);
15791                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
15792                return;
15793            }
15794        }
15795
15796        final int scrollX = mScrollX;
15797        final int scrollY = mScrollY;
15798        if ((scrollX | scrollY) == 0) {
15799            background.draw(canvas);
15800        } else {
15801            canvas.translate(scrollX, scrollY);
15802            background.draw(canvas);
15803            canvas.translate(-scrollX, -scrollY);
15804        }
15805    }
15806
15807    /**
15808     * Sets the correct background bounds and rebuilds the outline, if needed.
15809     * <p/>
15810     * This is called by LayoutLib.
15811     */
15812    void setBackgroundBounds() {
15813        if (mBackgroundSizeChanged && mBackground != null) {
15814            mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
15815            mBackgroundSizeChanged = false;
15816            rebuildOutline();
15817        }
15818    }
15819
15820    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
15821        renderNode.setTranslationX(mScrollX);
15822        renderNode.setTranslationY(mScrollY);
15823    }
15824
15825    /**
15826     * Creates a new display list or updates the existing display list for the
15827     * specified Drawable.
15828     *
15829     * @param drawable Drawable for which to create a display list
15830     * @param renderNode Existing RenderNode, or {@code null}
15831     * @return A valid display list for the specified drawable
15832     */
15833    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15834        if (renderNode == null) {
15835            renderNode = RenderNode.create(drawable.getClass().getName(), this);
15836        }
15837
15838        final Rect bounds = drawable.getBounds();
15839        final int width = bounds.width();
15840        final int height = bounds.height();
15841        final DisplayListCanvas canvas = renderNode.start(width, height);
15842
15843        // Reverse left/top translation done by drawable canvas, which will
15844        // instead be applied by rendernode's LTRB bounds below. This way, the
15845        // drawable's bounds match with its rendernode bounds and its content
15846        // will lie within those bounds in the rendernode tree.
15847        canvas.translate(-bounds.left, -bounds.top);
15848
15849        try {
15850            drawable.draw(canvas);
15851        } finally {
15852            renderNode.end(canvas);
15853        }
15854
15855        // Set up drawable properties that are view-independent.
15856        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15857        renderNode.setProjectBackwards(drawable.isProjected());
15858        renderNode.setProjectionReceiver(true);
15859        renderNode.setClipToBounds(false);
15860        return renderNode;
15861    }
15862
15863    /**
15864     * Returns the overlay for this view, creating it if it does not yet exist.
15865     * Adding drawables to the overlay will cause them to be displayed whenever
15866     * the view itself is redrawn. Objects in the overlay should be actively
15867     * managed: remove them when they should not be displayed anymore. The
15868     * overlay will always have the same size as its host view.
15869     *
15870     * <p>Note: Overlays do not currently work correctly with {@link
15871     * SurfaceView} or {@link TextureView}; contents in overlays for these
15872     * types of views may not display correctly.</p>
15873     *
15874     * @return The ViewOverlay object for this view.
15875     * @see ViewOverlay
15876     */
15877    public ViewOverlay getOverlay() {
15878        if (mOverlay == null) {
15879            mOverlay = new ViewOverlay(mContext, this);
15880        }
15881        return mOverlay;
15882    }
15883
15884    /**
15885     * Override this if your view is known to always be drawn on top of a solid color background,
15886     * and needs to draw fading edges. Returning a non-zero color enables the view system to
15887     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15888     * should be set to 0xFF.
15889     *
15890     * @see #setVerticalFadingEdgeEnabled(boolean)
15891     * @see #setHorizontalFadingEdgeEnabled(boolean)
15892     *
15893     * @return The known solid color background for this view, or 0 if the color may vary
15894     */
15895    @ViewDebug.ExportedProperty(category = "drawing")
15896    @ColorInt
15897    public int getSolidColor() {
15898        return 0;
15899    }
15900
15901    /**
15902     * Build a human readable string representation of the specified view flags.
15903     *
15904     * @param flags the view flags to convert to a string
15905     * @return a String representing the supplied flags
15906     */
15907    private static String printFlags(int flags) {
15908        String output = "";
15909        int numFlags = 0;
15910        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15911            output += "TAKES_FOCUS";
15912            numFlags++;
15913        }
15914
15915        switch (flags & VISIBILITY_MASK) {
15916        case INVISIBLE:
15917            if (numFlags > 0) {
15918                output += " ";
15919            }
15920            output += "INVISIBLE";
15921            // USELESS HERE numFlags++;
15922            break;
15923        case GONE:
15924            if (numFlags > 0) {
15925                output += " ";
15926            }
15927            output += "GONE";
15928            // USELESS HERE numFlags++;
15929            break;
15930        default:
15931            break;
15932        }
15933        return output;
15934    }
15935
15936    /**
15937     * Build a human readable string representation of the specified private
15938     * view flags.
15939     *
15940     * @param privateFlags the private view flags to convert to a string
15941     * @return a String representing the supplied flags
15942     */
15943    private static String printPrivateFlags(int privateFlags) {
15944        String output = "";
15945        int numFlags = 0;
15946
15947        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15948            output += "WANTS_FOCUS";
15949            numFlags++;
15950        }
15951
15952        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15953            if (numFlags > 0) {
15954                output += " ";
15955            }
15956            output += "FOCUSED";
15957            numFlags++;
15958        }
15959
15960        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15961            if (numFlags > 0) {
15962                output += " ";
15963            }
15964            output += "SELECTED";
15965            numFlags++;
15966        }
15967
15968        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15969            if (numFlags > 0) {
15970                output += " ";
15971            }
15972            output += "IS_ROOT_NAMESPACE";
15973            numFlags++;
15974        }
15975
15976        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15977            if (numFlags > 0) {
15978                output += " ";
15979            }
15980            output += "HAS_BOUNDS";
15981            numFlags++;
15982        }
15983
15984        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15985            if (numFlags > 0) {
15986                output += " ";
15987            }
15988            output += "DRAWN";
15989            // USELESS HERE numFlags++;
15990        }
15991        return output;
15992    }
15993
15994    /**
15995     * <p>Indicates whether or not this view's layout will be requested during
15996     * the next hierarchy layout pass.</p>
15997     *
15998     * @return true if the layout will be forced during next layout pass
15999     */
16000    public boolean isLayoutRequested() {
16001        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16002    }
16003
16004    /**
16005     * Return true if o is a ViewGroup that is laying out using optical bounds.
16006     * @hide
16007     */
16008    public static boolean isLayoutModeOptical(Object o) {
16009        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16010    }
16011
16012    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16013        Insets parentInsets = mParent instanceof View ?
16014                ((View) mParent).getOpticalInsets() : Insets.NONE;
16015        Insets childInsets = getOpticalInsets();
16016        return setFrame(
16017                left   + parentInsets.left - childInsets.left,
16018                top    + parentInsets.top  - childInsets.top,
16019                right  + parentInsets.left + childInsets.right,
16020                bottom + parentInsets.top  + childInsets.bottom);
16021    }
16022
16023    /**
16024     * Assign a size and position to a view and all of its
16025     * descendants
16026     *
16027     * <p>This is the second phase of the layout mechanism.
16028     * (The first is measuring). In this phase, each parent calls
16029     * layout on all of its children to position them.
16030     * This is typically done using the child measurements
16031     * that were stored in the measure pass().</p>
16032     *
16033     * <p>Derived classes should not override this method.
16034     * Derived classes with children should override
16035     * onLayout. In that method, they should
16036     * call layout on each of their children.</p>
16037     *
16038     * @param l Left position, relative to parent
16039     * @param t Top position, relative to parent
16040     * @param r Right position, relative to parent
16041     * @param b Bottom position, relative to parent
16042     */
16043    @SuppressWarnings({"unchecked"})
16044    public void layout(int l, int t, int r, int b) {
16045        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16046            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16047            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16048        }
16049
16050        int oldL = mLeft;
16051        int oldT = mTop;
16052        int oldB = mBottom;
16053        int oldR = mRight;
16054
16055        boolean changed = isLayoutModeOptical(mParent) ?
16056                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16057
16058        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16059            onLayout(changed, l, t, r, b);
16060            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16061
16062            ListenerInfo li = mListenerInfo;
16063            if (li != null && li.mOnLayoutChangeListeners != null) {
16064                ArrayList<OnLayoutChangeListener> listenersCopy =
16065                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16066                int numListeners = listenersCopy.size();
16067                for (int i = 0; i < numListeners; ++i) {
16068                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16069                }
16070            }
16071        }
16072
16073        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16074        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16075    }
16076
16077    /**
16078     * Called from layout when this view should
16079     * assign a size and position to each of its children.
16080     *
16081     * Derived classes with children should override
16082     * this method and call layout on each of
16083     * their children.
16084     * @param changed This is a new size or position for this view
16085     * @param left Left position, relative to parent
16086     * @param top Top position, relative to parent
16087     * @param right Right position, relative to parent
16088     * @param bottom Bottom position, relative to parent
16089     */
16090    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16091    }
16092
16093    /**
16094     * Assign a size and position to this view.
16095     *
16096     * This is called from layout.
16097     *
16098     * @param left Left position, relative to parent
16099     * @param top Top position, relative to parent
16100     * @param right Right position, relative to parent
16101     * @param bottom Bottom position, relative to parent
16102     * @return true if the new size and position are different than the
16103     *         previous ones
16104     * {@hide}
16105     */
16106    protected boolean setFrame(int left, int top, int right, int bottom) {
16107        boolean changed = false;
16108
16109        if (DBG) {
16110            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16111                    + right + "," + bottom + ")");
16112        }
16113
16114        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16115            changed = true;
16116
16117            // Remember our drawn bit
16118            int drawn = mPrivateFlags & PFLAG_DRAWN;
16119
16120            int oldWidth = mRight - mLeft;
16121            int oldHeight = mBottom - mTop;
16122            int newWidth = right - left;
16123            int newHeight = bottom - top;
16124            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16125
16126            // Invalidate our old position
16127            invalidate(sizeChanged);
16128
16129            mLeft = left;
16130            mTop = top;
16131            mRight = right;
16132            mBottom = bottom;
16133            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16134
16135            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16136
16137
16138            if (sizeChanged) {
16139                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16140            }
16141
16142            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16143                // If we are visible, force the DRAWN bit to on so that
16144                // this invalidate will go through (at least to our parent).
16145                // This is because someone may have invalidated this view
16146                // before this call to setFrame came in, thereby clearing
16147                // the DRAWN bit.
16148                mPrivateFlags |= PFLAG_DRAWN;
16149                invalidate(sizeChanged);
16150                // parent display list may need to be recreated based on a change in the bounds
16151                // of any child
16152                invalidateParentCaches();
16153            }
16154
16155            // Reset drawn bit to original value (invalidate turns it off)
16156            mPrivateFlags |= drawn;
16157
16158            mBackgroundSizeChanged = true;
16159            if (mForegroundInfo != null) {
16160                mForegroundInfo.mBoundsChanged = true;
16161            }
16162
16163            notifySubtreeAccessibilityStateChangedIfNeeded();
16164        }
16165        return changed;
16166    }
16167
16168    /**
16169     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16170     * @hide
16171     */
16172    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16173        setFrame(left, top, right, bottom);
16174    }
16175
16176    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16177        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16178        if (mOverlay != null) {
16179            mOverlay.getOverlayView().setRight(newWidth);
16180            mOverlay.getOverlayView().setBottom(newHeight);
16181        }
16182        rebuildOutline();
16183    }
16184
16185    /**
16186     * Finalize inflating a view from XML.  This is called as the last phase
16187     * of inflation, after all child views have been added.
16188     *
16189     * <p>Even if the subclass overrides onFinishInflate, they should always be
16190     * sure to call the super method, so that we get called.
16191     */
16192    @CallSuper
16193    protected void onFinishInflate() {
16194    }
16195
16196    /**
16197     * Returns the resources associated with this view.
16198     *
16199     * @return Resources object.
16200     */
16201    public Resources getResources() {
16202        return mResources;
16203    }
16204
16205    /**
16206     * Invalidates the specified Drawable.
16207     *
16208     * @param drawable the drawable to invalidate
16209     */
16210    @Override
16211    public void invalidateDrawable(@NonNull Drawable drawable) {
16212        if (verifyDrawable(drawable)) {
16213            final Rect dirty = drawable.getDirtyBounds();
16214            final int scrollX = mScrollX;
16215            final int scrollY = mScrollY;
16216
16217            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16218                    dirty.right + scrollX, dirty.bottom + scrollY);
16219            rebuildOutline();
16220        }
16221    }
16222
16223    /**
16224     * Schedules an action on a drawable to occur at a specified time.
16225     *
16226     * @param who the recipient of the action
16227     * @param what the action to run on the drawable
16228     * @param when the time at which the action must occur. Uses the
16229     *        {@link SystemClock#uptimeMillis} timebase.
16230     */
16231    @Override
16232    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16233        if (verifyDrawable(who) && what != null) {
16234            final long delay = when - SystemClock.uptimeMillis();
16235            if (mAttachInfo != null) {
16236                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16237                        Choreographer.CALLBACK_ANIMATION, what, who,
16238                        Choreographer.subtractFrameDelay(delay));
16239            } else {
16240                ViewRootImpl.getRunQueue().postDelayed(what, delay);
16241            }
16242        }
16243    }
16244
16245    /**
16246     * Cancels a scheduled action on a drawable.
16247     *
16248     * @param who the recipient of the action
16249     * @param what the action to cancel
16250     */
16251    @Override
16252    public void unscheduleDrawable(Drawable who, Runnable what) {
16253        if (verifyDrawable(who) && what != null) {
16254            if (mAttachInfo != null) {
16255                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16256                        Choreographer.CALLBACK_ANIMATION, what, who);
16257            }
16258            ViewRootImpl.getRunQueue().removeCallbacks(what);
16259        }
16260    }
16261
16262    /**
16263     * Unschedule any events associated with the given Drawable.  This can be
16264     * used when selecting a new Drawable into a view, so that the previous
16265     * one is completely unscheduled.
16266     *
16267     * @param who The Drawable to unschedule.
16268     *
16269     * @see #drawableStateChanged
16270     */
16271    public void unscheduleDrawable(Drawable who) {
16272        if (mAttachInfo != null && who != null) {
16273            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16274                    Choreographer.CALLBACK_ANIMATION, null, who);
16275        }
16276    }
16277
16278    /**
16279     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16280     * that the View directionality can and will be resolved before its Drawables.
16281     *
16282     * Will call {@link View#onResolveDrawables} when resolution is done.
16283     *
16284     * @hide
16285     */
16286    protected void resolveDrawables() {
16287        // Drawables resolution may need to happen before resolving the layout direction (which is
16288        // done only during the measure() call).
16289        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16290        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16291        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16292        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16293        // direction to be resolved as its resolved value will be the same as its raw value.
16294        if (!isLayoutDirectionResolved() &&
16295                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16296            return;
16297        }
16298
16299        final int layoutDirection = isLayoutDirectionResolved() ?
16300                getLayoutDirection() : getRawLayoutDirection();
16301
16302        if (mBackground != null) {
16303            mBackground.setLayoutDirection(layoutDirection);
16304        }
16305        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16306            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16307        }
16308        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16309        onResolveDrawables(layoutDirection);
16310    }
16311
16312    boolean areDrawablesResolved() {
16313        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16314    }
16315
16316    /**
16317     * Called when layout direction has been resolved.
16318     *
16319     * The default implementation does nothing.
16320     *
16321     * @param layoutDirection The resolved layout direction.
16322     *
16323     * @see #LAYOUT_DIRECTION_LTR
16324     * @see #LAYOUT_DIRECTION_RTL
16325     *
16326     * @hide
16327     */
16328    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16329    }
16330
16331    /**
16332     * @hide
16333     */
16334    protected void resetResolvedDrawables() {
16335        resetResolvedDrawablesInternal();
16336    }
16337
16338    void resetResolvedDrawablesInternal() {
16339        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16340    }
16341
16342    /**
16343     * If your view subclass is displaying its own Drawable objects, it should
16344     * override this function and return true for any Drawable it is
16345     * displaying.  This allows animations for those drawables to be
16346     * scheduled.
16347     *
16348     * <p>Be sure to call through to the super class when overriding this
16349     * function.
16350     *
16351     * @param who The Drawable to verify.  Return true if it is one you are
16352     *            displaying, else return the result of calling through to the
16353     *            super class.
16354     *
16355     * @return boolean If true than the Drawable is being displayed in the
16356     *         view; else false and it is not allowed to animate.
16357     *
16358     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16359     * @see #drawableStateChanged()
16360     */
16361    @CallSuper
16362    protected boolean verifyDrawable(Drawable who) {
16363        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16364                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16365    }
16366
16367    /**
16368     * This function is called whenever the state of the view changes in such
16369     * a way that it impacts the state of drawables being shown.
16370     * <p>
16371     * If the View has a StateListAnimator, it will also be called to run necessary state
16372     * change animations.
16373     * <p>
16374     * Be sure to call through to the superclass when overriding this function.
16375     *
16376     * @see Drawable#setState(int[])
16377     */
16378    @CallSuper
16379    protected void drawableStateChanged() {
16380        final int[] state = getDrawableState();
16381
16382        final Drawable bg = mBackground;
16383        if (bg != null && bg.isStateful()) {
16384            bg.setState(state);
16385        }
16386
16387        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16388        if (fg != null && fg.isStateful()) {
16389            fg.setState(state);
16390        }
16391
16392        if (mScrollCache != null) {
16393            final Drawable scrollBar = mScrollCache.scrollBar;
16394            if (scrollBar != null && scrollBar.isStateful()) {
16395                scrollBar.setState(state);
16396            }
16397        }
16398
16399        if (mStateListAnimator != null) {
16400            mStateListAnimator.setState(state);
16401        }
16402    }
16403
16404    /**
16405     * This function is called whenever the view hotspot changes and needs to
16406     * be propagated to drawables or child views managed by the view.
16407     * <p>
16408     * Dispatching to child views is handled by
16409     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16410     * <p>
16411     * Be sure to call through to the superclass when overriding this function.
16412     *
16413     * @param x hotspot x coordinate
16414     * @param y hotspot y coordinate
16415     */
16416    @CallSuper
16417    public void drawableHotspotChanged(float x, float y) {
16418        if (mBackground != null) {
16419            mBackground.setHotspot(x, y);
16420        }
16421        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16422            mForegroundInfo.mDrawable.setHotspot(x, y);
16423        }
16424
16425        dispatchDrawableHotspotChanged(x, y);
16426    }
16427
16428    /**
16429     * Dispatches drawableHotspotChanged to all of this View's children.
16430     *
16431     * @param x hotspot x coordinate
16432     * @param y hotspot y coordinate
16433     * @see #drawableHotspotChanged(float, float)
16434     */
16435    public void dispatchDrawableHotspotChanged(float x, float y) {
16436    }
16437
16438    /**
16439     * Call this to force a view to update its drawable state. This will cause
16440     * drawableStateChanged to be called on this view. Views that are interested
16441     * in the new state should call getDrawableState.
16442     *
16443     * @see #drawableStateChanged
16444     * @see #getDrawableState
16445     */
16446    public void refreshDrawableState() {
16447        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16448        drawableStateChanged();
16449
16450        ViewParent parent = mParent;
16451        if (parent != null) {
16452            parent.childDrawableStateChanged(this);
16453        }
16454    }
16455
16456    /**
16457     * Return an array of resource IDs of the drawable states representing the
16458     * current state of the view.
16459     *
16460     * @return The current drawable state
16461     *
16462     * @see Drawable#setState(int[])
16463     * @see #drawableStateChanged()
16464     * @see #onCreateDrawableState(int)
16465     */
16466    public final int[] getDrawableState() {
16467        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16468            return mDrawableState;
16469        } else {
16470            mDrawableState = onCreateDrawableState(0);
16471            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16472            return mDrawableState;
16473        }
16474    }
16475
16476    /**
16477     * Generate the new {@link android.graphics.drawable.Drawable} state for
16478     * this view. This is called by the view
16479     * system when the cached Drawable state is determined to be invalid.  To
16480     * retrieve the current state, you should use {@link #getDrawableState}.
16481     *
16482     * @param extraSpace if non-zero, this is the number of extra entries you
16483     * would like in the returned array in which you can place your own
16484     * states.
16485     *
16486     * @return Returns an array holding the current {@link Drawable} state of
16487     * the view.
16488     *
16489     * @see #mergeDrawableStates(int[], int[])
16490     */
16491    protected int[] onCreateDrawableState(int extraSpace) {
16492        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
16493                mParent instanceof View) {
16494            return ((View) mParent).onCreateDrawableState(extraSpace);
16495        }
16496
16497        int[] drawableState;
16498
16499        int privateFlags = mPrivateFlags;
16500
16501        int viewStateIndex = 0;
16502        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
16503        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
16504        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
16505        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
16506        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
16507        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
16508        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16509                HardwareRenderer.isAvailable()) {
16510            // This is set if HW acceleration is requested, even if the current
16511            // process doesn't allow it.  This is just to allow app preview
16512            // windows to better match their app.
16513            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
16514        }
16515        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
16516
16517        final int privateFlags2 = mPrivateFlags2;
16518        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
16519            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
16520        }
16521        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
16522            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
16523        }
16524
16525        drawableState = StateSet.get(viewStateIndex);
16526
16527        //noinspection ConstantIfStatement
16528        if (false) {
16529            Log.i("View", "drawableStateIndex=" + viewStateIndex);
16530            Log.i("View", toString()
16531                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16532                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16533                    + " fo=" + hasFocus()
16534                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16535                    + " wf=" + hasWindowFocus()
16536                    + ": " + Arrays.toString(drawableState));
16537        }
16538
16539        if (extraSpace == 0) {
16540            return drawableState;
16541        }
16542
16543        final int[] fullState;
16544        if (drawableState != null) {
16545            fullState = new int[drawableState.length + extraSpace];
16546            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16547        } else {
16548            fullState = new int[extraSpace];
16549        }
16550
16551        return fullState;
16552    }
16553
16554    /**
16555     * Merge your own state values in <var>additionalState</var> into the base
16556     * state values <var>baseState</var> that were returned by
16557     * {@link #onCreateDrawableState(int)}.
16558     *
16559     * @param baseState The base state values returned by
16560     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16561     * own additional state values.
16562     *
16563     * @param additionalState The additional state values you would like
16564     * added to <var>baseState</var>; this array is not modified.
16565     *
16566     * @return As a convenience, the <var>baseState</var> array you originally
16567     * passed into the function is returned.
16568     *
16569     * @see #onCreateDrawableState(int)
16570     */
16571    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16572        final int N = baseState.length;
16573        int i = N - 1;
16574        while (i >= 0 && baseState[i] == 0) {
16575            i--;
16576        }
16577        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16578        return baseState;
16579    }
16580
16581    /**
16582     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16583     * on all Drawable objects associated with this view.
16584     * <p>
16585     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16586     * attached to this view.
16587     */
16588    public void jumpDrawablesToCurrentState() {
16589        if (mBackground != null) {
16590            mBackground.jumpToCurrentState();
16591        }
16592        if (mStateListAnimator != null) {
16593            mStateListAnimator.jumpToCurrentState();
16594        }
16595        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16596            mForegroundInfo.mDrawable.jumpToCurrentState();
16597        }
16598    }
16599
16600    /**
16601     * Sets the background color for this view.
16602     * @param color the color of the background
16603     */
16604    @RemotableViewMethod
16605    public void setBackgroundColor(@ColorInt int color) {
16606        if (mBackground instanceof ColorDrawable) {
16607            ((ColorDrawable) mBackground.mutate()).setColor(color);
16608            computeOpaqueFlags();
16609            mBackgroundResource = 0;
16610        } else {
16611            setBackground(new ColorDrawable(color));
16612        }
16613    }
16614
16615    /**
16616     * If the view has a ColorDrawable background, returns the color of that
16617     * drawable.
16618     *
16619     * @return The color of the ColorDrawable background, if set, otherwise 0.
16620     */
16621    @ColorInt
16622    public int getBackgroundColor() {
16623        if (mBackground instanceof ColorDrawable) {
16624            return ((ColorDrawable) mBackground).getColor();
16625        }
16626        return 0;
16627    }
16628
16629    /**
16630     * Set the background to a given resource. The resource should refer to
16631     * a Drawable object or 0 to remove the background.
16632     * @param resid The identifier of the resource.
16633     *
16634     * @attr ref android.R.styleable#View_background
16635     */
16636    @RemotableViewMethod
16637    public void setBackgroundResource(@DrawableRes int resid) {
16638        if (resid != 0 && resid == mBackgroundResource) {
16639            return;
16640        }
16641
16642        Drawable d = null;
16643        if (resid != 0) {
16644            d = mContext.getDrawable(resid);
16645        }
16646        setBackground(d);
16647
16648        mBackgroundResource = resid;
16649    }
16650
16651    /**
16652     * Set the background to a given Drawable, or remove the background. If the
16653     * background has padding, this View's padding is set to the background's
16654     * padding. However, when a background is removed, this View's padding isn't
16655     * touched. If setting the padding is desired, please use
16656     * {@link #setPadding(int, int, int, int)}.
16657     *
16658     * @param background The Drawable to use as the background, or null to remove the
16659     *        background
16660     */
16661    public void setBackground(Drawable background) {
16662        //noinspection deprecation
16663        setBackgroundDrawable(background);
16664    }
16665
16666    /**
16667     * @deprecated use {@link #setBackground(Drawable)} instead
16668     */
16669    @Deprecated
16670    public void setBackgroundDrawable(Drawable background) {
16671        computeOpaqueFlags();
16672
16673        if (background == mBackground) {
16674            return;
16675        }
16676
16677        boolean requestLayout = false;
16678
16679        mBackgroundResource = 0;
16680
16681        /*
16682         * Regardless of whether we're setting a new background or not, we want
16683         * to clear the previous drawable.
16684         */
16685        if (mBackground != null) {
16686            mBackground.setCallback(null);
16687            unscheduleDrawable(mBackground);
16688        }
16689
16690        if (background != null) {
16691            Rect padding = sThreadLocal.get();
16692            if (padding == null) {
16693                padding = new Rect();
16694                sThreadLocal.set(padding);
16695            }
16696            resetResolvedDrawablesInternal();
16697            background.setLayoutDirection(getLayoutDirection());
16698            if (background.getPadding(padding)) {
16699                resetResolvedPaddingInternal();
16700                switch (background.getLayoutDirection()) {
16701                    case LAYOUT_DIRECTION_RTL:
16702                        mUserPaddingLeftInitial = padding.right;
16703                        mUserPaddingRightInitial = padding.left;
16704                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16705                        break;
16706                    case LAYOUT_DIRECTION_LTR:
16707                    default:
16708                        mUserPaddingLeftInitial = padding.left;
16709                        mUserPaddingRightInitial = padding.right;
16710                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16711                }
16712                mLeftPaddingDefined = false;
16713                mRightPaddingDefined = false;
16714            }
16715
16716            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
16717            // if it has a different minimum size, we should layout again
16718            if (mBackground == null
16719                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
16720                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16721                requestLayout = true;
16722            }
16723
16724            background.setCallback(this);
16725            if (background.isStateful()) {
16726                background.setState(getDrawableState());
16727            }
16728            background.setVisible(getVisibility() == VISIBLE, false);
16729            mBackground = background;
16730
16731            applyBackgroundTint();
16732
16733            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16734                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16735                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16736                requestLayout = true;
16737            }
16738        } else {
16739            /* Remove the background */
16740            mBackground = null;
16741
16742            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16743                /*
16744                 * This view ONLY drew the background before and we're removing
16745                 * the background, so now it won't draw anything
16746                 * (hence we SKIP_DRAW)
16747                 */
16748                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16749                mPrivateFlags |= PFLAG_SKIP_DRAW;
16750            }
16751
16752            /*
16753             * When the background is set, we try to apply its padding to this
16754             * View. When the background is removed, we don't touch this View's
16755             * padding. This is noted in the Javadocs. Hence, we don't need to
16756             * requestLayout(), the invalidate() below is sufficient.
16757             */
16758
16759            // The old background's minimum size could have affected this
16760            // View's layout, so let's requestLayout
16761            requestLayout = true;
16762        }
16763
16764        computeOpaqueFlags();
16765
16766        if (requestLayout) {
16767            requestLayout();
16768        }
16769
16770        mBackgroundSizeChanged = true;
16771        invalidate(true);
16772    }
16773
16774    /**
16775     * Gets the background drawable
16776     *
16777     * @return The drawable used as the background for this view, if any.
16778     *
16779     * @see #setBackground(Drawable)
16780     *
16781     * @attr ref android.R.styleable#View_background
16782     */
16783    public Drawable getBackground() {
16784        return mBackground;
16785    }
16786
16787    /**
16788     * Applies a tint to the background drawable. Does not modify the current tint
16789     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16790     * <p>
16791     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16792     * mutate the drawable and apply the specified tint and tint mode using
16793     * {@link Drawable#setTintList(ColorStateList)}.
16794     *
16795     * @param tint the tint to apply, may be {@code null} to clear tint
16796     *
16797     * @attr ref android.R.styleable#View_backgroundTint
16798     * @see #getBackgroundTintList()
16799     * @see Drawable#setTintList(ColorStateList)
16800     */
16801    public void setBackgroundTintList(@Nullable ColorStateList tint) {
16802        if (mBackgroundTint == null) {
16803            mBackgroundTint = new TintInfo();
16804        }
16805        mBackgroundTint.mTintList = tint;
16806        mBackgroundTint.mHasTintList = true;
16807
16808        applyBackgroundTint();
16809    }
16810
16811    /**
16812     * Return the tint applied to the background drawable, if specified.
16813     *
16814     * @return the tint applied to the background drawable
16815     * @attr ref android.R.styleable#View_backgroundTint
16816     * @see #setBackgroundTintList(ColorStateList)
16817     */
16818    @Nullable
16819    public ColorStateList getBackgroundTintList() {
16820        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16821    }
16822
16823    /**
16824     * Specifies the blending mode used to apply the tint specified by
16825     * {@link #setBackgroundTintList(ColorStateList)}} to the background
16826     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16827     *
16828     * @param tintMode the blending mode used to apply the tint, may be
16829     *                 {@code null} to clear tint
16830     * @attr ref android.R.styleable#View_backgroundTintMode
16831     * @see #getBackgroundTintMode()
16832     * @see Drawable#setTintMode(PorterDuff.Mode)
16833     */
16834    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16835        if (mBackgroundTint == null) {
16836            mBackgroundTint = new TintInfo();
16837        }
16838        mBackgroundTint.mTintMode = tintMode;
16839        mBackgroundTint.mHasTintMode = true;
16840
16841        applyBackgroundTint();
16842    }
16843
16844    /**
16845     * Return the blending mode used to apply the tint to the background
16846     * drawable, if specified.
16847     *
16848     * @return the blending mode used to apply the tint to the background
16849     *         drawable
16850     * @attr ref android.R.styleable#View_backgroundTintMode
16851     * @see #setBackgroundTintMode(PorterDuff.Mode)
16852     */
16853    @Nullable
16854    public PorterDuff.Mode getBackgroundTintMode() {
16855        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16856    }
16857
16858    private void applyBackgroundTint() {
16859        if (mBackground != null && mBackgroundTint != null) {
16860            final TintInfo tintInfo = mBackgroundTint;
16861            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16862                mBackground = mBackground.mutate();
16863
16864                if (tintInfo.mHasTintList) {
16865                    mBackground.setTintList(tintInfo.mTintList);
16866                }
16867
16868                if (tintInfo.mHasTintMode) {
16869                    mBackground.setTintMode(tintInfo.mTintMode);
16870                }
16871
16872                // The drawable (or one of its children) may not have been
16873                // stateful before applying the tint, so let's try again.
16874                if (mBackground.isStateful()) {
16875                    mBackground.setState(getDrawableState());
16876                }
16877            }
16878        }
16879    }
16880
16881    /**
16882     * Returns the drawable used as the foreground of this View. The
16883     * foreground drawable, if non-null, is always drawn on top of the view's content.
16884     *
16885     * @return a Drawable or null if no foreground was set
16886     *
16887     * @see #onDrawForeground(Canvas)
16888     */
16889    public Drawable getForeground() {
16890        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16891    }
16892
16893    /**
16894     * Supply a Drawable that is to be rendered on top of all of the content in the view.
16895     *
16896     * @param foreground the Drawable to be drawn on top of the children
16897     *
16898     * @attr ref android.R.styleable#View_foreground
16899     */
16900    public void setForeground(Drawable foreground) {
16901        if (mForegroundInfo == null) {
16902            if (foreground == null) {
16903                // Nothing to do.
16904                return;
16905            }
16906            mForegroundInfo = new ForegroundInfo();
16907        }
16908
16909        if (foreground == mForegroundInfo.mDrawable) {
16910            // Nothing to do
16911            return;
16912        }
16913
16914        if (mForegroundInfo.mDrawable != null) {
16915            mForegroundInfo.mDrawable.setCallback(null);
16916            unscheduleDrawable(mForegroundInfo.mDrawable);
16917        }
16918
16919        mForegroundInfo.mDrawable = foreground;
16920        mForegroundInfo.mBoundsChanged = true;
16921        if (foreground != null) {
16922            setWillNotDraw(false);
16923            foreground.setCallback(this);
16924            foreground.setLayoutDirection(getLayoutDirection());
16925            if (foreground.isStateful()) {
16926                foreground.setState(getDrawableState());
16927            }
16928            applyForegroundTint();
16929        }
16930        requestLayout();
16931        invalidate();
16932    }
16933
16934    /**
16935     * Magic bit used to support features of framework-internal window decor implementation details.
16936     * This used to live exclusively in FrameLayout.
16937     *
16938     * @return true if the foreground should draw inside the padding region or false
16939     *         if it should draw inset by the view's padding
16940     * @hide internal use only; only used by FrameLayout and internal screen layouts.
16941     */
16942    public boolean isForegroundInsidePadding() {
16943        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
16944    }
16945
16946    /**
16947     * Describes how the foreground is positioned.
16948     *
16949     * @return foreground gravity.
16950     *
16951     * @see #setForegroundGravity(int)
16952     *
16953     * @attr ref android.R.styleable#View_foregroundGravity
16954     */
16955    public int getForegroundGravity() {
16956        return mForegroundInfo != null ? mForegroundInfo.mGravity
16957                : Gravity.START | Gravity.TOP;
16958    }
16959
16960    /**
16961     * Describes how the foreground is positioned. Defaults to START and TOP.
16962     *
16963     * @param gravity see {@link android.view.Gravity}
16964     *
16965     * @see #getForegroundGravity()
16966     *
16967     * @attr ref android.R.styleable#View_foregroundGravity
16968     */
16969    public void setForegroundGravity(int gravity) {
16970        if (mForegroundInfo == null) {
16971            mForegroundInfo = new ForegroundInfo();
16972        }
16973
16974        if (mForegroundInfo.mGravity != gravity) {
16975            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
16976                gravity |= Gravity.START;
16977            }
16978
16979            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
16980                gravity |= Gravity.TOP;
16981            }
16982
16983            mForegroundInfo.mGravity = gravity;
16984            requestLayout();
16985        }
16986    }
16987
16988    /**
16989     * Applies a tint to the foreground drawable. Does not modify the current tint
16990     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16991     * <p>
16992     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
16993     * mutate the drawable and apply the specified tint and tint mode using
16994     * {@link Drawable#setTintList(ColorStateList)}.
16995     *
16996     * @param tint the tint to apply, may be {@code null} to clear tint
16997     *
16998     * @attr ref android.R.styleable#View_foregroundTint
16999     * @see #getForegroundTintList()
17000     * @see Drawable#setTintList(ColorStateList)
17001     */
17002    public void setForegroundTintList(@Nullable ColorStateList tint) {
17003        if (mForegroundInfo == null) {
17004            mForegroundInfo = new ForegroundInfo();
17005        }
17006        if (mForegroundInfo.mTintInfo == null) {
17007            mForegroundInfo.mTintInfo = new TintInfo();
17008        }
17009        mForegroundInfo.mTintInfo.mTintList = tint;
17010        mForegroundInfo.mTintInfo.mHasTintList = true;
17011
17012        applyForegroundTint();
17013    }
17014
17015    /**
17016     * Return the tint applied to the foreground drawable, if specified.
17017     *
17018     * @return the tint applied to the foreground drawable
17019     * @attr ref android.R.styleable#View_foregroundTint
17020     * @see #setForegroundTintList(ColorStateList)
17021     */
17022    @Nullable
17023    public ColorStateList getForegroundTintList() {
17024        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17025                ? mForegroundInfo.mTintInfo.mTintList : null;
17026    }
17027
17028    /**
17029     * Specifies the blending mode used to apply the tint specified by
17030     * {@link #setForegroundTintList(ColorStateList)}} to the background
17031     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17032     *
17033     * @param tintMode the blending mode used to apply the tint, may be
17034     *                 {@code null} to clear tint
17035     * @attr ref android.R.styleable#View_foregroundTintMode
17036     * @see #getForegroundTintMode()
17037     * @see Drawable#setTintMode(PorterDuff.Mode)
17038     */
17039    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17040        if (mBackgroundTint == null) {
17041            mBackgroundTint = new TintInfo();
17042        }
17043        mBackgroundTint.mTintMode = tintMode;
17044        mBackgroundTint.mHasTintMode = true;
17045
17046        applyBackgroundTint();
17047    }
17048
17049    /**
17050     * Return the blending mode used to apply the tint to the foreground
17051     * drawable, if specified.
17052     *
17053     * @return the blending mode used to apply the tint to the foreground
17054     *         drawable
17055     * @attr ref android.R.styleable#View_foregroundTintMode
17056     * @see #setBackgroundTintMode(PorterDuff.Mode)
17057     */
17058    @Nullable
17059    public PorterDuff.Mode getForegroundTintMode() {
17060        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17061                ? mForegroundInfo.mTintInfo.mTintMode : null;
17062    }
17063
17064    private void applyForegroundTint() {
17065        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17066                && mForegroundInfo.mTintInfo != null) {
17067            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17068            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17069                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17070
17071                if (tintInfo.mHasTintList) {
17072                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17073                }
17074
17075                if (tintInfo.mHasTintMode) {
17076                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17077                }
17078
17079                // The drawable (or one of its children) may not have been
17080                // stateful before applying the tint, so let's try again.
17081                if (mForegroundInfo.mDrawable.isStateful()) {
17082                    mForegroundInfo.mDrawable.setState(getDrawableState());
17083                }
17084            }
17085        }
17086    }
17087
17088    /**
17089     * Draw any foreground content for this view.
17090     *
17091     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17092     * drawable or other view-specific decorations. The foreground is drawn on top of the
17093     * primary view content.</p>
17094     *
17095     * @param canvas canvas to draw into
17096     */
17097    public void onDrawForeground(Canvas canvas) {
17098        onDrawScrollBars(canvas);
17099
17100        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17101        if (foreground != null) {
17102            if (mForegroundInfo.mBoundsChanged) {
17103                mForegroundInfo.mBoundsChanged = false;
17104                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17105                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17106
17107                if (mForegroundInfo.mInsidePadding) {
17108                    selfBounds.set(0, 0, getWidth(), getHeight());
17109                } else {
17110                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17111                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17112                }
17113
17114                final int ld = getLayoutDirection();
17115                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17116                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17117                foreground.setBounds(overlayBounds);
17118            }
17119
17120            foreground.draw(canvas);
17121        }
17122    }
17123
17124    /**
17125     * Sets the padding. The view may add on the space required to display
17126     * the scrollbars, depending on the style and visibility of the scrollbars.
17127     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17128     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17129     * from the values set in this call.
17130     *
17131     * @attr ref android.R.styleable#View_padding
17132     * @attr ref android.R.styleable#View_paddingBottom
17133     * @attr ref android.R.styleable#View_paddingLeft
17134     * @attr ref android.R.styleable#View_paddingRight
17135     * @attr ref android.R.styleable#View_paddingTop
17136     * @param left the left padding in pixels
17137     * @param top the top padding in pixels
17138     * @param right the right padding in pixels
17139     * @param bottom the bottom padding in pixels
17140     */
17141    public void setPadding(int left, int top, int right, int bottom) {
17142        resetResolvedPaddingInternal();
17143
17144        mUserPaddingStart = UNDEFINED_PADDING;
17145        mUserPaddingEnd = UNDEFINED_PADDING;
17146
17147        mUserPaddingLeftInitial = left;
17148        mUserPaddingRightInitial = right;
17149
17150        mLeftPaddingDefined = true;
17151        mRightPaddingDefined = true;
17152
17153        internalSetPadding(left, top, right, bottom);
17154    }
17155
17156    /**
17157     * @hide
17158     */
17159    protected void internalSetPadding(int left, int top, int right, int bottom) {
17160        mUserPaddingLeft = left;
17161        mUserPaddingRight = right;
17162        mUserPaddingBottom = bottom;
17163
17164        final int viewFlags = mViewFlags;
17165        boolean changed = false;
17166
17167        // Common case is there are no scroll bars.
17168        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17169            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17170                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17171                        ? 0 : getVerticalScrollbarWidth();
17172                switch (mVerticalScrollbarPosition) {
17173                    case SCROLLBAR_POSITION_DEFAULT:
17174                        if (isLayoutRtl()) {
17175                            left += offset;
17176                        } else {
17177                            right += offset;
17178                        }
17179                        break;
17180                    case SCROLLBAR_POSITION_RIGHT:
17181                        right += offset;
17182                        break;
17183                    case SCROLLBAR_POSITION_LEFT:
17184                        left += offset;
17185                        break;
17186                }
17187            }
17188            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17189                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17190                        ? 0 : getHorizontalScrollbarHeight();
17191            }
17192        }
17193
17194        if (mPaddingLeft != left) {
17195            changed = true;
17196            mPaddingLeft = left;
17197        }
17198        if (mPaddingTop != top) {
17199            changed = true;
17200            mPaddingTop = top;
17201        }
17202        if (mPaddingRight != right) {
17203            changed = true;
17204            mPaddingRight = right;
17205        }
17206        if (mPaddingBottom != bottom) {
17207            changed = true;
17208            mPaddingBottom = bottom;
17209        }
17210
17211        if (changed) {
17212            requestLayout();
17213            invalidateOutline();
17214        }
17215    }
17216
17217    /**
17218     * Sets the relative padding. The view may add on the space required to display
17219     * the scrollbars, depending on the style and visibility of the scrollbars.
17220     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17221     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17222     * from the values set in this call.
17223     *
17224     * @attr ref android.R.styleable#View_padding
17225     * @attr ref android.R.styleable#View_paddingBottom
17226     * @attr ref android.R.styleable#View_paddingStart
17227     * @attr ref android.R.styleable#View_paddingEnd
17228     * @attr ref android.R.styleable#View_paddingTop
17229     * @param start the start padding in pixels
17230     * @param top the top padding in pixels
17231     * @param end the end padding in pixels
17232     * @param bottom the bottom padding in pixels
17233     */
17234    public void setPaddingRelative(int start, int top, int end, int bottom) {
17235        resetResolvedPaddingInternal();
17236
17237        mUserPaddingStart = start;
17238        mUserPaddingEnd = end;
17239        mLeftPaddingDefined = true;
17240        mRightPaddingDefined = true;
17241
17242        switch(getLayoutDirection()) {
17243            case LAYOUT_DIRECTION_RTL:
17244                mUserPaddingLeftInitial = end;
17245                mUserPaddingRightInitial = start;
17246                internalSetPadding(end, top, start, bottom);
17247                break;
17248            case LAYOUT_DIRECTION_LTR:
17249            default:
17250                mUserPaddingLeftInitial = start;
17251                mUserPaddingRightInitial = end;
17252                internalSetPadding(start, top, end, bottom);
17253        }
17254    }
17255
17256    /**
17257     * Returns the top padding of this view.
17258     *
17259     * @return the top padding in pixels
17260     */
17261    public int getPaddingTop() {
17262        return mPaddingTop;
17263    }
17264
17265    /**
17266     * Returns the bottom padding of this view. If there are inset and enabled
17267     * scrollbars, this value may include the space required to display the
17268     * scrollbars as well.
17269     *
17270     * @return the bottom padding in pixels
17271     */
17272    public int getPaddingBottom() {
17273        return mPaddingBottom;
17274    }
17275
17276    /**
17277     * Returns the left padding of this view. If there are inset and enabled
17278     * scrollbars, this value may include the space required to display the
17279     * scrollbars as well.
17280     *
17281     * @return the left padding in pixels
17282     */
17283    public int getPaddingLeft() {
17284        if (!isPaddingResolved()) {
17285            resolvePadding();
17286        }
17287        return mPaddingLeft;
17288    }
17289
17290    /**
17291     * Returns the start padding of this view depending on its resolved layout direction.
17292     * If there are inset and enabled scrollbars, this value may include the space
17293     * required to display the scrollbars as well.
17294     *
17295     * @return the start padding in pixels
17296     */
17297    public int getPaddingStart() {
17298        if (!isPaddingResolved()) {
17299            resolvePadding();
17300        }
17301        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17302                mPaddingRight : mPaddingLeft;
17303    }
17304
17305    /**
17306     * Returns the right padding of this view. If there are inset and enabled
17307     * scrollbars, this value may include the space required to display the
17308     * scrollbars as well.
17309     *
17310     * @return the right padding in pixels
17311     */
17312    public int getPaddingRight() {
17313        if (!isPaddingResolved()) {
17314            resolvePadding();
17315        }
17316        return mPaddingRight;
17317    }
17318
17319    /**
17320     * Returns the end padding of this view depending on its resolved layout direction.
17321     * If there are inset and enabled scrollbars, this value may include the space
17322     * required to display the scrollbars as well.
17323     *
17324     * @return the end padding in pixels
17325     */
17326    public int getPaddingEnd() {
17327        if (!isPaddingResolved()) {
17328            resolvePadding();
17329        }
17330        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17331                mPaddingLeft : mPaddingRight;
17332    }
17333
17334    /**
17335     * Return if the padding has been set through relative values
17336     * {@link #setPaddingRelative(int, int, int, int)} or through
17337     * @attr ref android.R.styleable#View_paddingStart or
17338     * @attr ref android.R.styleable#View_paddingEnd
17339     *
17340     * @return true if the padding is relative or false if it is not.
17341     */
17342    public boolean isPaddingRelative() {
17343        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17344    }
17345
17346    Insets computeOpticalInsets() {
17347        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17348    }
17349
17350    /**
17351     * @hide
17352     */
17353    public void resetPaddingToInitialValues() {
17354        if (isRtlCompatibilityMode()) {
17355            mPaddingLeft = mUserPaddingLeftInitial;
17356            mPaddingRight = mUserPaddingRightInitial;
17357            return;
17358        }
17359        if (isLayoutRtl()) {
17360            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17361            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17362        } else {
17363            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17364            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17365        }
17366    }
17367
17368    /**
17369     * @hide
17370     */
17371    public Insets getOpticalInsets() {
17372        if (mLayoutInsets == null) {
17373            mLayoutInsets = computeOpticalInsets();
17374        }
17375        return mLayoutInsets;
17376    }
17377
17378    /**
17379     * Set this view's optical insets.
17380     *
17381     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17382     * property. Views that compute their own optical insets should call it as part of measurement.
17383     * This method does not request layout. If you are setting optical insets outside of
17384     * measure/layout itself you will want to call requestLayout() yourself.
17385     * </p>
17386     * @hide
17387     */
17388    public void setOpticalInsets(Insets insets) {
17389        mLayoutInsets = insets;
17390    }
17391
17392    /**
17393     * Changes the selection state of this view. A view can be selected or not.
17394     * Note that selection is not the same as focus. Views are typically
17395     * selected in the context of an AdapterView like ListView or GridView;
17396     * the selected view is the view that is highlighted.
17397     *
17398     * @param selected true if the view must be selected, false otherwise
17399     */
17400    public void setSelected(boolean selected) {
17401        //noinspection DoubleNegation
17402        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17403            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17404            if (!selected) resetPressedState();
17405            invalidate(true);
17406            refreshDrawableState();
17407            dispatchSetSelected(selected);
17408            if (selected) {
17409                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17410            } else {
17411                notifyViewAccessibilityStateChangedIfNeeded(
17412                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17413            }
17414        }
17415    }
17416
17417    /**
17418     * Dispatch setSelected to all of this View's children.
17419     *
17420     * @see #setSelected(boolean)
17421     *
17422     * @param selected The new selected state
17423     */
17424    protected void dispatchSetSelected(boolean selected) {
17425    }
17426
17427    /**
17428     * Indicates the selection state of this view.
17429     *
17430     * @return true if the view is selected, false otherwise
17431     */
17432    @ViewDebug.ExportedProperty
17433    public boolean isSelected() {
17434        return (mPrivateFlags & PFLAG_SELECTED) != 0;
17435    }
17436
17437    /**
17438     * Changes the activated state of this view. A view can be activated or not.
17439     * Note that activation is not the same as selection.  Selection is
17440     * a transient property, representing the view (hierarchy) the user is
17441     * currently interacting with.  Activation is a longer-term state that the
17442     * user can move views in and out of.  For example, in a list view with
17443     * single or multiple selection enabled, the views in the current selection
17444     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
17445     * here.)  The activated state is propagated down to children of the view it
17446     * is set on.
17447     *
17448     * @param activated true if the view must be activated, false otherwise
17449     */
17450    public void setActivated(boolean activated) {
17451        //noinspection DoubleNegation
17452        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
17453            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
17454            invalidate(true);
17455            refreshDrawableState();
17456            dispatchSetActivated(activated);
17457        }
17458    }
17459
17460    /**
17461     * Dispatch setActivated to all of this View's children.
17462     *
17463     * @see #setActivated(boolean)
17464     *
17465     * @param activated The new activated state
17466     */
17467    protected void dispatchSetActivated(boolean activated) {
17468    }
17469
17470    /**
17471     * Indicates the activation state of this view.
17472     *
17473     * @return true if the view is activated, false otherwise
17474     */
17475    @ViewDebug.ExportedProperty
17476    public boolean isActivated() {
17477        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
17478    }
17479
17480    /**
17481     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
17482     * observer can be used to get notifications when global events, like
17483     * layout, happen.
17484     *
17485     * The returned ViewTreeObserver observer is not guaranteed to remain
17486     * valid for the lifetime of this View. If the caller of this method keeps
17487     * a long-lived reference to ViewTreeObserver, it should always check for
17488     * the return value of {@link ViewTreeObserver#isAlive()}.
17489     *
17490     * @return The ViewTreeObserver for this view's hierarchy.
17491     */
17492    public ViewTreeObserver getViewTreeObserver() {
17493        if (mAttachInfo != null) {
17494            return mAttachInfo.mTreeObserver;
17495        }
17496        if (mFloatingTreeObserver == null) {
17497            mFloatingTreeObserver = new ViewTreeObserver();
17498        }
17499        return mFloatingTreeObserver;
17500    }
17501
17502    /**
17503     * <p>Finds the topmost view in the current view hierarchy.</p>
17504     *
17505     * @return the topmost view containing this view
17506     */
17507    public View getRootView() {
17508        if (mAttachInfo != null) {
17509            final View v = mAttachInfo.mRootView;
17510            if (v != null) {
17511                return v;
17512            }
17513        }
17514
17515        View parent = this;
17516
17517        while (parent.mParent != null && parent.mParent instanceof View) {
17518            parent = (View) parent.mParent;
17519        }
17520
17521        return parent;
17522    }
17523
17524    /**
17525     * Transforms a motion event from view-local coordinates to on-screen
17526     * coordinates.
17527     *
17528     * @param ev the view-local motion event
17529     * @return false if the transformation could not be applied
17530     * @hide
17531     */
17532    public boolean toGlobalMotionEvent(MotionEvent ev) {
17533        final AttachInfo info = mAttachInfo;
17534        if (info == null) {
17535            return false;
17536        }
17537
17538        final Matrix m = info.mTmpMatrix;
17539        m.set(Matrix.IDENTITY_MATRIX);
17540        transformMatrixToGlobal(m);
17541        ev.transform(m);
17542        return true;
17543    }
17544
17545    /**
17546     * Transforms a motion event from on-screen coordinates to view-local
17547     * coordinates.
17548     *
17549     * @param ev the on-screen motion event
17550     * @return false if the transformation could not be applied
17551     * @hide
17552     */
17553    public boolean toLocalMotionEvent(MotionEvent ev) {
17554        final AttachInfo info = mAttachInfo;
17555        if (info == null) {
17556            return false;
17557        }
17558
17559        final Matrix m = info.mTmpMatrix;
17560        m.set(Matrix.IDENTITY_MATRIX);
17561        transformMatrixToLocal(m);
17562        ev.transform(m);
17563        return true;
17564    }
17565
17566    /**
17567     * Modifies the input matrix such that it maps view-local coordinates to
17568     * on-screen coordinates.
17569     *
17570     * @param m input matrix to modify
17571     * @hide
17572     */
17573    public void transformMatrixToGlobal(Matrix m) {
17574        final ViewParent parent = mParent;
17575        if (parent instanceof View) {
17576            final View vp = (View) parent;
17577            vp.transformMatrixToGlobal(m);
17578            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
17579        } else if (parent instanceof ViewRootImpl) {
17580            final ViewRootImpl vr = (ViewRootImpl) parent;
17581            vr.transformMatrixToGlobal(m);
17582            m.preTranslate(0, -vr.mCurScrollY);
17583        }
17584
17585        m.preTranslate(mLeft, mTop);
17586
17587        if (!hasIdentityMatrix()) {
17588            m.preConcat(getMatrix());
17589        }
17590    }
17591
17592    /**
17593     * Modifies the input matrix such that it maps on-screen coordinates to
17594     * view-local coordinates.
17595     *
17596     * @param m input matrix to modify
17597     * @hide
17598     */
17599    public void transformMatrixToLocal(Matrix m) {
17600        final ViewParent parent = mParent;
17601        if (parent instanceof View) {
17602            final View vp = (View) parent;
17603            vp.transformMatrixToLocal(m);
17604            m.postTranslate(vp.mScrollX, vp.mScrollY);
17605        } else if (parent instanceof ViewRootImpl) {
17606            final ViewRootImpl vr = (ViewRootImpl) parent;
17607            vr.transformMatrixToLocal(m);
17608            m.postTranslate(0, vr.mCurScrollY);
17609        }
17610
17611        m.postTranslate(-mLeft, -mTop);
17612
17613        if (!hasIdentityMatrix()) {
17614            m.postConcat(getInverseMatrix());
17615        }
17616    }
17617
17618    /**
17619     * @hide
17620     */
17621    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
17622            @ViewDebug.IntToString(from = 0, to = "x"),
17623            @ViewDebug.IntToString(from = 1, to = "y")
17624    })
17625    public int[] getLocationOnScreen() {
17626        int[] location = new int[2];
17627        getLocationOnScreen(location);
17628        return location;
17629    }
17630
17631    /**
17632     * <p>Computes the coordinates of this view on the screen. The argument
17633     * must be an array of two integers. After the method returns, the array
17634     * contains the x and y location in that order.</p>
17635     *
17636     * @param location an array of two integers in which to hold the coordinates
17637     */
17638    public void getLocationOnScreen(@Size(2) int[] location) {
17639        getLocationInWindow(location);
17640
17641        final AttachInfo info = mAttachInfo;
17642        if (info != null) {
17643            location[0] += info.mWindowLeft;
17644            location[1] += info.mWindowTop;
17645        }
17646    }
17647
17648    /**
17649     * <p>Computes the coordinates of this view in its window. The argument
17650     * must be an array of two integers. After the method returns, the array
17651     * contains the x and y location in that order.</p>
17652     *
17653     * @param location an array of two integers in which to hold the coordinates
17654     */
17655    public void getLocationInWindow(@Size(2) int[] location) {
17656        if (location == null || location.length < 2) {
17657            throw new IllegalArgumentException("location must be an array of two integers");
17658        }
17659
17660        if (mAttachInfo == null) {
17661            // When the view is not attached to a window, this method does not make sense
17662            location[0] = location[1] = 0;
17663            return;
17664        }
17665
17666        float[] position = mAttachInfo.mTmpTransformLocation;
17667        position[0] = position[1] = 0.0f;
17668
17669        if (!hasIdentityMatrix()) {
17670            getMatrix().mapPoints(position);
17671        }
17672
17673        position[0] += mLeft;
17674        position[1] += mTop;
17675
17676        ViewParent viewParent = mParent;
17677        while (viewParent instanceof View) {
17678            final View view = (View) viewParent;
17679
17680            position[0] -= view.mScrollX;
17681            position[1] -= view.mScrollY;
17682
17683            if (!view.hasIdentityMatrix()) {
17684                view.getMatrix().mapPoints(position);
17685            }
17686
17687            position[0] += view.mLeft;
17688            position[1] += view.mTop;
17689
17690            viewParent = view.mParent;
17691         }
17692
17693        if (viewParent instanceof ViewRootImpl) {
17694            // *cough*
17695            final ViewRootImpl vr = (ViewRootImpl) viewParent;
17696            position[1] -= vr.mCurScrollY;
17697        }
17698
17699        location[0] = (int) (position[0] + 0.5f);
17700        location[1] = (int) (position[1] + 0.5f);
17701    }
17702
17703    /**
17704     * {@hide}
17705     * @param id the id of the view to be found
17706     * @return the view of the specified id, null if cannot be found
17707     */
17708    protected View findViewTraversal(@IdRes int id) {
17709        if (id == mID) {
17710            return this;
17711        }
17712        return null;
17713    }
17714
17715    /**
17716     * {@hide}
17717     * @param tag the tag of the view to be found
17718     * @return the view of specified tag, null if cannot be found
17719     */
17720    protected View findViewWithTagTraversal(Object tag) {
17721        if (tag != null && tag.equals(mTag)) {
17722            return this;
17723        }
17724        return null;
17725    }
17726
17727    /**
17728     * {@hide}
17729     * @param predicate The predicate to evaluate.
17730     * @param childToSkip If not null, ignores this child during the recursive traversal.
17731     * @return The first view that matches the predicate or null.
17732     */
17733    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
17734        if (predicate.apply(this)) {
17735            return this;
17736        }
17737        return null;
17738    }
17739
17740    /**
17741     * Look for a child view with the given id.  If this view has the given
17742     * id, return this view.
17743     *
17744     * @param id The id to search for.
17745     * @return The view that has the given id in the hierarchy or null
17746     */
17747    @Nullable
17748    public final View findViewById(@IdRes int id) {
17749        if (id < 0) {
17750            return null;
17751        }
17752        return findViewTraversal(id);
17753    }
17754
17755    /**
17756     * Finds a view by its unuque and stable accessibility id.
17757     *
17758     * @param accessibilityId The searched accessibility id.
17759     * @return The found view.
17760     */
17761    final View findViewByAccessibilityId(int accessibilityId) {
17762        if (accessibilityId < 0) {
17763            return null;
17764        }
17765        return findViewByAccessibilityIdTraversal(accessibilityId);
17766    }
17767
17768    /**
17769     * Performs the traversal to find a view by its unuque and stable accessibility id.
17770     *
17771     * <strong>Note:</strong>This method does not stop at the root namespace
17772     * boundary since the user can touch the screen at an arbitrary location
17773     * potentially crossing the root namespace bounday which will send an
17774     * accessibility event to accessibility services and they should be able
17775     * to obtain the event source. Also accessibility ids are guaranteed to be
17776     * unique in the window.
17777     *
17778     * @param accessibilityId The accessibility id.
17779     * @return The found view.
17780     *
17781     * @hide
17782     */
17783    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17784        if (getAccessibilityViewId() == accessibilityId) {
17785            return this;
17786        }
17787        return null;
17788    }
17789
17790    /**
17791     * Look for a child view with the given tag.  If this view has the given
17792     * tag, return this view.
17793     *
17794     * @param tag The tag to search for, using "tag.equals(getTag())".
17795     * @return The View that has the given tag in the hierarchy or null
17796     */
17797    public final View findViewWithTag(Object tag) {
17798        if (tag == null) {
17799            return null;
17800        }
17801        return findViewWithTagTraversal(tag);
17802    }
17803
17804    /**
17805     * {@hide}
17806     * Look for a child view that matches the specified predicate.
17807     * If this view matches the predicate, return this view.
17808     *
17809     * @param predicate The predicate to evaluate.
17810     * @return The first view that matches the predicate or null.
17811     */
17812    public final View findViewByPredicate(Predicate<View> predicate) {
17813        return findViewByPredicateTraversal(predicate, null);
17814    }
17815
17816    /**
17817     * {@hide}
17818     * Look for a child view that matches the specified predicate,
17819     * starting with the specified view and its descendents and then
17820     * recusively searching the ancestors and siblings of that view
17821     * until this view is reached.
17822     *
17823     * This method is useful in cases where the predicate does not match
17824     * a single unique view (perhaps multiple views use the same id)
17825     * and we are trying to find the view that is "closest" in scope to the
17826     * starting view.
17827     *
17828     * @param start The view to start from.
17829     * @param predicate The predicate to evaluate.
17830     * @return The first view that matches the predicate or null.
17831     */
17832    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17833        View childToSkip = null;
17834        for (;;) {
17835            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17836            if (view != null || start == this) {
17837                return view;
17838            }
17839
17840            ViewParent parent = start.getParent();
17841            if (parent == null || !(parent instanceof View)) {
17842                return null;
17843            }
17844
17845            childToSkip = start;
17846            start = (View) parent;
17847        }
17848    }
17849
17850    /**
17851     * Sets the identifier for this view. The identifier does not have to be
17852     * unique in this view's hierarchy. The identifier should be a positive
17853     * number.
17854     *
17855     * @see #NO_ID
17856     * @see #getId()
17857     * @see #findViewById(int)
17858     *
17859     * @param id a number used to identify the view
17860     *
17861     * @attr ref android.R.styleable#View_id
17862     */
17863    public void setId(@IdRes int id) {
17864        mID = id;
17865        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17866            mID = generateViewId();
17867        }
17868    }
17869
17870    /**
17871     * {@hide}
17872     *
17873     * @param isRoot true if the view belongs to the root namespace, false
17874     *        otherwise
17875     */
17876    public void setIsRootNamespace(boolean isRoot) {
17877        if (isRoot) {
17878            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17879        } else {
17880            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17881        }
17882    }
17883
17884    /**
17885     * {@hide}
17886     *
17887     * @return true if the view belongs to the root namespace, false otherwise
17888     */
17889    public boolean isRootNamespace() {
17890        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17891    }
17892
17893    /**
17894     * Returns this view's identifier.
17895     *
17896     * @return a positive integer used to identify the view or {@link #NO_ID}
17897     *         if the view has no ID
17898     *
17899     * @see #setId(int)
17900     * @see #findViewById(int)
17901     * @attr ref android.R.styleable#View_id
17902     */
17903    @IdRes
17904    @ViewDebug.CapturedViewProperty
17905    public int getId() {
17906        return mID;
17907    }
17908
17909    /**
17910     * Returns this view's tag.
17911     *
17912     * @return the Object stored in this view as a tag, or {@code null} if not
17913     *         set
17914     *
17915     * @see #setTag(Object)
17916     * @see #getTag(int)
17917     */
17918    @ViewDebug.ExportedProperty
17919    public Object getTag() {
17920        return mTag;
17921    }
17922
17923    /**
17924     * Sets the tag associated with this view. A tag can be used to mark
17925     * a view in its hierarchy and does not have to be unique within the
17926     * hierarchy. Tags can also be used to store data within a view without
17927     * resorting to another data structure.
17928     *
17929     * @param tag an Object to tag the view with
17930     *
17931     * @see #getTag()
17932     * @see #setTag(int, Object)
17933     */
17934    public void setTag(final Object tag) {
17935        mTag = tag;
17936    }
17937
17938    /**
17939     * Returns the tag associated with this view and the specified key.
17940     *
17941     * @param key The key identifying the tag
17942     *
17943     * @return the Object stored in this view as a tag, or {@code null} if not
17944     *         set
17945     *
17946     * @see #setTag(int, Object)
17947     * @see #getTag()
17948     */
17949    public Object getTag(int key) {
17950        if (mKeyedTags != null) return mKeyedTags.get(key);
17951        return null;
17952    }
17953
17954    /**
17955     * Sets a tag associated with this view and a key. A tag can be used
17956     * to mark a view in its hierarchy and does not have to be unique within
17957     * the hierarchy. Tags can also be used to store data within a view
17958     * without resorting to another data structure.
17959     *
17960     * The specified key should be an id declared in the resources of the
17961     * application to ensure it is unique (see the <a
17962     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17963     * Keys identified as belonging to
17964     * the Android framework or not associated with any package will cause
17965     * an {@link IllegalArgumentException} to be thrown.
17966     *
17967     * @param key The key identifying the tag
17968     * @param tag An Object to tag the view with
17969     *
17970     * @throws IllegalArgumentException If they specified key is not valid
17971     *
17972     * @see #setTag(Object)
17973     * @see #getTag(int)
17974     */
17975    public void setTag(int key, final Object tag) {
17976        // If the package id is 0x00 or 0x01, it's either an undefined package
17977        // or a framework id
17978        if ((key >>> 24) < 2) {
17979            throw new IllegalArgumentException("The key must be an application-specific "
17980                    + "resource id.");
17981        }
17982
17983        setKeyedTag(key, tag);
17984    }
17985
17986    /**
17987     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17988     * framework id.
17989     *
17990     * @hide
17991     */
17992    public void setTagInternal(int key, Object tag) {
17993        if ((key >>> 24) != 0x1) {
17994            throw new IllegalArgumentException("The key must be a framework-specific "
17995                    + "resource id.");
17996        }
17997
17998        setKeyedTag(key, tag);
17999    }
18000
18001    private void setKeyedTag(int key, Object tag) {
18002        if (mKeyedTags == null) {
18003            mKeyedTags = new SparseArray<Object>(2);
18004        }
18005
18006        mKeyedTags.put(key, tag);
18007    }
18008
18009    /**
18010     * Prints information about this view in the log output, with the tag
18011     * {@link #VIEW_LOG_TAG}.
18012     *
18013     * @hide
18014     */
18015    public void debug() {
18016        debug(0);
18017    }
18018
18019    /**
18020     * Prints information about this view in the log output, with the tag
18021     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18022     * indentation defined by the <code>depth</code>.
18023     *
18024     * @param depth the indentation level
18025     *
18026     * @hide
18027     */
18028    protected void debug(int depth) {
18029        String output = debugIndent(depth - 1);
18030
18031        output += "+ " + this;
18032        int id = getId();
18033        if (id != -1) {
18034            output += " (id=" + id + ")";
18035        }
18036        Object tag = getTag();
18037        if (tag != null) {
18038            output += " (tag=" + tag + ")";
18039        }
18040        Log.d(VIEW_LOG_TAG, output);
18041
18042        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18043            output = debugIndent(depth) + " FOCUSED";
18044            Log.d(VIEW_LOG_TAG, output);
18045        }
18046
18047        output = debugIndent(depth);
18048        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18049                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18050                + "} ";
18051        Log.d(VIEW_LOG_TAG, output);
18052
18053        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18054                || mPaddingBottom != 0) {
18055            output = debugIndent(depth);
18056            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18057                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18058            Log.d(VIEW_LOG_TAG, output);
18059        }
18060
18061        output = debugIndent(depth);
18062        output += "mMeasureWidth=" + mMeasuredWidth +
18063                " mMeasureHeight=" + mMeasuredHeight;
18064        Log.d(VIEW_LOG_TAG, output);
18065
18066        output = debugIndent(depth);
18067        if (mLayoutParams == null) {
18068            output += "BAD! no layout params";
18069        } else {
18070            output = mLayoutParams.debug(output);
18071        }
18072        Log.d(VIEW_LOG_TAG, output);
18073
18074        output = debugIndent(depth);
18075        output += "flags={";
18076        output += View.printFlags(mViewFlags);
18077        output += "}";
18078        Log.d(VIEW_LOG_TAG, output);
18079
18080        output = debugIndent(depth);
18081        output += "privateFlags={";
18082        output += View.printPrivateFlags(mPrivateFlags);
18083        output += "}";
18084        Log.d(VIEW_LOG_TAG, output);
18085    }
18086
18087    /**
18088     * Creates a string of whitespaces used for indentation.
18089     *
18090     * @param depth the indentation level
18091     * @return a String containing (depth * 2 + 3) * 2 white spaces
18092     *
18093     * @hide
18094     */
18095    protected static String debugIndent(int depth) {
18096        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18097        for (int i = 0; i < (depth * 2) + 3; i++) {
18098            spaces.append(' ').append(' ');
18099        }
18100        return spaces.toString();
18101    }
18102
18103    /**
18104     * <p>Return the offset of the widget's text baseline from the widget's top
18105     * boundary. If this widget does not support baseline alignment, this
18106     * method returns -1. </p>
18107     *
18108     * @return the offset of the baseline within the widget's bounds or -1
18109     *         if baseline alignment is not supported
18110     */
18111    @ViewDebug.ExportedProperty(category = "layout")
18112    public int getBaseline() {
18113        return -1;
18114    }
18115
18116    /**
18117     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18118     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18119     * a layout pass.
18120     *
18121     * @return whether the view hierarchy is currently undergoing a layout pass
18122     */
18123    public boolean isInLayout() {
18124        ViewRootImpl viewRoot = getViewRootImpl();
18125        return (viewRoot != null && viewRoot.isInLayout());
18126    }
18127
18128    /**
18129     * Call this when something has changed which has invalidated the
18130     * layout of this view. This will schedule a layout pass of the view
18131     * tree. This should not be called while the view hierarchy is currently in a layout
18132     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18133     * end of the current layout pass (and then layout will run again) or after the current
18134     * frame is drawn and the next layout occurs.
18135     *
18136     * <p>Subclasses which override this method should call the superclass method to
18137     * handle possible request-during-layout errors correctly.</p>
18138     */
18139    @CallSuper
18140    public void requestLayout() {
18141        if (mMeasureCache != null) mMeasureCache.clear();
18142
18143        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18144            // Only trigger request-during-layout logic if this is the view requesting it,
18145            // not the views in its parent hierarchy
18146            ViewRootImpl viewRoot = getViewRootImpl();
18147            if (viewRoot != null && viewRoot.isInLayout()) {
18148                if (!viewRoot.requestLayoutDuringLayout(this)) {
18149                    return;
18150                }
18151            }
18152            mAttachInfo.mViewRequestingLayout = this;
18153        }
18154
18155        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18156        mPrivateFlags |= PFLAG_INVALIDATED;
18157
18158        if (mParent != null && !mParent.isLayoutRequested()) {
18159            mParent.requestLayout();
18160        }
18161        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18162            mAttachInfo.mViewRequestingLayout = null;
18163        }
18164    }
18165
18166    /**
18167     * Forces this view to be laid out during the next layout pass.
18168     * This method does not call requestLayout() or forceLayout()
18169     * on the parent.
18170     */
18171    public void forceLayout() {
18172        if (mMeasureCache != null) mMeasureCache.clear();
18173
18174        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18175        mPrivateFlags |= PFLAG_INVALIDATED;
18176    }
18177
18178    /**
18179     * <p>
18180     * This is called to find out how big a view should be. The parent
18181     * supplies constraint information in the width and height parameters.
18182     * </p>
18183     *
18184     * <p>
18185     * The actual measurement work of a view is performed in
18186     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18187     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18188     * </p>
18189     *
18190     *
18191     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18192     *        parent
18193     * @param heightMeasureSpec Vertical space requirements as imposed by the
18194     *        parent
18195     *
18196     * @see #onMeasure(int, int)
18197     */
18198    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18199        boolean optical = isLayoutModeOptical(this);
18200        if (optical != isLayoutModeOptical(mParent)) {
18201            Insets insets = getOpticalInsets();
18202            int oWidth  = insets.left + insets.right;
18203            int oHeight = insets.top  + insets.bottom;
18204            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18205            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18206        }
18207
18208        // Suppress sign extension for the low bytes
18209        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18210        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18211
18212        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18213        final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
18214                MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
18215        final boolean matchingSize = isExactly &&
18216                getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
18217                getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
18218        if (forceLayout || !matchingSize &&
18219                (widthMeasureSpec != mOldWidthMeasureSpec ||
18220                        heightMeasureSpec != mOldHeightMeasureSpec)) {
18221
18222            // first clears the measured dimension flag
18223            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18224
18225            resolveRtlPropertiesIfNeeded();
18226
18227            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
18228            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18229                // measure ourselves, this should set the measured dimension flag back
18230                onMeasure(widthMeasureSpec, heightMeasureSpec);
18231                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18232            } else {
18233                long value = mMeasureCache.valueAt(cacheIndex);
18234                // Casting a long to int drops the high 32 bits, no mask needed
18235                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18236                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18237            }
18238
18239            // flag not set, setMeasuredDimension() was not invoked, we raise
18240            // an exception to warn the developer
18241            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18242                throw new IllegalStateException("View with id " + getId() + ": "
18243                        + getClass().getName() + "#onMeasure() did not set the"
18244                        + " measured dimension by calling"
18245                        + " setMeasuredDimension()");
18246            }
18247
18248            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18249        }
18250
18251        mOldWidthMeasureSpec = widthMeasureSpec;
18252        mOldHeightMeasureSpec = heightMeasureSpec;
18253
18254        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18255                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18256    }
18257
18258    /**
18259     * <p>
18260     * Measure the view and its content to determine the measured width and the
18261     * measured height. This method is invoked by {@link #measure(int, int)} and
18262     * should be overridden by subclasses to provide accurate and efficient
18263     * measurement of their contents.
18264     * </p>
18265     *
18266     * <p>
18267     * <strong>CONTRACT:</strong> When overriding this method, you
18268     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18269     * measured width and height of this view. Failure to do so will trigger an
18270     * <code>IllegalStateException</code>, thrown by
18271     * {@link #measure(int, int)}. Calling the superclass'
18272     * {@link #onMeasure(int, int)} is a valid use.
18273     * </p>
18274     *
18275     * <p>
18276     * The base class implementation of measure defaults to the background size,
18277     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18278     * override {@link #onMeasure(int, int)} to provide better measurements of
18279     * their content.
18280     * </p>
18281     *
18282     * <p>
18283     * If this method is overridden, it is the subclass's responsibility to make
18284     * sure the measured height and width are at least the view's minimum height
18285     * and width ({@link #getSuggestedMinimumHeight()} and
18286     * {@link #getSuggestedMinimumWidth()}).
18287     * </p>
18288     *
18289     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18290     *                         The requirements are encoded with
18291     *                         {@link android.view.View.MeasureSpec}.
18292     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18293     *                         The requirements are encoded with
18294     *                         {@link android.view.View.MeasureSpec}.
18295     *
18296     * @see #getMeasuredWidth()
18297     * @see #getMeasuredHeight()
18298     * @see #setMeasuredDimension(int, int)
18299     * @see #getSuggestedMinimumHeight()
18300     * @see #getSuggestedMinimumWidth()
18301     * @see android.view.View.MeasureSpec#getMode(int)
18302     * @see android.view.View.MeasureSpec#getSize(int)
18303     */
18304    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18305        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18306                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18307    }
18308
18309    /**
18310     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18311     * measured width and measured height. Failing to do so will trigger an
18312     * exception at measurement time.</p>
18313     *
18314     * @param measuredWidth The measured width of this view.  May be a complex
18315     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18316     * {@link #MEASURED_STATE_TOO_SMALL}.
18317     * @param measuredHeight The measured height of this view.  May be a complex
18318     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18319     * {@link #MEASURED_STATE_TOO_SMALL}.
18320     */
18321    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18322        boolean optical = isLayoutModeOptical(this);
18323        if (optical != isLayoutModeOptical(mParent)) {
18324            Insets insets = getOpticalInsets();
18325            int opticalWidth  = insets.left + insets.right;
18326            int opticalHeight = insets.top  + insets.bottom;
18327
18328            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18329            measuredHeight += optical ? opticalHeight : -opticalHeight;
18330        }
18331        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18332    }
18333
18334    /**
18335     * Sets the measured dimension without extra processing for things like optical bounds.
18336     * Useful for reapplying consistent values that have already been cooked with adjustments
18337     * for optical bounds, etc. such as those from the measurement cache.
18338     *
18339     * @param measuredWidth The measured width of this view.  May be a complex
18340     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18341     * {@link #MEASURED_STATE_TOO_SMALL}.
18342     * @param measuredHeight The measured height of this view.  May be a complex
18343     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18344     * {@link #MEASURED_STATE_TOO_SMALL}.
18345     */
18346    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18347        mMeasuredWidth = measuredWidth;
18348        mMeasuredHeight = measuredHeight;
18349
18350        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18351    }
18352
18353    /**
18354     * Merge two states as returned by {@link #getMeasuredState()}.
18355     * @param curState The current state as returned from a view or the result
18356     * of combining multiple views.
18357     * @param newState The new view state to combine.
18358     * @return Returns a new integer reflecting the combination of the two
18359     * states.
18360     */
18361    public static int combineMeasuredStates(int curState, int newState) {
18362        return curState | newState;
18363    }
18364
18365    /**
18366     * Version of {@link #resolveSizeAndState(int, int, int)}
18367     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18368     */
18369    public static int resolveSize(int size, int measureSpec) {
18370        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18371    }
18372
18373    /**
18374     * Utility to reconcile a desired size and state, with constraints imposed
18375     * by a MeasureSpec. Will take the desired size, unless a different size
18376     * is imposed by the constraints. The returned value is a compound integer,
18377     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18378     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18379     * resulting size is smaller than the size the view wants to be.
18380     *
18381     * @param size How big the view wants to be.
18382     * @param measureSpec Constraints imposed by the parent.
18383     * @param childMeasuredState Size information bit mask for the view's
18384     *                           children.
18385     * @return Size information bit mask as defined by
18386     *         {@link #MEASURED_SIZE_MASK} and
18387     *         {@link #MEASURED_STATE_TOO_SMALL}.
18388     */
18389    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18390        final int specMode = MeasureSpec.getMode(measureSpec);
18391        final int specSize = MeasureSpec.getSize(measureSpec);
18392        final int result;
18393        switch (specMode) {
18394            case MeasureSpec.AT_MOST:
18395                if (specSize < size) {
18396                    result = specSize | MEASURED_STATE_TOO_SMALL;
18397                } else {
18398                    result = size;
18399                }
18400                break;
18401            case MeasureSpec.EXACTLY:
18402                result = specSize;
18403                break;
18404            case MeasureSpec.UNSPECIFIED:
18405            default:
18406                result = size;
18407        }
18408        return result | (childMeasuredState & MEASURED_STATE_MASK);
18409    }
18410
18411    /**
18412     * Utility to return a default size. Uses the supplied size if the
18413     * MeasureSpec imposed no constraints. Will get larger if allowed
18414     * by the MeasureSpec.
18415     *
18416     * @param size Default size for this view
18417     * @param measureSpec Constraints imposed by the parent
18418     * @return The size this view should be.
18419     */
18420    public static int getDefaultSize(int size, int measureSpec) {
18421        int result = size;
18422        int specMode = MeasureSpec.getMode(measureSpec);
18423        int specSize = MeasureSpec.getSize(measureSpec);
18424
18425        switch (specMode) {
18426        case MeasureSpec.UNSPECIFIED:
18427            result = size;
18428            break;
18429        case MeasureSpec.AT_MOST:
18430        case MeasureSpec.EXACTLY:
18431            result = specSize;
18432            break;
18433        }
18434        return result;
18435    }
18436
18437    /**
18438     * Returns the suggested minimum height that the view should use. This
18439     * returns the maximum of the view's minimum height
18440     * and the background's minimum height
18441     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
18442     * <p>
18443     * When being used in {@link #onMeasure(int, int)}, the caller should still
18444     * ensure the returned height is within the requirements of the parent.
18445     *
18446     * @return The suggested minimum height of the view.
18447     */
18448    protected int getSuggestedMinimumHeight() {
18449        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
18450
18451    }
18452
18453    /**
18454     * Returns the suggested minimum width that the view should use. This
18455     * returns the maximum of the view's minimum width)
18456     * and the background's minimum width
18457     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
18458     * <p>
18459     * When being used in {@link #onMeasure(int, int)}, the caller should still
18460     * ensure the returned width is within the requirements of the parent.
18461     *
18462     * @return The suggested minimum width of the view.
18463     */
18464    protected int getSuggestedMinimumWidth() {
18465        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
18466    }
18467
18468    /**
18469     * Returns the minimum height of the view.
18470     *
18471     * @return the minimum height the view will try to be.
18472     *
18473     * @see #setMinimumHeight(int)
18474     *
18475     * @attr ref android.R.styleable#View_minHeight
18476     */
18477    public int getMinimumHeight() {
18478        return mMinHeight;
18479    }
18480
18481    /**
18482     * Sets the minimum height of the view. It is not guaranteed the view will
18483     * be able to achieve this minimum height (for example, if its parent layout
18484     * constrains it with less available height).
18485     *
18486     * @param minHeight The minimum height the view will try to be.
18487     *
18488     * @see #getMinimumHeight()
18489     *
18490     * @attr ref android.R.styleable#View_minHeight
18491     */
18492    public void setMinimumHeight(int minHeight) {
18493        mMinHeight = minHeight;
18494        requestLayout();
18495    }
18496
18497    /**
18498     * Returns the minimum width of the view.
18499     *
18500     * @return the minimum width the view will try to be.
18501     *
18502     * @see #setMinimumWidth(int)
18503     *
18504     * @attr ref android.R.styleable#View_minWidth
18505     */
18506    public int getMinimumWidth() {
18507        return mMinWidth;
18508    }
18509
18510    /**
18511     * Sets the minimum width of the view. It is not guaranteed the view will
18512     * be able to achieve this minimum width (for example, if its parent layout
18513     * constrains it with less available width).
18514     *
18515     * @param minWidth The minimum width the view will try to be.
18516     *
18517     * @see #getMinimumWidth()
18518     *
18519     * @attr ref android.R.styleable#View_minWidth
18520     */
18521    public void setMinimumWidth(int minWidth) {
18522        mMinWidth = minWidth;
18523        requestLayout();
18524
18525    }
18526
18527    /**
18528     * Get the animation currently associated with this view.
18529     *
18530     * @return The animation that is currently playing or
18531     *         scheduled to play for this view.
18532     */
18533    public Animation getAnimation() {
18534        return mCurrentAnimation;
18535    }
18536
18537    /**
18538     * Start the specified animation now.
18539     *
18540     * @param animation the animation to start now
18541     */
18542    public void startAnimation(Animation animation) {
18543        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
18544        setAnimation(animation);
18545        invalidateParentCaches();
18546        invalidate(true);
18547    }
18548
18549    /**
18550     * Cancels any animations for this view.
18551     */
18552    public void clearAnimation() {
18553        if (mCurrentAnimation != null) {
18554            mCurrentAnimation.detach();
18555        }
18556        mCurrentAnimation = null;
18557        invalidateParentIfNeeded();
18558    }
18559
18560    /**
18561     * Sets the next animation to play for this view.
18562     * If you want the animation to play immediately, use
18563     * {@link #startAnimation(android.view.animation.Animation)} instead.
18564     * This method provides allows fine-grained
18565     * control over the start time and invalidation, but you
18566     * must make sure that 1) the animation has a start time set, and
18567     * 2) the view's parent (which controls animations on its children)
18568     * will be invalidated when the animation is supposed to
18569     * start.
18570     *
18571     * @param animation The next animation, or null.
18572     */
18573    public void setAnimation(Animation animation) {
18574        mCurrentAnimation = animation;
18575
18576        if (animation != null) {
18577            // If the screen is off assume the animation start time is now instead of
18578            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
18579            // would cause the animation to start when the screen turns back on
18580            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
18581                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
18582                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
18583            }
18584            animation.reset();
18585        }
18586    }
18587
18588    /**
18589     * Invoked by a parent ViewGroup to notify the start of the animation
18590     * currently associated with this view. If you override this method,
18591     * always call super.onAnimationStart();
18592     *
18593     * @see #setAnimation(android.view.animation.Animation)
18594     * @see #getAnimation()
18595     */
18596    @CallSuper
18597    protected void onAnimationStart() {
18598        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
18599    }
18600
18601    /**
18602     * Invoked by a parent ViewGroup to notify the end of the animation
18603     * currently associated with this view. If you override this method,
18604     * always call super.onAnimationEnd();
18605     *
18606     * @see #setAnimation(android.view.animation.Animation)
18607     * @see #getAnimation()
18608     */
18609    @CallSuper
18610    protected void onAnimationEnd() {
18611        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
18612    }
18613
18614    /**
18615     * Invoked if there is a Transform that involves alpha. Subclass that can
18616     * draw themselves with the specified alpha should return true, and then
18617     * respect that alpha when their onDraw() is called. If this returns false
18618     * then the view may be redirected to draw into an offscreen buffer to
18619     * fulfill the request, which will look fine, but may be slower than if the
18620     * subclass handles it internally. The default implementation returns false.
18621     *
18622     * @param alpha The alpha (0..255) to apply to the view's drawing
18623     * @return true if the view can draw with the specified alpha.
18624     */
18625    protected boolean onSetAlpha(int alpha) {
18626        return false;
18627    }
18628
18629    /**
18630     * This is used by the RootView to perform an optimization when
18631     * the view hierarchy contains one or several SurfaceView.
18632     * SurfaceView is always considered transparent, but its children are not,
18633     * therefore all View objects remove themselves from the global transparent
18634     * region (passed as a parameter to this function).
18635     *
18636     * @param region The transparent region for this ViewAncestor (window).
18637     *
18638     * @return Returns true if the effective visibility of the view at this
18639     * point is opaque, regardless of the transparent region; returns false
18640     * if it is possible for underlying windows to be seen behind the view.
18641     *
18642     * {@hide}
18643     */
18644    public boolean gatherTransparentRegion(Region region) {
18645        final AttachInfo attachInfo = mAttachInfo;
18646        if (region != null && attachInfo != null) {
18647            final int pflags = mPrivateFlags;
18648            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
18649                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
18650                // remove it from the transparent region.
18651                final int[] location = attachInfo.mTransparentLocation;
18652                getLocationInWindow(location);
18653                region.op(location[0], location[1], location[0] + mRight - mLeft,
18654                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
18655            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
18656                    mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
18657                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
18658                // exists, so we remove the background drawable's non-transparent
18659                // parts from this transparent region.
18660                applyDrawableToTransparentRegion(mBackground, region);
18661            }
18662            final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18663            if (foreground != null) {
18664                applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
18665            }
18666        }
18667        return true;
18668    }
18669
18670    /**
18671     * Play a sound effect for this view.
18672     *
18673     * <p>The framework will play sound effects for some built in actions, such as
18674     * clicking, but you may wish to play these effects in your widget,
18675     * for instance, for internal navigation.
18676     *
18677     * <p>The sound effect will only be played if sound effects are enabled by the user, and
18678     * {@link #isSoundEffectsEnabled()} is true.
18679     *
18680     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
18681     */
18682    public void playSoundEffect(int soundConstant) {
18683        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
18684            return;
18685        }
18686        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
18687    }
18688
18689    /**
18690     * BZZZTT!!1!
18691     *
18692     * <p>Provide haptic feedback to the user for this view.
18693     *
18694     * <p>The framework will provide haptic feedback for some built in actions,
18695     * such as long presses, but you may wish to provide feedback for your
18696     * own widget.
18697     *
18698     * <p>The feedback will only be performed if
18699     * {@link #isHapticFeedbackEnabled()} is true.
18700     *
18701     * @param feedbackConstant One of the constants defined in
18702     * {@link HapticFeedbackConstants}
18703     */
18704    public boolean performHapticFeedback(int feedbackConstant) {
18705        return performHapticFeedback(feedbackConstant, 0);
18706    }
18707
18708    /**
18709     * BZZZTT!!1!
18710     *
18711     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
18712     *
18713     * @param feedbackConstant One of the constants defined in
18714     * {@link HapticFeedbackConstants}
18715     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
18716     */
18717    public boolean performHapticFeedback(int feedbackConstant, int flags) {
18718        if (mAttachInfo == null) {
18719            return false;
18720        }
18721        //noinspection SimplifiableIfStatement
18722        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
18723                && !isHapticFeedbackEnabled()) {
18724            return false;
18725        }
18726        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
18727                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
18728    }
18729
18730    /**
18731     * Request that the visibility of the status bar or other screen/window
18732     * decorations be changed.
18733     *
18734     * <p>This method is used to put the over device UI into temporary modes
18735     * where the user's attention is focused more on the application content,
18736     * by dimming or hiding surrounding system affordances.  This is typically
18737     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
18738     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
18739     * to be placed behind the action bar (and with these flags other system
18740     * affordances) so that smooth transitions between hiding and showing them
18741     * can be done.
18742     *
18743     * <p>Two representative examples of the use of system UI visibility is
18744     * implementing a content browsing application (like a magazine reader)
18745     * and a video playing application.
18746     *
18747     * <p>The first code shows a typical implementation of a View in a content
18748     * browsing application.  In this implementation, the application goes
18749     * into a content-oriented mode by hiding the status bar and action bar,
18750     * and putting the navigation elements into lights out mode.  The user can
18751     * then interact with content while in this mode.  Such an application should
18752     * provide an easy way for the user to toggle out of the mode (such as to
18753     * check information in the status bar or access notifications).  In the
18754     * implementation here, this is done simply by tapping on the content.
18755     *
18756     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
18757     *      content}
18758     *
18759     * <p>This second code sample shows a typical implementation of a View
18760     * in a video playing application.  In this situation, while the video is
18761     * playing the application would like to go into a complete full-screen mode,
18762     * to use as much of the display as possible for the video.  When in this state
18763     * the user can not interact with the application; the system intercepts
18764     * touching on the screen to pop the UI out of full screen mode.  See
18765     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
18766     *
18767     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
18768     *      content}
18769     *
18770     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18771     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18772     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18773     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18774     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18775     */
18776    public void setSystemUiVisibility(int visibility) {
18777        if (visibility != mSystemUiVisibility) {
18778            mSystemUiVisibility = visibility;
18779            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18780                mParent.recomputeViewAttributes(this);
18781            }
18782        }
18783    }
18784
18785    /**
18786     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
18787     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18788     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18789     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18790     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18791     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18792     */
18793    public int getSystemUiVisibility() {
18794        return mSystemUiVisibility;
18795    }
18796
18797    /**
18798     * Returns the current system UI visibility that is currently set for
18799     * the entire window.  This is the combination of the
18800     * {@link #setSystemUiVisibility(int)} values supplied by all of the
18801     * views in the window.
18802     */
18803    public int getWindowSystemUiVisibility() {
18804        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18805    }
18806
18807    /**
18808     * Override to find out when the window's requested system UI visibility
18809     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18810     * This is different from the callbacks received through
18811     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18812     * in that this is only telling you about the local request of the window,
18813     * not the actual values applied by the system.
18814     */
18815    public void onWindowSystemUiVisibilityChanged(int visible) {
18816    }
18817
18818    /**
18819     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18820     * the view hierarchy.
18821     */
18822    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18823        onWindowSystemUiVisibilityChanged(visible);
18824    }
18825
18826    /**
18827     * Set a listener to receive callbacks when the visibility of the system bar changes.
18828     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18829     */
18830    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18831        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18832        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18833            mParent.recomputeViewAttributes(this);
18834        }
18835    }
18836
18837    /**
18838     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18839     * the view hierarchy.
18840     */
18841    public void dispatchSystemUiVisibilityChanged(int visibility) {
18842        ListenerInfo li = mListenerInfo;
18843        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18844            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18845                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18846        }
18847    }
18848
18849    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18850        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18851        if (val != mSystemUiVisibility) {
18852            setSystemUiVisibility(val);
18853            return true;
18854        }
18855        return false;
18856    }
18857
18858    /** @hide */
18859    public void setDisabledSystemUiVisibility(int flags) {
18860        if (mAttachInfo != null) {
18861            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18862                mAttachInfo.mDisabledSystemUiVisibility = flags;
18863                if (mParent != null) {
18864                    mParent.recomputeViewAttributes(this);
18865                }
18866            }
18867        }
18868    }
18869
18870    /**
18871     * Creates an image that the system displays during the drag and drop
18872     * operation. This is called a &quot;drag shadow&quot;. The default implementation
18873     * for a DragShadowBuilder based on a View returns an image that has exactly the same
18874     * appearance as the given View. The default also positions the center of the drag shadow
18875     * directly under the touch point. If no View is provided (the constructor with no parameters
18876     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18877     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
18878     * default is an invisible drag shadow.
18879     * <p>
18880     * You are not required to use the View you provide to the constructor as the basis of the
18881     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18882     * anything you want as the drag shadow.
18883     * </p>
18884     * <p>
18885     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
18886     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18887     *  size and position of the drag shadow. It uses this data to construct a
18888     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18889     *  so that your application can draw the shadow image in the Canvas.
18890     * </p>
18891     *
18892     * <div class="special reference">
18893     * <h3>Developer Guides</h3>
18894     * <p>For a guide to implementing drag and drop features, read the
18895     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18896     * </div>
18897     */
18898    public static class DragShadowBuilder {
18899        private final WeakReference<View> mView;
18900
18901        /**
18902         * Constructs a shadow image builder based on a View. By default, the resulting drag
18903         * shadow will have the same appearance and dimensions as the View, with the touch point
18904         * over the center of the View.
18905         * @param view A View. Any View in scope can be used.
18906         */
18907        public DragShadowBuilder(View view) {
18908            mView = new WeakReference<View>(view);
18909        }
18910
18911        /**
18912         * Construct a shadow builder object with no associated View.  This
18913         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18914         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18915         * to supply the drag shadow's dimensions and appearance without
18916         * reference to any View object. If they are not overridden, then the result is an
18917         * invisible drag shadow.
18918         */
18919        public DragShadowBuilder() {
18920            mView = new WeakReference<View>(null);
18921        }
18922
18923        /**
18924         * Returns the View object that had been passed to the
18925         * {@link #View.DragShadowBuilder(View)}
18926         * constructor.  If that View parameter was {@code null} or if the
18927         * {@link #View.DragShadowBuilder()}
18928         * constructor was used to instantiate the builder object, this method will return
18929         * null.
18930         *
18931         * @return The View object associate with this builder object.
18932         */
18933        @SuppressWarnings({"JavadocReference"})
18934        final public View getView() {
18935            return mView.get();
18936        }
18937
18938        /**
18939         * Provides the metrics for the shadow image. These include the dimensions of
18940         * the shadow image, and the point within that shadow that should
18941         * be centered under the touch location while dragging.
18942         * <p>
18943         * The default implementation sets the dimensions of the shadow to be the
18944         * same as the dimensions of the View itself and centers the shadow under
18945         * the touch point.
18946         * </p>
18947         *
18948         * @param shadowSize A {@link android.graphics.Point} containing the width and height
18949         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18950         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18951         * image.
18952         *
18953         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18954         * shadow image that should be underneath the touch point during the drag and drop
18955         * operation. Your application must set {@link android.graphics.Point#x} to the
18956         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18957         */
18958        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18959            final View view = mView.get();
18960            if (view != null) {
18961                shadowSize.set(view.getWidth(), view.getHeight());
18962                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18963            } else {
18964                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18965            }
18966        }
18967
18968        /**
18969         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18970         * based on the dimensions it received from the
18971         * {@link #onProvideShadowMetrics(Point, Point)} callback.
18972         *
18973         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18974         */
18975        public void onDrawShadow(Canvas canvas) {
18976            final View view = mView.get();
18977            if (view != null) {
18978                view.draw(canvas);
18979            } else {
18980                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18981            }
18982        }
18983    }
18984
18985    /**
18986     * Starts a drag and drop operation. When your application calls this method, it passes a
18987     * {@link android.view.View.DragShadowBuilder} object to the system. The
18988     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18989     * to get metrics for the drag shadow, and then calls the object's
18990     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18991     * <p>
18992     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
18993     *  drag events to all the View objects in your application that are currently visible. It does
18994     *  this either by calling the View object's drag listener (an implementation of
18995     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18996     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18997     *  Both are passed a {@link android.view.DragEvent} object that has a
18998     *  {@link android.view.DragEvent#getAction()} value of
18999     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19000     * </p>
19001     * <p>
19002     * Your application can invoke startDrag() on any attached View object. The View object does not
19003     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19004     * be related to the View the user selected for dragging.
19005     * </p>
19006     * @param data A {@link android.content.ClipData} object pointing to the data to be
19007     * transferred by the drag and drop operation.
19008     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19009     * drag shadow.
19010     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19011     * drop operation. This Object is put into every DragEvent object sent by the system during the
19012     * current drag.
19013     * <p>
19014     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19015     * to the target Views. For example, it can contain flags that differentiate between a
19016     * a copy operation and a move operation.
19017     * </p>
19018     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19019     * so the parameter should be set to 0.
19020     * @return {@code true} if the method completes successfully, or
19021     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19022     * do a drag, and so no drag operation is in progress.
19023     */
19024    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19025            Object myLocalState, int flags) {
19026        if (ViewDebug.DEBUG_DRAG) {
19027            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19028        }
19029        boolean okay = false;
19030
19031        Point shadowSize = new Point();
19032        Point shadowTouchPoint = new Point();
19033        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19034
19035        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19036                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19037            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19038        }
19039
19040        if (ViewDebug.DEBUG_DRAG) {
19041            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19042                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19043        }
19044        Surface surface = new Surface();
19045        try {
19046            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19047                    flags, shadowSize.x, shadowSize.y, surface);
19048            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19049                    + " surface=" + surface);
19050            if (token != null) {
19051                Canvas canvas = surface.lockCanvas(null);
19052                try {
19053                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19054                    shadowBuilder.onDrawShadow(canvas);
19055                } finally {
19056                    surface.unlockCanvasAndPost(canvas);
19057                }
19058
19059                final ViewRootImpl root = getViewRootImpl();
19060
19061                // Cache the local state object for delivery with DragEvents
19062                root.setLocalDragState(myLocalState);
19063
19064                // repurpose 'shadowSize' for the last touch point
19065                root.getLastTouchPoint(shadowSize);
19066
19067                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19068                        shadowSize.x, shadowSize.y,
19069                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19070                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19071
19072                // Off and running!  Release our local surface instance; the drag
19073                // shadow surface is now managed by the system process.
19074                surface.release();
19075            }
19076        } catch (Exception e) {
19077            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19078            surface.destroy();
19079        }
19080
19081        return okay;
19082    }
19083
19084    /**
19085     * Handles drag events sent by the system following a call to
19086     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19087     *<p>
19088     * When the system calls this method, it passes a
19089     * {@link android.view.DragEvent} object. A call to
19090     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19091     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19092     * operation.
19093     * @param event The {@link android.view.DragEvent} sent by the system.
19094     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19095     * in DragEvent, indicating the type of drag event represented by this object.
19096     * @return {@code true} if the method was successful, otherwise {@code false}.
19097     * <p>
19098     *  The method should return {@code true} in response to an action type of
19099     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19100     *  operation.
19101     * </p>
19102     * <p>
19103     *  The method should also return {@code true} in response to an action type of
19104     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19105     *  {@code false} if it didn't.
19106     * </p>
19107     */
19108    public boolean onDragEvent(DragEvent event) {
19109        return false;
19110    }
19111
19112    /**
19113     * Detects if this View is enabled and has a drag event listener.
19114     * If both are true, then it calls the drag event listener with the
19115     * {@link android.view.DragEvent} it received. If the drag event listener returns
19116     * {@code true}, then dispatchDragEvent() returns {@code true}.
19117     * <p>
19118     * For all other cases, the method calls the
19119     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19120     * method and returns its result.
19121     * </p>
19122     * <p>
19123     * This ensures that a drag event is always consumed, even if the View does not have a drag
19124     * event listener. However, if the View has a listener and the listener returns true, then
19125     * onDragEvent() is not called.
19126     * </p>
19127     */
19128    public boolean dispatchDragEvent(DragEvent event) {
19129        ListenerInfo li = mListenerInfo;
19130        //noinspection SimplifiableIfStatement
19131        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19132                && li.mOnDragListener.onDrag(this, event)) {
19133            return true;
19134        }
19135        return onDragEvent(event);
19136    }
19137
19138    boolean canAcceptDrag() {
19139        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19140    }
19141
19142    /**
19143     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19144     * it is ever exposed at all.
19145     * @hide
19146     */
19147    public void onCloseSystemDialogs(String reason) {
19148    }
19149
19150    /**
19151     * Given a Drawable whose bounds have been set to draw into this view,
19152     * update a Region being computed for
19153     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19154     * that any non-transparent parts of the Drawable are removed from the
19155     * given transparent region.
19156     *
19157     * @param dr The Drawable whose transparency is to be applied to the region.
19158     * @param region A Region holding the current transparency information,
19159     * where any parts of the region that are set are considered to be
19160     * transparent.  On return, this region will be modified to have the
19161     * transparency information reduced by the corresponding parts of the
19162     * Drawable that are not transparent.
19163     * {@hide}
19164     */
19165    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19166        if (DBG) {
19167            Log.i("View", "Getting transparent region for: " + this);
19168        }
19169        final Region r = dr.getTransparentRegion();
19170        final Rect db = dr.getBounds();
19171        final AttachInfo attachInfo = mAttachInfo;
19172        if (r != null && attachInfo != null) {
19173            final int w = getRight()-getLeft();
19174            final int h = getBottom()-getTop();
19175            if (db.left > 0) {
19176                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19177                r.op(0, 0, db.left, h, Region.Op.UNION);
19178            }
19179            if (db.right < w) {
19180                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19181                r.op(db.right, 0, w, h, Region.Op.UNION);
19182            }
19183            if (db.top > 0) {
19184                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19185                r.op(0, 0, w, db.top, Region.Op.UNION);
19186            }
19187            if (db.bottom < h) {
19188                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19189                r.op(0, db.bottom, w, h, Region.Op.UNION);
19190            }
19191            final int[] location = attachInfo.mTransparentLocation;
19192            getLocationInWindow(location);
19193            r.translate(location[0], location[1]);
19194            region.op(r, Region.Op.INTERSECT);
19195        } else {
19196            region.op(db, Region.Op.DIFFERENCE);
19197        }
19198    }
19199
19200    private void checkForLongClick(int delayOffset) {
19201        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19202            mHasPerformedLongPress = false;
19203
19204            if (mPendingCheckForLongPress == null) {
19205                mPendingCheckForLongPress = new CheckForLongPress();
19206            }
19207            mPendingCheckForLongPress.rememberWindowAttachCount();
19208            postDelayed(mPendingCheckForLongPress,
19209                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19210        }
19211    }
19212
19213    /**
19214     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19215     * LayoutInflater} class, which provides a full range of options for view inflation.
19216     *
19217     * @param context The Context object for your activity or application.
19218     * @param resource The resource ID to inflate
19219     * @param root A view group that will be the parent.  Used to properly inflate the
19220     * layout_* parameters.
19221     * @see LayoutInflater
19222     */
19223    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19224        LayoutInflater factory = LayoutInflater.from(context);
19225        return factory.inflate(resource, root);
19226    }
19227
19228    /**
19229     * Scroll the view with standard behavior for scrolling beyond the normal
19230     * content boundaries. Views that call this method should override
19231     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19232     * results of an over-scroll operation.
19233     *
19234     * Views can use this method to handle any touch or fling-based scrolling.
19235     *
19236     * @param deltaX Change in X in pixels
19237     * @param deltaY Change in Y in pixels
19238     * @param scrollX Current X scroll value in pixels before applying deltaX
19239     * @param scrollY Current Y scroll value in pixels before applying deltaY
19240     * @param scrollRangeX Maximum content scroll range along the X axis
19241     * @param scrollRangeY Maximum content scroll range along the Y axis
19242     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19243     *          along the X axis.
19244     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19245     *          along the Y axis.
19246     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19247     * @return true if scrolling was clamped to an over-scroll boundary along either
19248     *          axis, false otherwise.
19249     */
19250    @SuppressWarnings({"UnusedParameters"})
19251    protected boolean overScrollBy(int deltaX, int deltaY,
19252            int scrollX, int scrollY,
19253            int scrollRangeX, int scrollRangeY,
19254            int maxOverScrollX, int maxOverScrollY,
19255            boolean isTouchEvent) {
19256        final int overScrollMode = mOverScrollMode;
19257        final boolean canScrollHorizontal =
19258                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19259        final boolean canScrollVertical =
19260                computeVerticalScrollRange() > computeVerticalScrollExtent();
19261        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19262                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19263        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19264                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19265
19266        int newScrollX = scrollX + deltaX;
19267        if (!overScrollHorizontal) {
19268            maxOverScrollX = 0;
19269        }
19270
19271        int newScrollY = scrollY + deltaY;
19272        if (!overScrollVertical) {
19273            maxOverScrollY = 0;
19274        }
19275
19276        // Clamp values if at the limits and record
19277        final int left = -maxOverScrollX;
19278        final int right = maxOverScrollX + scrollRangeX;
19279        final int top = -maxOverScrollY;
19280        final int bottom = maxOverScrollY + scrollRangeY;
19281
19282        boolean clampedX = false;
19283        if (newScrollX > right) {
19284            newScrollX = right;
19285            clampedX = true;
19286        } else if (newScrollX < left) {
19287            newScrollX = left;
19288            clampedX = true;
19289        }
19290
19291        boolean clampedY = false;
19292        if (newScrollY > bottom) {
19293            newScrollY = bottom;
19294            clampedY = true;
19295        } else if (newScrollY < top) {
19296            newScrollY = top;
19297            clampedY = true;
19298        }
19299
19300        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19301
19302        return clampedX || clampedY;
19303    }
19304
19305    /**
19306     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19307     * respond to the results of an over-scroll operation.
19308     *
19309     * @param scrollX New X scroll value in pixels
19310     * @param scrollY New Y scroll value in pixels
19311     * @param clampedX True if scrollX was clamped to an over-scroll boundary
19312     * @param clampedY True if scrollY was clamped to an over-scroll boundary
19313     */
19314    protected void onOverScrolled(int scrollX, int scrollY,
19315            boolean clampedX, boolean clampedY) {
19316        // Intentionally empty.
19317    }
19318
19319    /**
19320     * Returns the over-scroll mode for this view. The result will be
19321     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19322     * (allow over-scrolling only if the view content is larger than the container),
19323     * or {@link #OVER_SCROLL_NEVER}.
19324     *
19325     * @return This view's over-scroll mode.
19326     */
19327    public int getOverScrollMode() {
19328        return mOverScrollMode;
19329    }
19330
19331    /**
19332     * Set the over-scroll mode for this view. Valid over-scroll modes are
19333     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19334     * (allow over-scrolling only if the view content is larger than the container),
19335     * or {@link #OVER_SCROLL_NEVER}.
19336     *
19337     * Setting the over-scroll mode of a view will have an effect only if the
19338     * view is capable of scrolling.
19339     *
19340     * @param overScrollMode The new over-scroll mode for this view.
19341     */
19342    public void setOverScrollMode(int overScrollMode) {
19343        if (overScrollMode != OVER_SCROLL_ALWAYS &&
19344                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19345                overScrollMode != OVER_SCROLL_NEVER) {
19346            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19347        }
19348        mOverScrollMode = overScrollMode;
19349    }
19350
19351    /**
19352     * Enable or disable nested scrolling for this view.
19353     *
19354     * <p>If this property is set to true the view will be permitted to initiate nested
19355     * scrolling operations with a compatible parent view in the current hierarchy. If this
19356     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19357     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19358     * the nested scroll.</p>
19359     *
19360     * @param enabled true to enable nested scrolling, false to disable
19361     *
19362     * @see #isNestedScrollingEnabled()
19363     */
19364    public void setNestedScrollingEnabled(boolean enabled) {
19365        if (enabled) {
19366            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19367        } else {
19368            stopNestedScroll();
19369            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19370        }
19371    }
19372
19373    /**
19374     * Returns true if nested scrolling is enabled for this view.
19375     *
19376     * <p>If nested scrolling is enabled and this View class implementation supports it,
19377     * this view will act as a nested scrolling child view when applicable, forwarding data
19378     * about the scroll operation in progress to a compatible and cooperating nested scrolling
19379     * parent.</p>
19380     *
19381     * @return true if nested scrolling is enabled
19382     *
19383     * @see #setNestedScrollingEnabled(boolean)
19384     */
19385    public boolean isNestedScrollingEnabled() {
19386        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19387                PFLAG3_NESTED_SCROLLING_ENABLED;
19388    }
19389
19390    /**
19391     * Begin a nestable scroll operation along the given axes.
19392     *
19393     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19394     *
19395     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19396     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19397     * In the case of touch scrolling the nested scroll will be terminated automatically in
19398     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19399     * In the event of programmatic scrolling the caller must explicitly call
19400     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19401     *
19402     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19403     * If it returns false the caller may ignore the rest of this contract until the next scroll.
19404     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19405     *
19406     * <p>At each incremental step of the scroll the caller should invoke
19407     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19408     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19409     * parent at least partially consumed the scroll and the caller should adjust the amount it
19410     * scrolls by.</p>
19411     *
19412     * <p>After applying the remainder of the scroll delta the caller should invoke
19413     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19414     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19415     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19416     * </p>
19417     *
19418     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19419     *             {@link #SCROLL_AXIS_VERTICAL}.
19420     * @return true if a cooperative parent was found and nested scrolling has been enabled for
19421     *         the current gesture.
19422     *
19423     * @see #stopNestedScroll()
19424     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19425     * @see #dispatchNestedScroll(int, int, int, int, int[])
19426     */
19427    public boolean startNestedScroll(int axes) {
19428        if (hasNestedScrollingParent()) {
19429            // Already in progress
19430            return true;
19431        }
19432        if (isNestedScrollingEnabled()) {
19433            ViewParent p = getParent();
19434            View child = this;
19435            while (p != null) {
19436                try {
19437                    if (p.onStartNestedScroll(child, this, axes)) {
19438                        mNestedScrollingParent = p;
19439                        p.onNestedScrollAccepted(child, this, axes);
19440                        return true;
19441                    }
19442                } catch (AbstractMethodError e) {
19443                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
19444                            "method onStartNestedScroll", e);
19445                    // Allow the search upward to continue
19446                }
19447                if (p instanceof View) {
19448                    child = (View) p;
19449                }
19450                p = p.getParent();
19451            }
19452        }
19453        return false;
19454    }
19455
19456    /**
19457     * Stop a nested scroll in progress.
19458     *
19459     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
19460     *
19461     * @see #startNestedScroll(int)
19462     */
19463    public void stopNestedScroll() {
19464        if (mNestedScrollingParent != null) {
19465            mNestedScrollingParent.onStopNestedScroll(this);
19466            mNestedScrollingParent = null;
19467        }
19468    }
19469
19470    /**
19471     * Returns true if this view has a nested scrolling parent.
19472     *
19473     * <p>The presence of a nested scrolling parent indicates that this view has initiated
19474     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
19475     *
19476     * @return whether this view has a nested scrolling parent
19477     */
19478    public boolean hasNestedScrollingParent() {
19479        return mNestedScrollingParent != null;
19480    }
19481
19482    /**
19483     * Dispatch one step of a nested scroll in progress.
19484     *
19485     * <p>Implementations of views that support nested scrolling should call this to report
19486     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
19487     * is not currently in progress or nested scrolling is not
19488     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
19489     *
19490     * <p>Compatible View implementations should also call
19491     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
19492     * consuming a component of the scroll event themselves.</p>
19493     *
19494     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
19495     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
19496     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
19497     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
19498     * @param offsetInWindow Optional. If not null, on return this will contain the offset
19499     *                       in local view coordinates of this view from before this operation
19500     *                       to after it completes. View implementations may use this to adjust
19501     *                       expected input coordinate tracking.
19502     * @return true if the event was dispatched, false if it could not be dispatched.
19503     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19504     */
19505    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
19506            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
19507        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19508            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
19509                int startX = 0;
19510                int startY = 0;
19511                if (offsetInWindow != null) {
19512                    getLocationInWindow(offsetInWindow);
19513                    startX = offsetInWindow[0];
19514                    startY = offsetInWindow[1];
19515                }
19516
19517                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
19518                        dxUnconsumed, dyUnconsumed);
19519
19520                if (offsetInWindow != null) {
19521                    getLocationInWindow(offsetInWindow);
19522                    offsetInWindow[0] -= startX;
19523                    offsetInWindow[1] -= startY;
19524                }
19525                return true;
19526            } else if (offsetInWindow != null) {
19527                // No motion, no dispatch. Keep offsetInWindow up to date.
19528                offsetInWindow[0] = 0;
19529                offsetInWindow[1] = 0;
19530            }
19531        }
19532        return false;
19533    }
19534
19535    /**
19536     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
19537     *
19538     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
19539     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
19540     * scrolling operation to consume some or all of the scroll operation before the child view
19541     * consumes it.</p>
19542     *
19543     * @param dx Horizontal scroll distance in pixels
19544     * @param dy Vertical scroll distance in pixels
19545     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
19546     *                 and consumed[1] the consumed dy.
19547     * @param offsetInWindow Optional. If not null, on return this will contain the offset
19548     *                       in local view coordinates of this view from before this operation
19549     *                       to after it completes. View implementations may use this to adjust
19550     *                       expected input coordinate tracking.
19551     * @return true if the parent consumed some or all of the scroll delta
19552     * @see #dispatchNestedScroll(int, int, int, int, int[])
19553     */
19554    public boolean dispatchNestedPreScroll(int dx, int dy,
19555            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
19556        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19557            if (dx != 0 || dy != 0) {
19558                int startX = 0;
19559                int startY = 0;
19560                if (offsetInWindow != null) {
19561                    getLocationInWindow(offsetInWindow);
19562                    startX = offsetInWindow[0];
19563                    startY = offsetInWindow[1];
19564                }
19565
19566                if (consumed == null) {
19567                    if (mTempNestedScrollConsumed == null) {
19568                        mTempNestedScrollConsumed = new int[2];
19569                    }
19570                    consumed = mTempNestedScrollConsumed;
19571                }
19572                consumed[0] = 0;
19573                consumed[1] = 0;
19574                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
19575
19576                if (offsetInWindow != null) {
19577                    getLocationInWindow(offsetInWindow);
19578                    offsetInWindow[0] -= startX;
19579                    offsetInWindow[1] -= startY;
19580                }
19581                return consumed[0] != 0 || consumed[1] != 0;
19582            } else if (offsetInWindow != null) {
19583                offsetInWindow[0] = 0;
19584                offsetInWindow[1] = 0;
19585            }
19586        }
19587        return false;
19588    }
19589
19590    /**
19591     * Dispatch a fling to a nested scrolling parent.
19592     *
19593     * <p>This method should be used to indicate that a nested scrolling child has detected
19594     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
19595     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
19596     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
19597     * along a scrollable axis.</p>
19598     *
19599     * <p>If a nested scrolling child view would normally fling but it is at the edge of
19600     * its own content, it can use this method to delegate the fling to its nested scrolling
19601     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
19602     *
19603     * @param velocityX Horizontal fling velocity in pixels per second
19604     * @param velocityY Vertical fling velocity in pixels per second
19605     * @param consumed true if the child consumed the fling, false otherwise
19606     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
19607     */
19608    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
19609        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19610            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
19611        }
19612        return false;
19613    }
19614
19615    /**
19616     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
19617     *
19618     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
19619     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
19620     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
19621     * before the child view consumes it. If this method returns <code>true</code>, a nested
19622     * parent view consumed the fling and this view should not scroll as a result.</p>
19623     *
19624     * <p>For a better user experience, only one view in a nested scrolling chain should consume
19625     * the fling at a time. If a parent view consumed the fling this method will return false.
19626     * Custom view implementations should account for this in two ways:</p>
19627     *
19628     * <ul>
19629     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
19630     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
19631     *     position regardless.</li>
19632     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
19633     *     even to settle back to a valid idle position.</li>
19634     * </ul>
19635     *
19636     * <p>Views should also not offer fling velocities to nested parent views along an axis
19637     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
19638     * should not offer a horizontal fling velocity to its parents since scrolling along that
19639     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
19640     *
19641     * @param velocityX Horizontal fling velocity in pixels per second
19642     * @param velocityY Vertical fling velocity in pixels per second
19643     * @return true if a nested scrolling parent consumed the fling
19644     */
19645    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
19646        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19647            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
19648        }
19649        return false;
19650    }
19651
19652    /**
19653     * Gets a scale factor that determines the distance the view should scroll
19654     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
19655     * @return The vertical scroll scale factor.
19656     * @hide
19657     */
19658    protected float getVerticalScrollFactor() {
19659        if (mVerticalScrollFactor == 0) {
19660            TypedValue outValue = new TypedValue();
19661            if (!mContext.getTheme().resolveAttribute(
19662                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
19663                throw new IllegalStateException(
19664                        "Expected theme to define listPreferredItemHeight.");
19665            }
19666            mVerticalScrollFactor = outValue.getDimension(
19667                    mContext.getResources().getDisplayMetrics());
19668        }
19669        return mVerticalScrollFactor;
19670    }
19671
19672    /**
19673     * Gets a scale factor that determines the distance the view should scroll
19674     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
19675     * @return The horizontal scroll scale factor.
19676     * @hide
19677     */
19678    protected float getHorizontalScrollFactor() {
19679        // TODO: Should use something else.
19680        return getVerticalScrollFactor();
19681    }
19682
19683    /**
19684     * Return the value specifying the text direction or policy that was set with
19685     * {@link #setTextDirection(int)}.
19686     *
19687     * @return the defined text direction. It can be one of:
19688     *
19689     * {@link #TEXT_DIRECTION_INHERIT},
19690     * {@link #TEXT_DIRECTION_FIRST_STRONG},
19691     * {@link #TEXT_DIRECTION_ANY_RTL},
19692     * {@link #TEXT_DIRECTION_LTR},
19693     * {@link #TEXT_DIRECTION_RTL},
19694     * {@link #TEXT_DIRECTION_LOCALE},
19695     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
19696     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
19697     *
19698     * @attr ref android.R.styleable#View_textDirection
19699     *
19700     * @hide
19701     */
19702    @ViewDebug.ExportedProperty(category = "text", mapping = {
19703            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19704            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19705            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19706            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19707            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19708            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
19709            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
19710            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
19711    })
19712    public int getRawTextDirection() {
19713        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
19714    }
19715
19716    /**
19717     * Set the text direction.
19718     *
19719     * @param textDirection the direction to set. Should be one of:
19720     *
19721     * {@link #TEXT_DIRECTION_INHERIT},
19722     * {@link #TEXT_DIRECTION_FIRST_STRONG},
19723     * {@link #TEXT_DIRECTION_ANY_RTL},
19724     * {@link #TEXT_DIRECTION_LTR},
19725     * {@link #TEXT_DIRECTION_RTL},
19726     * {@link #TEXT_DIRECTION_LOCALE}
19727     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
19728     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
19729     *
19730     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
19731     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
19732     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
19733     *
19734     * @attr ref android.R.styleable#View_textDirection
19735     */
19736    public void setTextDirection(int textDirection) {
19737        if (getRawTextDirection() != textDirection) {
19738            // Reset the current text direction and the resolved one
19739            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
19740            resetResolvedTextDirection();
19741            // Set the new text direction
19742            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
19743            // Do resolution
19744            resolveTextDirection();
19745            // Notify change
19746            onRtlPropertiesChanged(getLayoutDirection());
19747            // Refresh
19748            requestLayout();
19749            invalidate(true);
19750        }
19751    }
19752
19753    /**
19754     * Return the resolved text direction.
19755     *
19756     * @return the resolved text direction. Returns one of:
19757     *
19758     * {@link #TEXT_DIRECTION_FIRST_STRONG},
19759     * {@link #TEXT_DIRECTION_ANY_RTL},
19760     * {@link #TEXT_DIRECTION_LTR},
19761     * {@link #TEXT_DIRECTION_RTL},
19762     * {@link #TEXT_DIRECTION_LOCALE},
19763     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
19764     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
19765     *
19766     * @attr ref android.R.styleable#View_textDirection
19767     */
19768    @ViewDebug.ExportedProperty(category = "text", mapping = {
19769            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19770            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19771            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19772            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19773            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19774            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
19775            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
19776            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
19777    })
19778    public int getTextDirection() {
19779        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
19780    }
19781
19782    /**
19783     * Resolve the text direction.
19784     *
19785     * @return true if resolution has been done, false otherwise.
19786     *
19787     * @hide
19788     */
19789    public boolean resolveTextDirection() {
19790        // Reset any previous text direction resolution
19791        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19792
19793        if (hasRtlSupport()) {
19794            // Set resolved text direction flag depending on text direction flag
19795            final int textDirection = getRawTextDirection();
19796            switch(textDirection) {
19797                case TEXT_DIRECTION_INHERIT:
19798                    if (!canResolveTextDirection()) {
19799                        // We cannot do the resolution if there is no parent, so use the default one
19800                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19801                        // Resolution will need to happen again later
19802                        return false;
19803                    }
19804
19805                    // Parent has not yet resolved, so we still return the default
19806                    try {
19807                        if (!mParent.isTextDirectionResolved()) {
19808                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19809                            // Resolution will need to happen again later
19810                            return false;
19811                        }
19812                    } catch (AbstractMethodError e) {
19813                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19814                                " does not fully implement ViewParent", e);
19815                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19816                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19817                        return true;
19818                    }
19819
19820                    // Set current resolved direction to the same value as the parent's one
19821                    int parentResolvedDirection;
19822                    try {
19823                        parentResolvedDirection = mParent.getTextDirection();
19824                    } catch (AbstractMethodError e) {
19825                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19826                                " does not fully implement ViewParent", e);
19827                        parentResolvedDirection = TEXT_DIRECTION_LTR;
19828                    }
19829                    switch (parentResolvedDirection) {
19830                        case TEXT_DIRECTION_FIRST_STRONG:
19831                        case TEXT_DIRECTION_ANY_RTL:
19832                        case TEXT_DIRECTION_LTR:
19833                        case TEXT_DIRECTION_RTL:
19834                        case TEXT_DIRECTION_LOCALE:
19835                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
19836                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
19837                            mPrivateFlags2 |=
19838                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19839                            break;
19840                        default:
19841                            // Default resolved direction is "first strong" heuristic
19842                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19843                    }
19844                    break;
19845                case TEXT_DIRECTION_FIRST_STRONG:
19846                case TEXT_DIRECTION_ANY_RTL:
19847                case TEXT_DIRECTION_LTR:
19848                case TEXT_DIRECTION_RTL:
19849                case TEXT_DIRECTION_LOCALE:
19850                case TEXT_DIRECTION_FIRST_STRONG_LTR:
19851                case TEXT_DIRECTION_FIRST_STRONG_RTL:
19852                    // Resolved direction is the same as text direction
19853                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19854                    break;
19855                default:
19856                    // Default resolved direction is "first strong" heuristic
19857                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19858            }
19859        } else {
19860            // Default resolved direction is "first strong" heuristic
19861            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19862        }
19863
19864        // Set to resolved
19865        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19866        return true;
19867    }
19868
19869    /**
19870     * Check if text direction resolution can be done.
19871     *
19872     * @return true if text direction resolution can be done otherwise return false.
19873     */
19874    public boolean canResolveTextDirection() {
19875        switch (getRawTextDirection()) {
19876            case TEXT_DIRECTION_INHERIT:
19877                if (mParent != null) {
19878                    try {
19879                        return mParent.canResolveTextDirection();
19880                    } catch (AbstractMethodError e) {
19881                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19882                                " does not fully implement ViewParent", e);
19883                    }
19884                }
19885                return false;
19886
19887            default:
19888                return true;
19889        }
19890    }
19891
19892    /**
19893     * Reset resolved text direction. Text direction will be resolved during a call to
19894     * {@link #onMeasure(int, int)}.
19895     *
19896     * @hide
19897     */
19898    public void resetResolvedTextDirection() {
19899        // Reset any previous text direction resolution
19900        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19901        // Set to default value
19902        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19903    }
19904
19905    /**
19906     * @return true if text direction is inherited.
19907     *
19908     * @hide
19909     */
19910    public boolean isTextDirectionInherited() {
19911        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19912    }
19913
19914    /**
19915     * @return true if text direction is resolved.
19916     */
19917    public boolean isTextDirectionResolved() {
19918        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19919    }
19920
19921    /**
19922     * Return the value specifying the text alignment or policy that was set with
19923     * {@link #setTextAlignment(int)}.
19924     *
19925     * @return the defined text alignment. It can be one of:
19926     *
19927     * {@link #TEXT_ALIGNMENT_INHERIT},
19928     * {@link #TEXT_ALIGNMENT_GRAVITY},
19929     * {@link #TEXT_ALIGNMENT_CENTER},
19930     * {@link #TEXT_ALIGNMENT_TEXT_START},
19931     * {@link #TEXT_ALIGNMENT_TEXT_END},
19932     * {@link #TEXT_ALIGNMENT_VIEW_START},
19933     * {@link #TEXT_ALIGNMENT_VIEW_END}
19934     *
19935     * @attr ref android.R.styleable#View_textAlignment
19936     *
19937     * @hide
19938     */
19939    @ViewDebug.ExportedProperty(category = "text", mapping = {
19940            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19941            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19942            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19943            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19944            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19945            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19946            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19947    })
19948    @TextAlignment
19949    public int getRawTextAlignment() {
19950        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19951    }
19952
19953    /**
19954     * Set the text alignment.
19955     *
19956     * @param textAlignment The text alignment to set. Should be one of
19957     *
19958     * {@link #TEXT_ALIGNMENT_INHERIT},
19959     * {@link #TEXT_ALIGNMENT_GRAVITY},
19960     * {@link #TEXT_ALIGNMENT_CENTER},
19961     * {@link #TEXT_ALIGNMENT_TEXT_START},
19962     * {@link #TEXT_ALIGNMENT_TEXT_END},
19963     * {@link #TEXT_ALIGNMENT_VIEW_START},
19964     * {@link #TEXT_ALIGNMENT_VIEW_END}
19965     *
19966     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19967     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19968     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19969     *
19970     * @attr ref android.R.styleable#View_textAlignment
19971     */
19972    public void setTextAlignment(@TextAlignment int textAlignment) {
19973        if (textAlignment != getRawTextAlignment()) {
19974            // Reset the current and resolved text alignment
19975            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19976            resetResolvedTextAlignment();
19977            // Set the new text alignment
19978            mPrivateFlags2 |=
19979                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19980            // Do resolution
19981            resolveTextAlignment();
19982            // Notify change
19983            onRtlPropertiesChanged(getLayoutDirection());
19984            // Refresh
19985            requestLayout();
19986            invalidate(true);
19987        }
19988    }
19989
19990    /**
19991     * Return the resolved text alignment.
19992     *
19993     * @return the resolved text alignment. Returns one of:
19994     *
19995     * {@link #TEXT_ALIGNMENT_GRAVITY},
19996     * {@link #TEXT_ALIGNMENT_CENTER},
19997     * {@link #TEXT_ALIGNMENT_TEXT_START},
19998     * {@link #TEXT_ALIGNMENT_TEXT_END},
19999     * {@link #TEXT_ALIGNMENT_VIEW_START},
20000     * {@link #TEXT_ALIGNMENT_VIEW_END}
20001     *
20002     * @attr ref android.R.styleable#View_textAlignment
20003     */
20004    @ViewDebug.ExportedProperty(category = "text", mapping = {
20005            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20006            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20007            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20008            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20009            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20010            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20011            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20012    })
20013    @TextAlignment
20014    public int getTextAlignment() {
20015        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20016                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20017    }
20018
20019    /**
20020     * Resolve the text alignment.
20021     *
20022     * @return true if resolution has been done, false otherwise.
20023     *
20024     * @hide
20025     */
20026    public boolean resolveTextAlignment() {
20027        // Reset any previous text alignment resolution
20028        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20029
20030        if (hasRtlSupport()) {
20031            // Set resolved text alignment flag depending on text alignment flag
20032            final int textAlignment = getRawTextAlignment();
20033            switch (textAlignment) {
20034                case TEXT_ALIGNMENT_INHERIT:
20035                    // Check if we can resolve the text alignment
20036                    if (!canResolveTextAlignment()) {
20037                        // We cannot do the resolution if there is no parent so use the default
20038                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20039                        // Resolution will need to happen again later
20040                        return false;
20041                    }
20042
20043                    // Parent has not yet resolved, so we still return the default
20044                    try {
20045                        if (!mParent.isTextAlignmentResolved()) {
20046                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20047                            // Resolution will need to happen again later
20048                            return false;
20049                        }
20050                    } catch (AbstractMethodError e) {
20051                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20052                                " does not fully implement ViewParent", e);
20053                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20054                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20055                        return true;
20056                    }
20057
20058                    int parentResolvedTextAlignment;
20059                    try {
20060                        parentResolvedTextAlignment = mParent.getTextAlignment();
20061                    } catch (AbstractMethodError e) {
20062                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20063                                " does not fully implement ViewParent", e);
20064                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20065                    }
20066                    switch (parentResolvedTextAlignment) {
20067                        case TEXT_ALIGNMENT_GRAVITY:
20068                        case TEXT_ALIGNMENT_TEXT_START:
20069                        case TEXT_ALIGNMENT_TEXT_END:
20070                        case TEXT_ALIGNMENT_CENTER:
20071                        case TEXT_ALIGNMENT_VIEW_START:
20072                        case TEXT_ALIGNMENT_VIEW_END:
20073                            // Resolved text alignment is the same as the parent resolved
20074                            // text alignment
20075                            mPrivateFlags2 |=
20076                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20077                            break;
20078                        default:
20079                            // Use default resolved text alignment
20080                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20081                    }
20082                    break;
20083                case TEXT_ALIGNMENT_GRAVITY:
20084                case TEXT_ALIGNMENT_TEXT_START:
20085                case TEXT_ALIGNMENT_TEXT_END:
20086                case TEXT_ALIGNMENT_CENTER:
20087                case TEXT_ALIGNMENT_VIEW_START:
20088                case TEXT_ALIGNMENT_VIEW_END:
20089                    // Resolved text alignment is the same as text alignment
20090                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20091                    break;
20092                default:
20093                    // Use default resolved text alignment
20094                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20095            }
20096        } else {
20097            // Use default resolved text alignment
20098            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20099        }
20100
20101        // Set the resolved
20102        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20103        return true;
20104    }
20105
20106    /**
20107     * Check if text alignment resolution can be done.
20108     *
20109     * @return true if text alignment resolution can be done otherwise return false.
20110     */
20111    public boolean canResolveTextAlignment() {
20112        switch (getRawTextAlignment()) {
20113            case TEXT_DIRECTION_INHERIT:
20114                if (mParent != null) {
20115                    try {
20116                        return mParent.canResolveTextAlignment();
20117                    } catch (AbstractMethodError e) {
20118                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20119                                " does not fully implement ViewParent", e);
20120                    }
20121                }
20122                return false;
20123
20124            default:
20125                return true;
20126        }
20127    }
20128
20129    /**
20130     * Reset resolved text alignment. Text alignment will be resolved during a call to
20131     * {@link #onMeasure(int, int)}.
20132     *
20133     * @hide
20134     */
20135    public void resetResolvedTextAlignment() {
20136        // Reset any previous text alignment resolution
20137        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20138        // Set to default
20139        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20140    }
20141
20142    /**
20143     * @return true if text alignment is inherited.
20144     *
20145     * @hide
20146     */
20147    public boolean isTextAlignmentInherited() {
20148        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20149    }
20150
20151    /**
20152     * @return true if text alignment is resolved.
20153     */
20154    public boolean isTextAlignmentResolved() {
20155        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20156    }
20157
20158    /**
20159     * Generate a value suitable for use in {@link #setId(int)}.
20160     * This value will not collide with ID values generated at build time by aapt for R.id.
20161     *
20162     * @return a generated ID value
20163     */
20164    public static int generateViewId() {
20165        for (;;) {
20166            final int result = sNextGeneratedId.get();
20167            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20168            int newValue = result + 1;
20169            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20170            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20171                return result;
20172            }
20173        }
20174    }
20175
20176    /**
20177     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20178     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20179     *                           a normal View or a ViewGroup with
20180     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20181     * @hide
20182     */
20183    public void captureTransitioningViews(List<View> transitioningViews) {
20184        if (getVisibility() == View.VISIBLE) {
20185            transitioningViews.add(this);
20186        }
20187    }
20188
20189    /**
20190     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20191     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20192     * @hide
20193     */
20194    public void findNamedViews(Map<String, View> namedElements) {
20195        if (getVisibility() == VISIBLE || mGhostView != null) {
20196            String transitionName = getTransitionName();
20197            if (transitionName != null) {
20198                namedElements.put(transitionName, this);
20199            }
20200        }
20201    }
20202
20203    //
20204    // Properties
20205    //
20206    /**
20207     * A Property wrapper around the <code>alpha</code> functionality handled by the
20208     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20209     */
20210    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20211        @Override
20212        public void setValue(View object, float value) {
20213            object.setAlpha(value);
20214        }
20215
20216        @Override
20217        public Float get(View object) {
20218            return object.getAlpha();
20219        }
20220    };
20221
20222    /**
20223     * A Property wrapper around the <code>translationX</code> functionality handled by the
20224     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20225     */
20226    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20227        @Override
20228        public void setValue(View object, float value) {
20229            object.setTranslationX(value);
20230        }
20231
20232                @Override
20233        public Float get(View object) {
20234            return object.getTranslationX();
20235        }
20236    };
20237
20238    /**
20239     * A Property wrapper around the <code>translationY</code> functionality handled by the
20240     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20241     */
20242    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20243        @Override
20244        public void setValue(View object, float value) {
20245            object.setTranslationY(value);
20246        }
20247
20248        @Override
20249        public Float get(View object) {
20250            return object.getTranslationY();
20251        }
20252    };
20253
20254    /**
20255     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20256     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20257     */
20258    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20259        @Override
20260        public void setValue(View object, float value) {
20261            object.setTranslationZ(value);
20262        }
20263
20264        @Override
20265        public Float get(View object) {
20266            return object.getTranslationZ();
20267        }
20268    };
20269
20270    /**
20271     * A Property wrapper around the <code>x</code> functionality handled by the
20272     * {@link View#setX(float)} and {@link View#getX()} methods.
20273     */
20274    public static final Property<View, Float> X = new FloatProperty<View>("x") {
20275        @Override
20276        public void setValue(View object, float value) {
20277            object.setX(value);
20278        }
20279
20280        @Override
20281        public Float get(View object) {
20282            return object.getX();
20283        }
20284    };
20285
20286    /**
20287     * A Property wrapper around the <code>y</code> functionality handled by the
20288     * {@link View#setY(float)} and {@link View#getY()} methods.
20289     */
20290    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20291        @Override
20292        public void setValue(View object, float value) {
20293            object.setY(value);
20294        }
20295
20296        @Override
20297        public Float get(View object) {
20298            return object.getY();
20299        }
20300    };
20301
20302    /**
20303     * A Property wrapper around the <code>z</code> functionality handled by the
20304     * {@link View#setZ(float)} and {@link View#getZ()} methods.
20305     */
20306    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20307        @Override
20308        public void setValue(View object, float value) {
20309            object.setZ(value);
20310        }
20311
20312        @Override
20313        public Float get(View object) {
20314            return object.getZ();
20315        }
20316    };
20317
20318    /**
20319     * A Property wrapper around the <code>rotation</code> functionality handled by the
20320     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20321     */
20322    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20323        @Override
20324        public void setValue(View object, float value) {
20325            object.setRotation(value);
20326        }
20327
20328        @Override
20329        public Float get(View object) {
20330            return object.getRotation();
20331        }
20332    };
20333
20334    /**
20335     * A Property wrapper around the <code>rotationX</code> functionality handled by the
20336     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20337     */
20338    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20339        @Override
20340        public void setValue(View object, float value) {
20341            object.setRotationX(value);
20342        }
20343
20344        @Override
20345        public Float get(View object) {
20346            return object.getRotationX();
20347        }
20348    };
20349
20350    /**
20351     * A Property wrapper around the <code>rotationY</code> functionality handled by the
20352     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20353     */
20354    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20355        @Override
20356        public void setValue(View object, float value) {
20357            object.setRotationY(value);
20358        }
20359
20360        @Override
20361        public Float get(View object) {
20362            return object.getRotationY();
20363        }
20364    };
20365
20366    /**
20367     * A Property wrapper around the <code>scaleX</code> functionality handled by the
20368     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20369     */
20370    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20371        @Override
20372        public void setValue(View object, float value) {
20373            object.setScaleX(value);
20374        }
20375
20376        @Override
20377        public Float get(View object) {
20378            return object.getScaleX();
20379        }
20380    };
20381
20382    /**
20383     * A Property wrapper around the <code>scaleY</code> functionality handled by the
20384     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20385     */
20386    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20387        @Override
20388        public void setValue(View object, float value) {
20389            object.setScaleY(value);
20390        }
20391
20392        @Override
20393        public Float get(View object) {
20394            return object.getScaleY();
20395        }
20396    };
20397
20398    /**
20399     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20400     * Each MeasureSpec represents a requirement for either the width or the height.
20401     * A MeasureSpec is comprised of a size and a mode. There are three possible
20402     * modes:
20403     * <dl>
20404     * <dt>UNSPECIFIED</dt>
20405     * <dd>
20406     * The parent has not imposed any constraint on the child. It can be whatever size
20407     * it wants.
20408     * </dd>
20409     *
20410     * <dt>EXACTLY</dt>
20411     * <dd>
20412     * The parent has determined an exact size for the child. The child is going to be
20413     * given those bounds regardless of how big it wants to be.
20414     * </dd>
20415     *
20416     * <dt>AT_MOST</dt>
20417     * <dd>
20418     * The child can be as large as it wants up to the specified size.
20419     * </dd>
20420     * </dl>
20421     *
20422     * MeasureSpecs are implemented as ints to reduce object allocation. This class
20423     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20424     */
20425    public static class MeasureSpec {
20426        private static final int MODE_SHIFT = 30;
20427        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
20428
20429        /**
20430         * Measure specification mode: The parent has not imposed any constraint
20431         * on the child. It can be whatever size it wants.
20432         */
20433        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20434
20435        /**
20436         * Measure specification mode: The parent has determined an exact size
20437         * for the child. The child is going to be given those bounds regardless
20438         * of how big it wants to be.
20439         */
20440        public static final int EXACTLY     = 1 << MODE_SHIFT;
20441
20442        /**
20443         * Measure specification mode: The child can be as large as it wants up
20444         * to the specified size.
20445         */
20446        public static final int AT_MOST     = 2 << MODE_SHIFT;
20447
20448        /**
20449         * Creates a measure specification based on the supplied size and mode.
20450         *
20451         * The mode must always be one of the following:
20452         * <ul>
20453         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
20454         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
20455         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
20456         * </ul>
20457         *
20458         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
20459         * implementation was such that the order of arguments did not matter
20460         * and overflow in either value could impact the resulting MeasureSpec.
20461         * {@link android.widget.RelativeLayout} was affected by this bug.
20462         * Apps targeting API levels greater than 17 will get the fixed, more strict
20463         * behavior.</p>
20464         *
20465         * @param size the size of the measure specification
20466         * @param mode the mode of the measure specification
20467         * @return the measure specification based on size and mode
20468         */
20469        public static int makeMeasureSpec(int size, int mode) {
20470            if (sUseBrokenMakeMeasureSpec) {
20471                return size + mode;
20472            } else {
20473                return (size & ~MODE_MASK) | (mode & MODE_MASK);
20474            }
20475        }
20476
20477        /**
20478         * Extracts the mode from the supplied measure specification.
20479         *
20480         * @param measureSpec the measure specification to extract the mode from
20481         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
20482         *         {@link android.view.View.MeasureSpec#AT_MOST} or
20483         *         {@link android.view.View.MeasureSpec#EXACTLY}
20484         */
20485        public static int getMode(int measureSpec) {
20486            return (measureSpec & MODE_MASK);
20487        }
20488
20489        /**
20490         * Extracts the size from the supplied measure specification.
20491         *
20492         * @param measureSpec the measure specification to extract the size from
20493         * @return the size in pixels defined in the supplied measure specification
20494         */
20495        public static int getSize(int measureSpec) {
20496            return (measureSpec & ~MODE_MASK);
20497        }
20498
20499        static int adjust(int measureSpec, int delta) {
20500            final int mode = getMode(measureSpec);
20501            int size = getSize(measureSpec);
20502            if (mode == UNSPECIFIED) {
20503                // No need to adjust size for UNSPECIFIED mode.
20504                return makeMeasureSpec(size, UNSPECIFIED);
20505            }
20506            size += delta;
20507            if (size < 0) {
20508                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
20509                        ") spec: " + toString(measureSpec) + " delta: " + delta);
20510                size = 0;
20511            }
20512            return makeMeasureSpec(size, mode);
20513        }
20514
20515        /**
20516         * Returns a String representation of the specified measure
20517         * specification.
20518         *
20519         * @param measureSpec the measure specification to convert to a String
20520         * @return a String with the following format: "MeasureSpec: MODE SIZE"
20521         */
20522        public static String toString(int measureSpec) {
20523            int mode = getMode(measureSpec);
20524            int size = getSize(measureSpec);
20525
20526            StringBuilder sb = new StringBuilder("MeasureSpec: ");
20527
20528            if (mode == UNSPECIFIED)
20529                sb.append("UNSPECIFIED ");
20530            else if (mode == EXACTLY)
20531                sb.append("EXACTLY ");
20532            else if (mode == AT_MOST)
20533                sb.append("AT_MOST ");
20534            else
20535                sb.append(mode).append(" ");
20536
20537            sb.append(size);
20538            return sb.toString();
20539        }
20540    }
20541
20542    private final class CheckForLongPress implements Runnable {
20543        private int mOriginalWindowAttachCount;
20544
20545        @Override
20546        public void run() {
20547            if (isPressed() && (mParent != null)
20548                    && mOriginalWindowAttachCount == mWindowAttachCount) {
20549                if (performLongClick()) {
20550                    mHasPerformedLongPress = true;
20551                }
20552            }
20553        }
20554
20555        public void rememberWindowAttachCount() {
20556            mOriginalWindowAttachCount = mWindowAttachCount;
20557        }
20558    }
20559
20560    private final class CheckForTap implements Runnable {
20561        public float x;
20562        public float y;
20563
20564        @Override
20565        public void run() {
20566            mPrivateFlags &= ~PFLAG_PREPRESSED;
20567            setPressed(true, x, y);
20568            checkForLongClick(ViewConfiguration.getTapTimeout());
20569        }
20570    }
20571
20572    private final class PerformClick implements Runnable {
20573        @Override
20574        public void run() {
20575            performClick();
20576        }
20577    }
20578
20579    /** @hide */
20580    public void hackTurnOffWindowResizeAnim(boolean off) {
20581        mAttachInfo.mTurnOffWindowResizeAnim = off;
20582    }
20583
20584    /**
20585     * This method returns a ViewPropertyAnimator object, which can be used to animate
20586     * specific properties on this View.
20587     *
20588     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
20589     */
20590    public ViewPropertyAnimator animate() {
20591        if (mAnimator == null) {
20592            mAnimator = new ViewPropertyAnimator(this);
20593        }
20594        return mAnimator;
20595    }
20596
20597    /**
20598     * Sets the name of the View to be used to identify Views in Transitions.
20599     * Names should be unique in the View hierarchy.
20600     *
20601     * @param transitionName The name of the View to uniquely identify it for Transitions.
20602     */
20603    public final void setTransitionName(String transitionName) {
20604        mTransitionName = transitionName;
20605    }
20606
20607    /**
20608     * Returns the name of the View to be used to identify Views in Transitions.
20609     * Names should be unique in the View hierarchy.
20610     *
20611     * <p>This returns null if the View has not been given a name.</p>
20612     *
20613     * @return The name used of the View to be used to identify Views in Transitions or null
20614     * if no name has been given.
20615     */
20616    @ViewDebug.ExportedProperty
20617    public String getTransitionName() {
20618        return mTransitionName;
20619    }
20620
20621    /**
20622     * Interface definition for a callback to be invoked when a hardware key event is
20623     * dispatched to this view. The callback will be invoked before the key event is
20624     * given to the view. This is only useful for hardware keyboards; a software input
20625     * method has no obligation to trigger this listener.
20626     */
20627    public interface OnKeyListener {
20628        /**
20629         * Called when a hardware key is dispatched to a view. This allows listeners to
20630         * get a chance to respond before the target view.
20631         * <p>Key presses in software keyboards will generally NOT trigger this method,
20632         * although some may elect to do so in some situations. Do not assume a
20633         * software input method has to be key-based; even if it is, it may use key presses
20634         * in a different way than you expect, so there is no way to reliably catch soft
20635         * input key presses.
20636         *
20637         * @param v The view the key has been dispatched to.
20638         * @param keyCode The code for the physical key that was pressed
20639         * @param event The KeyEvent object containing full information about
20640         *        the event.
20641         * @return True if the listener has consumed the event, false otherwise.
20642         */
20643        boolean onKey(View v, int keyCode, KeyEvent event);
20644    }
20645
20646    /**
20647     * Interface definition for a callback to be invoked when a touch event is
20648     * dispatched to this view. The callback will be invoked before the touch
20649     * event is given to the view.
20650     */
20651    public interface OnTouchListener {
20652        /**
20653         * Called when a touch event is dispatched to a view. This allows listeners to
20654         * get a chance to respond before the target view.
20655         *
20656         * @param v The view the touch event has been dispatched to.
20657         * @param event The MotionEvent object containing full information about
20658         *        the event.
20659         * @return True if the listener has consumed the event, false otherwise.
20660         */
20661        boolean onTouch(View v, MotionEvent event);
20662    }
20663
20664    /**
20665     * Interface definition for a callback to be invoked when a hover event is
20666     * dispatched to this view. The callback will be invoked before the hover
20667     * event is given to the view.
20668     */
20669    public interface OnHoverListener {
20670        /**
20671         * Called when a hover event is dispatched to a view. This allows listeners to
20672         * get a chance to respond before the target view.
20673         *
20674         * @param v The view the hover event has been dispatched to.
20675         * @param event The MotionEvent object containing full information about
20676         *        the event.
20677         * @return True if the listener has consumed the event, false otherwise.
20678         */
20679        boolean onHover(View v, MotionEvent event);
20680    }
20681
20682    /**
20683     * Interface definition for a callback to be invoked when a generic motion event is
20684     * dispatched to this view. The callback will be invoked before the generic motion
20685     * event is given to the view.
20686     */
20687    public interface OnGenericMotionListener {
20688        /**
20689         * Called when a generic motion event is dispatched to a view. This allows listeners to
20690         * get a chance to respond before the target view.
20691         *
20692         * @param v The view the generic motion event has been dispatched to.
20693         * @param event The MotionEvent object containing full information about
20694         *        the event.
20695         * @return True if the listener has consumed the event, false otherwise.
20696         */
20697        boolean onGenericMotion(View v, MotionEvent event);
20698    }
20699
20700    /**
20701     * Interface definition for a callback to be invoked when a view has been clicked and held.
20702     */
20703    public interface OnLongClickListener {
20704        /**
20705         * Called when a view has been clicked and held.
20706         *
20707         * @param v The view that was clicked and held.
20708         *
20709         * @return true if the callback consumed the long click, false otherwise.
20710         */
20711        boolean onLongClick(View v);
20712    }
20713
20714    /**
20715     * Interface definition for a callback to be invoked when a drag is being dispatched
20716     * to this view.  The callback will be invoked before the hosting view's own
20717     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
20718     * onDrag(event) behavior, it should return 'false' from this callback.
20719     *
20720     * <div class="special reference">
20721     * <h3>Developer Guides</h3>
20722     * <p>For a guide to implementing drag and drop features, read the
20723     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20724     * </div>
20725     */
20726    public interface OnDragListener {
20727        /**
20728         * Called when a drag event is dispatched to a view. This allows listeners
20729         * to get a chance to override base View behavior.
20730         *
20731         * @param v The View that received the drag event.
20732         * @param event The {@link android.view.DragEvent} object for the drag event.
20733         * @return {@code true} if the drag event was handled successfully, or {@code false}
20734         * if the drag event was not handled. Note that {@code false} will trigger the View
20735         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
20736         */
20737        boolean onDrag(View v, DragEvent event);
20738    }
20739
20740    /**
20741     * Interface definition for a callback to be invoked when the focus state of
20742     * a view changed.
20743     */
20744    public interface OnFocusChangeListener {
20745        /**
20746         * Called when the focus state of a view has changed.
20747         *
20748         * @param v The view whose state has changed.
20749         * @param hasFocus The new focus state of v.
20750         */
20751        void onFocusChange(View v, boolean hasFocus);
20752    }
20753
20754    /**
20755     * Interface definition for a callback to be invoked when a view is clicked.
20756     */
20757    public interface OnClickListener {
20758        /**
20759         * Called when a view has been clicked.
20760         *
20761         * @param v The view that was clicked.
20762         */
20763        void onClick(View v);
20764    }
20765
20766    /**
20767     * Interface definition for a callback to be invoked when the context menu
20768     * for this view is being built.
20769     */
20770    public interface OnCreateContextMenuListener {
20771        /**
20772         * Called when the context menu for this view is being built. It is not
20773         * safe to hold onto the menu after this method returns.
20774         *
20775         * @param menu The context menu that is being built
20776         * @param v The view for which the context menu is being built
20777         * @param menuInfo Extra information about the item for which the
20778         *            context menu should be shown. This information will vary
20779         *            depending on the class of v.
20780         */
20781        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
20782    }
20783
20784    /**
20785     * Interface definition for a callback to be invoked when the status bar changes
20786     * visibility.  This reports <strong>global</strong> changes to the system UI
20787     * state, not what the application is requesting.
20788     *
20789     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
20790     */
20791    public interface OnSystemUiVisibilityChangeListener {
20792        /**
20793         * Called when the status bar changes visibility because of a call to
20794         * {@link View#setSystemUiVisibility(int)}.
20795         *
20796         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20797         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
20798         * This tells you the <strong>global</strong> state of these UI visibility
20799         * flags, not what your app is currently applying.
20800         */
20801        public void onSystemUiVisibilityChange(int visibility);
20802    }
20803
20804    /**
20805     * Interface definition for a callback to be invoked when this view is attached
20806     * or detached from its window.
20807     */
20808    public interface OnAttachStateChangeListener {
20809        /**
20810         * Called when the view is attached to a window.
20811         * @param v The view that was attached
20812         */
20813        public void onViewAttachedToWindow(View v);
20814        /**
20815         * Called when the view is detached from a window.
20816         * @param v The view that was detached
20817         */
20818        public void onViewDetachedFromWindow(View v);
20819    }
20820
20821    /**
20822     * Listener for applying window insets on a view in a custom way.
20823     *
20824     * <p>Apps may choose to implement this interface if they want to apply custom policy
20825     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20826     * is set, its
20827     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20828     * method will be called instead of the View's own
20829     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20830     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20831     * the View's normal behavior as part of its own.</p>
20832     */
20833    public interface OnApplyWindowInsetsListener {
20834        /**
20835         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20836         * on a View, this listener method will be called instead of the view's own
20837         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20838         *
20839         * @param v The view applying window insets
20840         * @param insets The insets to apply
20841         * @return The insets supplied, minus any insets that were consumed
20842         */
20843        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20844    }
20845
20846    private final class UnsetPressedState implements Runnable {
20847        @Override
20848        public void run() {
20849            setPressed(false);
20850        }
20851    }
20852
20853    /**
20854     * Base class for derived classes that want to save and restore their own
20855     * state in {@link android.view.View#onSaveInstanceState()}.
20856     */
20857    public static class BaseSavedState extends AbsSavedState {
20858        String mStartActivityRequestWhoSaved;
20859
20860        /**
20861         * Constructor used when reading from a parcel. Reads the state of the superclass.
20862         *
20863         * @param source
20864         */
20865        public BaseSavedState(Parcel source) {
20866            super(source);
20867            mStartActivityRequestWhoSaved = source.readString();
20868        }
20869
20870        /**
20871         * Constructor called by derived classes when creating their SavedState objects
20872         *
20873         * @param superState The state of the superclass of this view
20874         */
20875        public BaseSavedState(Parcelable superState) {
20876            super(superState);
20877        }
20878
20879        @Override
20880        public void writeToParcel(Parcel out, int flags) {
20881            super.writeToParcel(out, flags);
20882            out.writeString(mStartActivityRequestWhoSaved);
20883        }
20884
20885        public static final Parcelable.Creator<BaseSavedState> CREATOR =
20886                new Parcelable.Creator<BaseSavedState>() {
20887            public BaseSavedState createFromParcel(Parcel in) {
20888                return new BaseSavedState(in);
20889            }
20890
20891            public BaseSavedState[] newArray(int size) {
20892                return new BaseSavedState[size];
20893            }
20894        };
20895    }
20896
20897    /**
20898     * A set of information given to a view when it is attached to its parent
20899     * window.
20900     */
20901    final static class AttachInfo {
20902        interface Callbacks {
20903            void playSoundEffect(int effectId);
20904            boolean performHapticFeedback(int effectId, boolean always);
20905        }
20906
20907        /**
20908         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20909         * to a Handler. This class contains the target (View) to invalidate and
20910         * the coordinates of the dirty rectangle.
20911         *
20912         * For performance purposes, this class also implements a pool of up to
20913         * POOL_LIMIT objects that get reused. This reduces memory allocations
20914         * whenever possible.
20915         */
20916        static class InvalidateInfo {
20917            private static final int POOL_LIMIT = 10;
20918
20919            private static final SynchronizedPool<InvalidateInfo> sPool =
20920                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20921
20922            View target;
20923
20924            int left;
20925            int top;
20926            int right;
20927            int bottom;
20928
20929            public static InvalidateInfo obtain() {
20930                InvalidateInfo instance = sPool.acquire();
20931                return (instance != null) ? instance : new InvalidateInfo();
20932            }
20933
20934            public void recycle() {
20935                target = null;
20936                sPool.release(this);
20937            }
20938        }
20939
20940        final IWindowSession mSession;
20941
20942        final IWindow mWindow;
20943
20944        final IBinder mWindowToken;
20945
20946        final Display mDisplay;
20947
20948        final Callbacks mRootCallbacks;
20949
20950        IWindowId mIWindowId;
20951        WindowId mWindowId;
20952
20953        /**
20954         * The top view of the hierarchy.
20955         */
20956        View mRootView;
20957
20958        IBinder mPanelParentWindowToken;
20959
20960        boolean mHardwareAccelerated;
20961        boolean mHardwareAccelerationRequested;
20962        HardwareRenderer mHardwareRenderer;
20963        List<RenderNode> mPendingAnimatingRenderNodes;
20964
20965        /**
20966         * The state of the display to which the window is attached, as reported
20967         * by {@link Display#getState()}.  Note that the display state constants
20968         * declared by {@link Display} do not exactly line up with the screen state
20969         * constants declared by {@link View} (there are more display states than
20970         * screen states).
20971         */
20972        int mDisplayState = Display.STATE_UNKNOWN;
20973
20974        /**
20975         * Scale factor used by the compatibility mode
20976         */
20977        float mApplicationScale;
20978
20979        /**
20980         * Indicates whether the application is in compatibility mode
20981         */
20982        boolean mScalingRequired;
20983
20984        /**
20985         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20986         */
20987        boolean mTurnOffWindowResizeAnim;
20988
20989        /**
20990         * Left position of this view's window
20991         */
20992        int mWindowLeft;
20993
20994        /**
20995         * Top position of this view's window
20996         */
20997        int mWindowTop;
20998
20999        /**
21000         * Indicates whether views need to use 32-bit drawing caches
21001         */
21002        boolean mUse32BitDrawingCache;
21003
21004        /**
21005         * For windows that are full-screen but using insets to layout inside
21006         * of the screen areas, these are the current insets to appear inside
21007         * the overscan area of the display.
21008         */
21009        final Rect mOverscanInsets = new Rect();
21010
21011        /**
21012         * For windows that are full-screen but using insets to layout inside
21013         * of the screen decorations, these are the current insets for the
21014         * content of the window.
21015         */
21016        final Rect mContentInsets = new Rect();
21017
21018        /**
21019         * For windows that are full-screen but using insets to layout inside
21020         * of the screen decorations, these are the current insets for the
21021         * actual visible parts of the window.
21022         */
21023        final Rect mVisibleInsets = new Rect();
21024
21025        /**
21026         * For windows that are full-screen but using insets to layout inside
21027         * of the screen decorations, these are the current insets for the
21028         * stable system windows.
21029         */
21030        final Rect mStableInsets = new Rect();
21031
21032        /**
21033         * The internal insets given by this window.  This value is
21034         * supplied by the client (through
21035         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21036         * be given to the window manager when changed to be used in laying
21037         * out windows behind it.
21038         */
21039        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21040                = new ViewTreeObserver.InternalInsetsInfo();
21041
21042        /**
21043         * Set to true when mGivenInternalInsets is non-empty.
21044         */
21045        boolean mHasNonEmptyGivenInternalInsets;
21046
21047        /**
21048         * All views in the window's hierarchy that serve as scroll containers,
21049         * used to determine if the window can be resized or must be panned
21050         * to adjust for a soft input area.
21051         */
21052        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21053
21054        final KeyEvent.DispatcherState mKeyDispatchState
21055                = new KeyEvent.DispatcherState();
21056
21057        /**
21058         * Indicates whether the view's window currently has the focus.
21059         */
21060        boolean mHasWindowFocus;
21061
21062        /**
21063         * The current visibility of the window.
21064         */
21065        int mWindowVisibility;
21066
21067        /**
21068         * Indicates the time at which drawing started to occur.
21069         */
21070        long mDrawingTime;
21071
21072        /**
21073         * Indicates whether or not ignoring the DIRTY_MASK flags.
21074         */
21075        boolean mIgnoreDirtyState;
21076
21077        /**
21078         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21079         * to avoid clearing that flag prematurely.
21080         */
21081        boolean mSetIgnoreDirtyState = false;
21082
21083        /**
21084         * Indicates whether the view's window is currently in touch mode.
21085         */
21086        boolean mInTouchMode;
21087
21088        /**
21089         * Indicates whether the view has requested unbuffered input dispatching for the current
21090         * event stream.
21091         */
21092        boolean mUnbufferedDispatchRequested;
21093
21094        /**
21095         * Indicates that ViewAncestor should trigger a global layout change
21096         * the next time it performs a traversal
21097         */
21098        boolean mRecomputeGlobalAttributes;
21099
21100        /**
21101         * Always report new attributes at next traversal.
21102         */
21103        boolean mForceReportNewAttributes;
21104
21105        /**
21106         * Set during a traveral if any views want to keep the screen on.
21107         */
21108        boolean mKeepScreenOn;
21109
21110        /**
21111         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21112         */
21113        int mSystemUiVisibility;
21114
21115        /**
21116         * Hack to force certain system UI visibility flags to be cleared.
21117         */
21118        int mDisabledSystemUiVisibility;
21119
21120        /**
21121         * Last global system UI visibility reported by the window manager.
21122         */
21123        int mGlobalSystemUiVisibility;
21124
21125        /**
21126         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21127         * attached.
21128         */
21129        boolean mHasSystemUiListeners;
21130
21131        /**
21132         * Set if the window has requested to extend into the overscan region
21133         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21134         */
21135        boolean mOverscanRequested;
21136
21137        /**
21138         * Set if the visibility of any views has changed.
21139         */
21140        boolean mViewVisibilityChanged;
21141
21142        /**
21143         * Set to true if a view has been scrolled.
21144         */
21145        boolean mViewScrollChanged;
21146
21147        /**
21148         * Set to true if high contrast mode enabled
21149         */
21150        boolean mHighContrastText;
21151
21152        /**
21153         * Global to the view hierarchy used as a temporary for dealing with
21154         * x/y points in the transparent region computations.
21155         */
21156        final int[] mTransparentLocation = new int[2];
21157
21158        /**
21159         * Global to the view hierarchy used as a temporary for dealing with
21160         * x/y points in the ViewGroup.invalidateChild implementation.
21161         */
21162        final int[] mInvalidateChildLocation = new int[2];
21163
21164        /**
21165         * Global to the view hierarchy used as a temporary for dealng with
21166         * computing absolute on-screen location.
21167         */
21168        final int[] mTmpLocation = new int[2];
21169
21170        /**
21171         * Global to the view hierarchy used as a temporary for dealing with
21172         * x/y location when view is transformed.
21173         */
21174        final float[] mTmpTransformLocation = new float[2];
21175
21176        /**
21177         * The view tree observer used to dispatch global events like
21178         * layout, pre-draw, touch mode change, etc.
21179         */
21180        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21181
21182        /**
21183         * A Canvas used by the view hierarchy to perform bitmap caching.
21184         */
21185        Canvas mCanvas;
21186
21187        /**
21188         * The view root impl.
21189         */
21190        final ViewRootImpl mViewRootImpl;
21191
21192        /**
21193         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21194         * handler can be used to pump events in the UI events queue.
21195         */
21196        final Handler mHandler;
21197
21198        /**
21199         * Temporary for use in computing invalidate rectangles while
21200         * calling up the hierarchy.
21201         */
21202        final Rect mTmpInvalRect = new Rect();
21203
21204        /**
21205         * Temporary for use in computing hit areas with transformed views
21206         */
21207        final RectF mTmpTransformRect = new RectF();
21208
21209        /**
21210         * Temporary for use in computing hit areas with transformed views
21211         */
21212        final RectF mTmpTransformRect1 = new RectF();
21213
21214        /**
21215         * Temporary list of rectanges.
21216         */
21217        final List<RectF> mTmpRectList = new ArrayList<>();
21218
21219        /**
21220         * Temporary for use in transforming invalidation rect
21221         */
21222        final Matrix mTmpMatrix = new Matrix();
21223
21224        /**
21225         * Temporary for use in transforming invalidation rect
21226         */
21227        final Transformation mTmpTransformation = new Transformation();
21228
21229        /**
21230         * Temporary for use in querying outlines from OutlineProviders
21231         */
21232        final Outline mTmpOutline = new Outline();
21233
21234        /**
21235         * Temporary list for use in collecting focusable descendents of a view.
21236         */
21237        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21238
21239        /**
21240         * The id of the window for accessibility purposes.
21241         */
21242        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21243
21244        /**
21245         * Flags related to accessibility processing.
21246         *
21247         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21248         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21249         */
21250        int mAccessibilityFetchFlags;
21251
21252        /**
21253         * The drawable for highlighting accessibility focus.
21254         */
21255        Drawable mAccessibilityFocusDrawable;
21256
21257        /**
21258         * Show where the margins, bounds and layout bounds are for each view.
21259         */
21260        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21261
21262        /**
21263         * Point used to compute visible regions.
21264         */
21265        final Point mPoint = new Point();
21266
21267        /**
21268         * Used to track which View originated a requestLayout() call, used when
21269         * requestLayout() is called during layout.
21270         */
21271        View mViewRequestingLayout;
21272
21273        /**
21274         * Creates a new set of attachment information with the specified
21275         * events handler and thread.
21276         *
21277         * @param handler the events handler the view must use
21278         */
21279        AttachInfo(IWindowSession session, IWindow window, Display display,
21280                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21281            mSession = session;
21282            mWindow = window;
21283            mWindowToken = window.asBinder();
21284            mDisplay = display;
21285            mViewRootImpl = viewRootImpl;
21286            mHandler = handler;
21287            mRootCallbacks = effectPlayer;
21288        }
21289    }
21290
21291    /**
21292     * <p>ScrollabilityCache holds various fields used by a View when scrolling
21293     * is supported. This avoids keeping too many unused fields in most
21294     * instances of View.</p>
21295     */
21296    private static class ScrollabilityCache implements Runnable {
21297
21298        /**
21299         * Scrollbars are not visible
21300         */
21301        public static final int OFF = 0;
21302
21303        /**
21304         * Scrollbars are visible
21305         */
21306        public static final int ON = 1;
21307
21308        /**
21309         * Scrollbars are fading away
21310         */
21311        public static final int FADING = 2;
21312
21313        public boolean fadeScrollBars;
21314
21315        public int fadingEdgeLength;
21316        public int scrollBarDefaultDelayBeforeFade;
21317        public int scrollBarFadeDuration;
21318
21319        public int scrollBarSize;
21320        public ScrollBarDrawable scrollBar;
21321        public float[] interpolatorValues;
21322        public View host;
21323
21324        public final Paint paint;
21325        public final Matrix matrix;
21326        public Shader shader;
21327
21328        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21329
21330        private static final float[] OPAQUE = { 255 };
21331        private static final float[] TRANSPARENT = { 0.0f };
21332
21333        /**
21334         * When fading should start. This time moves into the future every time
21335         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21336         */
21337        public long fadeStartTime;
21338
21339
21340        /**
21341         * The current state of the scrollbars: ON, OFF, or FADING
21342         */
21343        public int state = OFF;
21344
21345        private int mLastColor;
21346
21347        public ScrollabilityCache(ViewConfiguration configuration, View host) {
21348            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21349            scrollBarSize = configuration.getScaledScrollBarSize();
21350            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21351            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21352
21353            paint = new Paint();
21354            matrix = new Matrix();
21355            // use use a height of 1, and then wack the matrix each time we
21356            // actually use it.
21357            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21358            paint.setShader(shader);
21359            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21360
21361            this.host = host;
21362        }
21363
21364        public void setFadeColor(int color) {
21365            if (color != mLastColor) {
21366                mLastColor = color;
21367
21368                if (color != 0) {
21369                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21370                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21371                    paint.setShader(shader);
21372                    // Restore the default transfer mode (src_over)
21373                    paint.setXfermode(null);
21374                } else {
21375                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21376                    paint.setShader(shader);
21377                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21378                }
21379            }
21380        }
21381
21382        public void run() {
21383            long now = AnimationUtils.currentAnimationTimeMillis();
21384            if (now >= fadeStartTime) {
21385
21386                // the animation fades the scrollbars out by changing
21387                // the opacity (alpha) from fully opaque to fully
21388                // transparent
21389                int nextFrame = (int) now;
21390                int framesCount = 0;
21391
21392                Interpolator interpolator = scrollBarInterpolator;
21393
21394                // Start opaque
21395                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21396
21397                // End transparent
21398                nextFrame += scrollBarFadeDuration;
21399                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21400
21401                state = FADING;
21402
21403                // Kick off the fade animation
21404                host.invalidate(true);
21405            }
21406        }
21407    }
21408
21409    /**
21410     * Resuable callback for sending
21411     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
21412     */
21413    private class SendViewScrolledAccessibilityEvent implements Runnable {
21414        public volatile boolean mIsPending;
21415
21416        public void run() {
21417            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
21418            mIsPending = false;
21419        }
21420    }
21421
21422    /**
21423     * <p>
21424     * This class represents a delegate that can be registered in a {@link View}
21425     * to enhance accessibility support via composition rather via inheritance.
21426     * It is specifically targeted to widget developers that extend basic View
21427     * classes i.e. classes in package android.view, that would like their
21428     * applications to be backwards compatible.
21429     * </p>
21430     * <div class="special reference">
21431     * <h3>Developer Guides</h3>
21432     * <p>For more information about making applications accessible, read the
21433     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
21434     * developer guide.</p>
21435     * </div>
21436     * <p>
21437     * A scenario in which a developer would like to use an accessibility delegate
21438     * is overriding a method introduced in a later API version then the minimal API
21439     * version supported by the application. For example, the method
21440     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
21441     * in API version 4 when the accessibility APIs were first introduced. If a
21442     * developer would like his application to run on API version 4 devices (assuming
21443     * all other APIs used by the application are version 4 or lower) and take advantage
21444     * of this method, instead of overriding the method which would break the application's
21445     * backwards compatibility, he can override the corresponding method in this
21446     * delegate and register the delegate in the target View if the API version of
21447     * the system is high enough i.e. the API version is same or higher to the API
21448     * version that introduced
21449     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
21450     * </p>
21451     * <p>
21452     * Here is an example implementation:
21453     * </p>
21454     * <code><pre><p>
21455     * if (Build.VERSION.SDK_INT >= 14) {
21456     *     // If the API version is equal of higher than the version in
21457     *     // which onInitializeAccessibilityNodeInfo was introduced we
21458     *     // register a delegate with a customized implementation.
21459     *     View view = findViewById(R.id.view_id);
21460     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
21461     *         public void onInitializeAccessibilityNodeInfo(View host,
21462     *                 AccessibilityNodeInfo info) {
21463     *             // Let the default implementation populate the info.
21464     *             super.onInitializeAccessibilityNodeInfo(host, info);
21465     *             // Set some other information.
21466     *             info.setEnabled(host.isEnabled());
21467     *         }
21468     *     });
21469     * }
21470     * </code></pre></p>
21471     * <p>
21472     * This delegate contains methods that correspond to the accessibility methods
21473     * in View. If a delegate has been specified the implementation in View hands
21474     * off handling to the corresponding method in this delegate. The default
21475     * implementation the delegate methods behaves exactly as the corresponding
21476     * method in View for the case of no accessibility delegate been set. Hence,
21477     * to customize the behavior of a View method, clients can override only the
21478     * corresponding delegate method without altering the behavior of the rest
21479     * accessibility related methods of the host view.
21480     * </p>
21481     */
21482    public static class AccessibilityDelegate {
21483
21484        /**
21485         * Sends an accessibility event of the given type. If accessibility is not
21486         * enabled this method has no effect.
21487         * <p>
21488         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
21489         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
21490         * been set.
21491         * </p>
21492         *
21493         * @param host The View hosting the delegate.
21494         * @param eventType The type of the event to send.
21495         *
21496         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
21497         */
21498        public void sendAccessibilityEvent(View host, int eventType) {
21499            host.sendAccessibilityEventInternal(eventType);
21500        }
21501
21502        /**
21503         * Performs the specified accessibility action on the view. For
21504         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
21505         * <p>
21506         * The default implementation behaves as
21507         * {@link View#performAccessibilityAction(int, Bundle)
21508         *  View#performAccessibilityAction(int, Bundle)} for the case of
21509         *  no accessibility delegate been set.
21510         * </p>
21511         *
21512         * @param action The action to perform.
21513         * @return Whether the action was performed.
21514         *
21515         * @see View#performAccessibilityAction(int, Bundle)
21516         *      View#performAccessibilityAction(int, Bundle)
21517         */
21518        public boolean performAccessibilityAction(View host, int action, Bundle args) {
21519            return host.performAccessibilityActionInternal(action, args);
21520        }
21521
21522        /**
21523         * Sends an accessibility event. This method behaves exactly as
21524         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
21525         * empty {@link AccessibilityEvent} and does not perform a check whether
21526         * accessibility is enabled.
21527         * <p>
21528         * The default implementation behaves as
21529         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21530         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
21531         * the case of no accessibility delegate been set.
21532         * </p>
21533         *
21534         * @param host The View hosting the delegate.
21535         * @param event The event to send.
21536         *
21537         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21538         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21539         */
21540        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
21541            host.sendAccessibilityEventUncheckedInternal(event);
21542        }
21543
21544        /**
21545         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
21546         * to its children for adding their text content to the event.
21547         * <p>
21548         * The default implementation behaves as
21549         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21550         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
21551         * the case of no accessibility delegate been set.
21552         * </p>
21553         *
21554         * @param host The View hosting the delegate.
21555         * @param event The event.
21556         * @return True if the event population was completed.
21557         *
21558         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21559         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21560         */
21561        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
21562            return host.dispatchPopulateAccessibilityEventInternal(event);
21563        }
21564
21565        /**
21566         * Gives a chance to the host View to populate the accessibility event with its
21567         * text content.
21568         * <p>
21569         * The default implementation behaves as
21570         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
21571         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
21572         * the case of no accessibility delegate been set.
21573         * </p>
21574         *
21575         * @param host The View hosting the delegate.
21576         * @param event The accessibility event which to populate.
21577         *
21578         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
21579         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
21580         */
21581        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
21582            host.onPopulateAccessibilityEventInternal(event);
21583        }
21584
21585        /**
21586         * Initializes an {@link AccessibilityEvent} with information about the
21587         * the host View which is the event source.
21588         * <p>
21589         * The default implementation behaves as
21590         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
21591         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
21592         * the case of no accessibility delegate been set.
21593         * </p>
21594         *
21595         * @param host The View hosting the delegate.
21596         * @param event The event to initialize.
21597         *
21598         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
21599         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
21600         */
21601        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
21602            host.onInitializeAccessibilityEventInternal(event);
21603        }
21604
21605        /**
21606         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
21607         * <p>
21608         * The default implementation behaves as
21609         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21610         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
21611         * the case of no accessibility delegate been set.
21612         * </p>
21613         *
21614         * @param host The View hosting the delegate.
21615         * @param info The instance to initialize.
21616         *
21617         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21618         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21619         */
21620        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
21621            host.onInitializeAccessibilityNodeInfoInternal(info);
21622        }
21623
21624        /**
21625         * Called when a child of the host View has requested sending an
21626         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
21627         * to augment the event.
21628         * <p>
21629         * The default implementation behaves as
21630         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21631         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
21632         * the case of no accessibility delegate been set.
21633         * </p>
21634         *
21635         * @param host The View hosting the delegate.
21636         * @param child The child which requests sending the event.
21637         * @param event The event to be sent.
21638         * @return True if the event should be sent
21639         *
21640         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21641         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21642         */
21643        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
21644                AccessibilityEvent event) {
21645            return host.onRequestSendAccessibilityEventInternal(child, event);
21646        }
21647
21648        /**
21649         * Gets the provider for managing a virtual view hierarchy rooted at this View
21650         * and reported to {@link android.accessibilityservice.AccessibilityService}s
21651         * that explore the window content.
21652         * <p>
21653         * The default implementation behaves as
21654         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
21655         * the case of no accessibility delegate been set.
21656         * </p>
21657         *
21658         * @return The provider.
21659         *
21660         * @see AccessibilityNodeProvider
21661         */
21662        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
21663            return null;
21664        }
21665
21666        /**
21667         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
21668         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
21669         * This method is responsible for obtaining an accessibility node info from a
21670         * pool of reusable instances and calling
21671         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
21672         * view to initialize the former.
21673         * <p>
21674         * <strong>Note:</strong> The client is responsible for recycling the obtained
21675         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
21676         * creation.
21677         * </p>
21678         * <p>
21679         * The default implementation behaves as
21680         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
21681         * the case of no accessibility delegate been set.
21682         * </p>
21683         * @return A populated {@link AccessibilityNodeInfo}.
21684         *
21685         * @see AccessibilityNodeInfo
21686         *
21687         * @hide
21688         */
21689        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
21690            return host.createAccessibilityNodeInfoInternal();
21691        }
21692    }
21693
21694    private class MatchIdPredicate implements Predicate<View> {
21695        public int mId;
21696
21697        @Override
21698        public boolean apply(View view) {
21699            return (view.mID == mId);
21700        }
21701    }
21702
21703    private class MatchLabelForPredicate implements Predicate<View> {
21704        private int mLabeledId;
21705
21706        @Override
21707        public boolean apply(View view) {
21708            return (view.mLabelForId == mLabeledId);
21709        }
21710    }
21711
21712    private class SendViewStateChangedAccessibilityEvent implements Runnable {
21713        private int mChangeTypes = 0;
21714        private boolean mPosted;
21715        private boolean mPostedWithDelay;
21716        private long mLastEventTimeMillis;
21717
21718        @Override
21719        public void run() {
21720            mPosted = false;
21721            mPostedWithDelay = false;
21722            mLastEventTimeMillis = SystemClock.uptimeMillis();
21723            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21724                final AccessibilityEvent event = AccessibilityEvent.obtain();
21725                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
21726                event.setContentChangeTypes(mChangeTypes);
21727                sendAccessibilityEventUnchecked(event);
21728            }
21729            mChangeTypes = 0;
21730        }
21731
21732        public void runOrPost(int changeType) {
21733            mChangeTypes |= changeType;
21734
21735            // If this is a live region or the child of a live region, collect
21736            // all events from this frame and send them on the next frame.
21737            if (inLiveRegion()) {
21738                // If we're already posted with a delay, remove that.
21739                if (mPostedWithDelay) {
21740                    removeCallbacks(this);
21741                    mPostedWithDelay = false;
21742                }
21743                // Only post if we're not already posted.
21744                if (!mPosted) {
21745                    post(this);
21746                    mPosted = true;
21747                }
21748                return;
21749            }
21750
21751            if (mPosted) {
21752                return;
21753            }
21754
21755            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
21756            final long minEventIntevalMillis =
21757                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
21758            if (timeSinceLastMillis >= minEventIntevalMillis) {
21759                removeCallbacks(this);
21760                run();
21761            } else {
21762                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
21763                mPostedWithDelay = true;
21764            }
21765        }
21766    }
21767
21768    private boolean inLiveRegion() {
21769        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21770            return true;
21771        }
21772
21773        ViewParent parent = getParent();
21774        while (parent instanceof View) {
21775            if (((View) parent).getAccessibilityLiveRegion()
21776                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21777                return true;
21778            }
21779            parent = parent.getParent();
21780        }
21781
21782        return false;
21783    }
21784
21785    /**
21786     * Dump all private flags in readable format, useful for documentation and
21787     * sanity checking.
21788     */
21789    private static void dumpFlags() {
21790        final HashMap<String, String> found = Maps.newHashMap();
21791        try {
21792            for (Field field : View.class.getDeclaredFields()) {
21793                final int modifiers = field.getModifiers();
21794                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
21795                    if (field.getType().equals(int.class)) {
21796                        final int value = field.getInt(null);
21797                        dumpFlag(found, field.getName(), value);
21798                    } else if (field.getType().equals(int[].class)) {
21799                        final int[] values = (int[]) field.get(null);
21800                        for (int i = 0; i < values.length; i++) {
21801                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
21802                        }
21803                    }
21804                }
21805            }
21806        } catch (IllegalAccessException e) {
21807            throw new RuntimeException(e);
21808        }
21809
21810        final ArrayList<String> keys = Lists.newArrayList();
21811        keys.addAll(found.keySet());
21812        Collections.sort(keys);
21813        for (String key : keys) {
21814            Log.d(VIEW_LOG_TAG, found.get(key));
21815        }
21816    }
21817
21818    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21819        // Sort flags by prefix, then by bits, always keeping unique keys
21820        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21821        final int prefix = name.indexOf('_');
21822        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21823        final String output = bits + " " + name;
21824        found.put(key, output);
21825    }
21826}
21827