View.java revision c0a1b7f9a6a496deb68b095d122ca85f22daad98
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.ColorInt;
22import android.annotation.DrawableRes;
23import android.annotation.IdRes;
24import android.annotation.IntDef;
25import android.annotation.NonNull;
26import android.annotation.Nullable;
27import android.content.ClipData;
28import android.content.Context;
29import android.content.res.ColorStateList;
30import android.content.res.Configuration;
31import android.content.res.Resources;
32import android.content.res.TypedArray;
33import android.graphics.Bitmap;
34import android.graphics.Canvas;
35import android.graphics.Insets;
36import android.graphics.Interpolator;
37import android.graphics.LinearGradient;
38import android.graphics.Matrix;
39import android.graphics.Outline;
40import android.graphics.Paint;
41import android.graphics.PixelFormat;
42import android.graphics.Point;
43import android.graphics.PorterDuff;
44import android.graphics.PorterDuffXfermode;
45import android.graphics.Rect;
46import android.graphics.RectF;
47import android.graphics.Region;
48import android.graphics.Shader;
49import android.graphics.drawable.ColorDrawable;
50import android.graphics.drawable.Drawable;
51import android.hardware.display.DisplayManagerGlobal;
52import android.os.Bundle;
53import android.os.Handler;
54import android.os.IBinder;
55import android.os.Parcel;
56import android.os.Parcelable;
57import android.os.RemoteException;
58import android.os.SystemClock;
59import android.os.SystemProperties;
60import android.os.Trace;
61import android.text.TextUtils;
62import android.util.AttributeSet;
63import android.util.FloatProperty;
64import android.util.LayoutDirection;
65import android.util.Log;
66import android.util.LongSparseLongArray;
67import android.util.Pools.SynchronizedPool;
68import android.util.Property;
69import android.util.SparseArray;
70import android.util.StateSet;
71import android.util.SuperNotCalledException;
72import android.util.TypedValue;
73import android.view.ContextMenu.ContextMenuInfo;
74import android.view.AccessibilityIterators.TextSegmentIterator;
75import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
76import android.view.AccessibilityIterators.WordTextSegmentIterator;
77import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
78import android.view.accessibility.AccessibilityEvent;
79import android.view.accessibility.AccessibilityEventSource;
80import android.view.accessibility.AccessibilityManager;
81import android.view.accessibility.AccessibilityNodeInfo;
82import android.view.accessibility.AccessibilityNodeProvider;
83import android.view.animation.Animation;
84import android.view.animation.AnimationUtils;
85import android.view.animation.Transformation;
86import android.view.inputmethod.EditorInfo;
87import android.view.inputmethod.InputConnection;
88import android.view.inputmethod.InputMethodManager;
89import android.widget.ScrollBarDrawable;
90
91import static android.os.Build.VERSION_CODES.*;
92import static java.lang.Math.max;
93
94import com.android.internal.R;
95import com.android.internal.util.Predicate;
96import com.android.internal.view.menu.MenuBuilder;
97import com.google.android.collect.Lists;
98import com.google.android.collect.Maps;
99
100import java.lang.annotation.Retention;
101import java.lang.annotation.RetentionPolicy;
102import java.lang.ref.WeakReference;
103import java.lang.reflect.Field;
104import java.lang.reflect.InvocationTargetException;
105import java.lang.reflect.Method;
106import java.lang.reflect.Modifier;
107import java.util.ArrayList;
108import java.util.Arrays;
109import java.util.Collections;
110import java.util.HashMap;
111import java.util.List;
112import java.util.Locale;
113import java.util.Map;
114import java.util.concurrent.CopyOnWriteArrayList;
115import java.util.concurrent.atomic.AtomicInteger;
116
117/**
118 * <p>
119 * This class represents the basic building block for user interface components. A View
120 * occupies a rectangular area on the screen and is responsible for drawing and
121 * event handling. View is the base class for <em>widgets</em>, which are
122 * used to create interactive UI components (buttons, text fields, etc.). The
123 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
124 * are invisible containers that hold other Views (or other ViewGroups) and define
125 * their layout properties.
126 * </p>
127 *
128 * <div class="special reference">
129 * <h3>Developer Guides</h3>
130 * <p>For information about using this class to develop your application's user interface,
131 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
132 * </div>
133 *
134 * <a name="Using"></a>
135 * <h3>Using Views</h3>
136 * <p>
137 * All of the views in a window are arranged in a single tree. You can add views
138 * either from code or by specifying a tree of views in one or more XML layout
139 * files. There are many specialized subclasses of views that act as controls or
140 * are capable of displaying text, images, or other content.
141 * </p>
142 * <p>
143 * Once you have created a tree of views, there are typically a few types of
144 * common operations you may wish to perform:
145 * <ul>
146 * <li><strong>Set properties:</strong> for example setting the text of a
147 * {@link android.widget.TextView}. The available properties and the methods
148 * that set them will vary among the different subclasses of views. Note that
149 * properties that are known at build time can be set in the XML layout
150 * files.</li>
151 * <li><strong>Set focus:</strong> The framework will handled moving focus in
152 * response to user input. To force focus to a specific view, call
153 * {@link #requestFocus}.</li>
154 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
155 * that will be notified when something interesting happens to the view. For
156 * example, all views will let you set a listener to be notified when the view
157 * gains or loses focus. You can register such a listener using
158 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
159 * Other view subclasses offer more specialized listeners. For example, a Button
160 * exposes a listener to notify clients when the button is clicked.</li>
161 * <li><strong>Set visibility:</strong> You can hide or show views using
162 * {@link #setVisibility(int)}.</li>
163 * </ul>
164 * </p>
165 * <p><em>
166 * Note: The Android framework is responsible for measuring, laying out and
167 * drawing views. You should not call methods that perform these actions on
168 * views yourself unless you are actually implementing a
169 * {@link android.view.ViewGroup}.
170 * </em></p>
171 *
172 * <a name="Lifecycle"></a>
173 * <h3>Implementing a Custom View</h3>
174 *
175 * <p>
176 * To implement a custom view, you will usually begin by providing overrides for
177 * some of the standard methods that the framework calls on all views. You do
178 * not need to override all of these methods. In fact, you can start by just
179 * overriding {@link #onDraw(android.graphics.Canvas)}.
180 * <table border="2" width="85%" align="center" cellpadding="5">
181 *     <thead>
182 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
183 *     </thead>
184 *
185 *     <tbody>
186 *     <tr>
187 *         <td rowspan="2">Creation</td>
188 *         <td>Constructors</td>
189 *         <td>There is a form of the constructor that are called when the view
190 *         is created from code and a form that is called when the view is
191 *         inflated from a layout file. The second form should parse and apply
192 *         any attributes defined in the layout file.
193 *         </td>
194 *     </tr>
195 *     <tr>
196 *         <td><code>{@link #onFinishInflate()}</code></td>
197 *         <td>Called after a view and all of its children has been inflated
198 *         from XML.</td>
199 *     </tr>
200 *
201 *     <tr>
202 *         <td rowspan="3">Layout</td>
203 *         <td><code>{@link #onMeasure(int, int)}</code></td>
204 *         <td>Called to determine the size requirements for this view and all
205 *         of its children.
206 *         </td>
207 *     </tr>
208 *     <tr>
209 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
210 *         <td>Called when this view should assign a size and position to all
211 *         of its children.
212 *         </td>
213 *     </tr>
214 *     <tr>
215 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
216 *         <td>Called when the size of this view has changed.
217 *         </td>
218 *     </tr>
219 *
220 *     <tr>
221 *         <td>Drawing</td>
222 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
223 *         <td>Called when the view should render its content.
224 *         </td>
225 *     </tr>
226 *
227 *     <tr>
228 *         <td rowspan="4">Event processing</td>
229 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
230 *         <td>Called when a new hardware key event occurs.
231 *         </td>
232 *     </tr>
233 *     <tr>
234 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
235 *         <td>Called when a hardware key up event occurs.
236 *         </td>
237 *     </tr>
238 *     <tr>
239 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
240 *         <td>Called when a trackball motion event occurs.
241 *         </td>
242 *     </tr>
243 *     <tr>
244 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
245 *         <td>Called when a touch screen motion event occurs.
246 *         </td>
247 *     </tr>
248 *
249 *     <tr>
250 *         <td rowspan="2">Focus</td>
251 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
252 *         <td>Called when the view gains or loses focus.
253 *         </td>
254 *     </tr>
255 *
256 *     <tr>
257 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
258 *         <td>Called when the window containing the view gains or loses focus.
259 *         </td>
260 *     </tr>
261 *
262 *     <tr>
263 *         <td rowspan="3">Attaching</td>
264 *         <td><code>{@link #onAttachedToWindow()}</code></td>
265 *         <td>Called when the view is attached to a window.
266 *         </td>
267 *     </tr>
268 *
269 *     <tr>
270 *         <td><code>{@link #onDetachedFromWindow}</code></td>
271 *         <td>Called when the view is detached from its window.
272 *         </td>
273 *     </tr>
274 *
275 *     <tr>
276 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
277 *         <td>Called when the visibility of the window containing the view
278 *         has changed.
279 *         </td>
280 *     </tr>
281 *     </tbody>
282 *
283 * </table>
284 * </p>
285 *
286 * <a name="IDs"></a>
287 * <h3>IDs</h3>
288 * Views may have an integer id associated with them. These ids are typically
289 * assigned in the layout XML files, and are used to find specific views within
290 * the view tree. A common pattern is to:
291 * <ul>
292 * <li>Define a Button in the layout file and assign it a unique ID.
293 * <pre>
294 * &lt;Button
295 *     android:id="@+id/my_button"
296 *     android:layout_width="wrap_content"
297 *     android:layout_height="wrap_content"
298 *     android:text="@string/my_button_text"/&gt;
299 * </pre></li>
300 * <li>From the onCreate method of an Activity, find the Button
301 * <pre class="prettyprint">
302 *      Button myButton = (Button) findViewById(R.id.my_button);
303 * </pre></li>
304 * </ul>
305 * <p>
306 * View IDs need not be unique throughout the tree, but it is good practice to
307 * ensure that they are at least unique within the part of the tree you are
308 * searching.
309 * </p>
310 *
311 * <a name="Position"></a>
312 * <h3>Position</h3>
313 * <p>
314 * The geometry of a view is that of a rectangle. A view has a location,
315 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
316 * two dimensions, expressed as a width and a height. The unit for location
317 * and dimensions is the pixel.
318 * </p>
319 *
320 * <p>
321 * It is possible to retrieve the location of a view by invoking the methods
322 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
323 * coordinate of the rectangle representing the view. The latter returns the
324 * top, or Y, coordinate of the rectangle representing the view. These methods
325 * both return the location of the view relative to its parent. For instance,
326 * when getLeft() returns 20, that means the view is located 20 pixels to the
327 * right of the left edge of its direct parent.
328 * </p>
329 *
330 * <p>
331 * In addition, several convenience methods are offered to avoid unnecessary
332 * computations, namely {@link #getRight()} and {@link #getBottom()}.
333 * These methods return the coordinates of the right and bottom edges of the
334 * rectangle representing the view. For instance, calling {@link #getRight()}
335 * is similar to the following computation: <code>getLeft() + getWidth()</code>
336 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
337 * </p>
338 *
339 * <a name="SizePaddingMargins"></a>
340 * <h3>Size, padding and margins</h3>
341 * <p>
342 * The size of a view is expressed with a width and a height. A view actually
343 * possess two pairs of width and height values.
344 * </p>
345 *
346 * <p>
347 * The first pair is known as <em>measured width</em> and
348 * <em>measured height</em>. These dimensions define how big a view wants to be
349 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
350 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
351 * and {@link #getMeasuredHeight()}.
352 * </p>
353 *
354 * <p>
355 * The second pair is simply known as <em>width</em> and <em>height</em>, or
356 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
357 * dimensions define the actual size of the view on screen, at drawing time and
358 * after layout. These values may, but do not have to, be different from the
359 * measured width and height. The width and height can be obtained by calling
360 * {@link #getWidth()} and {@link #getHeight()}.
361 * </p>
362 *
363 * <p>
364 * To measure its dimensions, a view takes into account its padding. The padding
365 * is expressed in pixels for the left, top, right and bottom parts of the view.
366 * Padding can be used to offset the content of the view by a specific amount of
367 * pixels. For instance, a left padding of 2 will push the view's content by
368 * 2 pixels to the right of the left edge. Padding can be set using the
369 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
370 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
371 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
372 * {@link #getPaddingEnd()}.
373 * </p>
374 *
375 * <p>
376 * Even though a view can define a padding, it does not provide any support for
377 * margins. However, view groups provide such a support. Refer to
378 * {@link android.view.ViewGroup} and
379 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
380 * </p>
381 *
382 * <a name="Layout"></a>
383 * <h3>Layout</h3>
384 * <p>
385 * Layout is a two pass process: a measure pass and a layout pass. The measuring
386 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
387 * of the view tree. Each view pushes dimension specifications down the tree
388 * during the recursion. At the end of the measure pass, every view has stored
389 * its measurements. The second pass happens in
390 * {@link #layout(int,int,int,int)} and is also top-down. During
391 * this pass each parent is responsible for positioning all of its children
392 * using the sizes computed in the measure pass.
393 * </p>
394 *
395 * <p>
396 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
397 * {@link #getMeasuredHeight()} values must be set, along with those for all of
398 * that view's descendants. A view's measured width and measured height values
399 * must respect the constraints imposed by the view's parents. This guarantees
400 * that at the end of the measure pass, all parents accept all of their
401 * children's measurements. A parent view may call measure() more than once on
402 * its children. For example, the parent may measure each child once with
403 * unspecified dimensions to find out how big they want to be, then call
404 * measure() on them again with actual numbers if the sum of all the children's
405 * unconstrained sizes is too big or too small.
406 * </p>
407 *
408 * <p>
409 * The measure pass uses two classes to communicate dimensions. The
410 * {@link MeasureSpec} class is used by views to tell their parents how they
411 * want to be measured and positioned. The base LayoutParams class just
412 * describes how big the view wants to be for both width and height. For each
413 * dimension, it can specify one of:
414 * <ul>
415 * <li> an exact number
416 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
417 * (minus padding)
418 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
419 * enclose its content (plus padding).
420 * </ul>
421 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
422 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
423 * an X and Y value.
424 * </p>
425 *
426 * <p>
427 * MeasureSpecs are used to push requirements down the tree from parent to
428 * child. A MeasureSpec can be in one of three modes:
429 * <ul>
430 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
431 * of a child view. For example, a LinearLayout may call measure() on its child
432 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
433 * tall the child view wants to be given a width of 240 pixels.
434 * <li>EXACTLY: This is used by the parent to impose an exact size on the
435 * child. The child must use this size, and guarantee that all of its
436 * descendants will fit within this size.
437 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
438 * child. The child must guarantee that it and all of its descendants will fit
439 * within this size.
440 * </ul>
441 * </p>
442 *
443 * <p>
444 * To initiate a layout, call {@link #requestLayout}. This method is typically
445 * called by a view on itself when it believes that is can no longer fit within
446 * its current bounds.
447 * </p>
448 *
449 * <a name="Drawing"></a>
450 * <h3>Drawing</h3>
451 * <p>
452 * Drawing is handled by walking the tree and recording the drawing commands of
453 * any View that needs to update. After this, the drawing commands of the
454 * entire tree are issued to screen, clipped to the newly damaged area.
455 * </p>
456 *
457 * <p>
458 * The tree is largely recorded and drawn in order, with parents drawn before
459 * (i.e., behind) their children, with siblings drawn in the order they appear
460 * in the tree. If you set a background drawable for a View, then the View will
461 * draw it before calling back to its <code>onDraw()</code> method. The child
462 * drawing order can be overridden with
463 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
464 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
465 * </p>
466 *
467 * <p>
468 * To force a view to draw, call {@link #invalidate()}.
469 * </p>
470 *
471 * <a name="EventHandlingThreading"></a>
472 * <h3>Event Handling and Threading</h3>
473 * <p>
474 * The basic cycle of a view is as follows:
475 * <ol>
476 * <li>An event comes in and is dispatched to the appropriate view. The view
477 * handles the event and notifies any listeners.</li>
478 * <li>If in the course of processing the event, the view's bounds may need
479 * to be changed, the view will call {@link #requestLayout()}.</li>
480 * <li>Similarly, if in the course of processing the event the view's appearance
481 * may need to be changed, the view will call {@link #invalidate()}.</li>
482 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
483 * the framework will take care of measuring, laying out, and drawing the tree
484 * as appropriate.</li>
485 * </ol>
486 * </p>
487 *
488 * <p><em>Note: The entire view tree is single threaded. You must always be on
489 * the UI thread when calling any method on any view.</em>
490 * If you are doing work on other threads and want to update the state of a view
491 * from that thread, you should use a {@link Handler}.
492 * </p>
493 *
494 * <a name="FocusHandling"></a>
495 * <h3>Focus Handling</h3>
496 * <p>
497 * The framework will handle routine focus movement in response to user input.
498 * This includes changing the focus as views are removed or hidden, or as new
499 * views become available. Views indicate their willingness to take focus
500 * through the {@link #isFocusable} method. To change whether a view can take
501 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
502 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
503 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
504 * </p>
505 * <p>
506 * Focus movement is based on an algorithm which finds the nearest neighbor in a
507 * given direction. In rare cases, the default algorithm may not match the
508 * intended behavior of the developer. In these situations, you can provide
509 * explicit overrides by using these XML attributes in the layout file:
510 * <pre>
511 * nextFocusDown
512 * nextFocusLeft
513 * nextFocusRight
514 * nextFocusUp
515 * </pre>
516 * </p>
517 *
518 *
519 * <p>
520 * To get a particular view to take focus, call {@link #requestFocus()}.
521 * </p>
522 *
523 * <a name="TouchMode"></a>
524 * <h3>Touch Mode</h3>
525 * <p>
526 * When a user is navigating a user interface via directional keys such as a D-pad, it is
527 * necessary to give focus to actionable items such as buttons so the user can see
528 * what will take input.  If the device has touch capabilities, however, and the user
529 * begins interacting with the interface by touching it, it is no longer necessary to
530 * always highlight, or give focus to, a particular view.  This motivates a mode
531 * for interaction named 'touch mode'.
532 * </p>
533 * <p>
534 * For a touch capable device, once the user touches the screen, the device
535 * will enter touch mode.  From this point onward, only views for which
536 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
537 * Other views that are touchable, like buttons, will not take focus when touched; they will
538 * only fire the on click listeners.
539 * </p>
540 * <p>
541 * Any time a user hits a directional key, such as a D-pad direction, the view device will
542 * exit touch mode, and find a view to take focus, so that the user may resume interacting
543 * with the user interface without touching the screen again.
544 * </p>
545 * <p>
546 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
547 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
548 * </p>
549 *
550 * <a name="Scrolling"></a>
551 * <h3>Scrolling</h3>
552 * <p>
553 * The framework provides basic support for views that wish to internally
554 * scroll their content. This includes keeping track of the X and Y scroll
555 * offset as well as mechanisms for drawing scrollbars. See
556 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
557 * {@link #awakenScrollBars()} for more details.
558 * </p>
559 *
560 * <a name="Tags"></a>
561 * <h3>Tags</h3>
562 * <p>
563 * Unlike IDs, tags are not used to identify views. Tags are essentially an
564 * extra piece of information that can be associated with a view. They are most
565 * often used as a convenience to store data related to views in the views
566 * themselves rather than by putting them in a separate structure.
567 * </p>
568 *
569 * <a name="Properties"></a>
570 * <h3>Properties</h3>
571 * <p>
572 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
573 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
574 * available both in the {@link Property} form as well as in similarly-named setter/getter
575 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
576 * be used to set persistent state associated with these rendering-related properties on the view.
577 * The properties and methods can also be used in conjunction with
578 * {@link android.animation.Animator Animator}-based animations, described more in the
579 * <a href="#Animation">Animation</a> section.
580 * </p>
581 *
582 * <a name="Animation"></a>
583 * <h3>Animation</h3>
584 * <p>
585 * Starting with Android 3.0, the preferred way of animating views is to use the
586 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
587 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
588 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
589 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
590 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
591 * makes animating these View properties particularly easy and efficient.
592 * </p>
593 * <p>
594 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
595 * You can attach an {@link Animation} object to a view using
596 * {@link #setAnimation(Animation)} or
597 * {@link #startAnimation(Animation)}. The animation can alter the scale,
598 * rotation, translation and alpha of a view over time. If the animation is
599 * attached to a view that has children, the animation will affect the entire
600 * subtree rooted by that node. When an animation is started, the framework will
601 * take care of redrawing the appropriate views until the animation completes.
602 * </p>
603 *
604 * <a name="Security"></a>
605 * <h3>Security</h3>
606 * <p>
607 * Sometimes it is essential that an application be able to verify that an action
608 * is being performed with the full knowledge and consent of the user, such as
609 * granting a permission request, making a purchase or clicking on an advertisement.
610 * Unfortunately, a malicious application could try to spoof the user into
611 * performing these actions, unaware, by concealing the intended purpose of the view.
612 * As a remedy, the framework offers a touch filtering mechanism that can be used to
613 * improve the security of views that provide access to sensitive functionality.
614 * </p><p>
615 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
616 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
617 * will discard touches that are received whenever the view's window is obscured by
618 * another visible window.  As a result, the view will not receive touches whenever a
619 * toast, dialog or other window appears above the view's window.
620 * </p><p>
621 * For more fine-grained control over security, consider overriding the
622 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
623 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
624 * </p>
625 *
626 * @attr ref android.R.styleable#View_alpha
627 * @attr ref android.R.styleable#View_background
628 * @attr ref android.R.styleable#View_clickable
629 * @attr ref android.R.styleable#View_contentDescription
630 * @attr ref android.R.styleable#View_drawingCacheQuality
631 * @attr ref android.R.styleable#View_duplicateParentState
632 * @attr ref android.R.styleable#View_id
633 * @attr ref android.R.styleable#View_requiresFadingEdge
634 * @attr ref android.R.styleable#View_fadeScrollbars
635 * @attr ref android.R.styleable#View_fadingEdgeLength
636 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
637 * @attr ref android.R.styleable#View_fitsSystemWindows
638 * @attr ref android.R.styleable#View_isScrollContainer
639 * @attr ref android.R.styleable#View_focusable
640 * @attr ref android.R.styleable#View_focusableInTouchMode
641 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
642 * @attr ref android.R.styleable#View_keepScreenOn
643 * @attr ref android.R.styleable#View_layerType
644 * @attr ref android.R.styleable#View_layoutDirection
645 * @attr ref android.R.styleable#View_longClickable
646 * @attr ref android.R.styleable#View_minHeight
647 * @attr ref android.R.styleable#View_minWidth
648 * @attr ref android.R.styleable#View_nextFocusDown
649 * @attr ref android.R.styleable#View_nextFocusLeft
650 * @attr ref android.R.styleable#View_nextFocusRight
651 * @attr ref android.R.styleable#View_nextFocusUp
652 * @attr ref android.R.styleable#View_onClick
653 * @attr ref android.R.styleable#View_padding
654 * @attr ref android.R.styleable#View_paddingBottom
655 * @attr ref android.R.styleable#View_paddingLeft
656 * @attr ref android.R.styleable#View_paddingRight
657 * @attr ref android.R.styleable#View_paddingTop
658 * @attr ref android.R.styleable#View_paddingStart
659 * @attr ref android.R.styleable#View_paddingEnd
660 * @attr ref android.R.styleable#View_saveEnabled
661 * @attr ref android.R.styleable#View_rotation
662 * @attr ref android.R.styleable#View_rotationX
663 * @attr ref android.R.styleable#View_rotationY
664 * @attr ref android.R.styleable#View_scaleX
665 * @attr ref android.R.styleable#View_scaleY
666 * @attr ref android.R.styleable#View_scrollX
667 * @attr ref android.R.styleable#View_scrollY
668 * @attr ref android.R.styleable#View_scrollbarSize
669 * @attr ref android.R.styleable#View_scrollbarStyle
670 * @attr ref android.R.styleable#View_scrollbars
671 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
672 * @attr ref android.R.styleable#View_scrollbarFadeDuration
673 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
674 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
675 * @attr ref android.R.styleable#View_scrollbarThumbVertical
676 * @attr ref android.R.styleable#View_scrollbarTrackVertical
677 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
678 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
679 * @attr ref android.R.styleable#View_stateListAnimator
680 * @attr ref android.R.styleable#View_transitionName
681 * @attr ref android.R.styleable#View_soundEffectsEnabled
682 * @attr ref android.R.styleable#View_tag
683 * @attr ref android.R.styleable#View_textAlignment
684 * @attr ref android.R.styleable#View_textDirection
685 * @attr ref android.R.styleable#View_transformPivotX
686 * @attr ref android.R.styleable#View_transformPivotY
687 * @attr ref android.R.styleable#View_translationX
688 * @attr ref android.R.styleable#View_translationY
689 * @attr ref android.R.styleable#View_translationZ
690 * @attr ref android.R.styleable#View_visibility
691 *
692 * @see android.view.ViewGroup
693 */
694public class View implements Drawable.Callback, KeyEvent.Callback,
695        AccessibilityEventSource {
696    private static final boolean DBG = false;
697
698    /**
699     * The logging tag used by this class with android.util.Log.
700     */
701    protected static final String VIEW_LOG_TAG = "View";
702
703    /**
704     * When set to true, apps will draw debugging information about their layouts.
705     *
706     * @hide
707     */
708    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
709
710    /**
711     * When set to true, this view will save its attribute data.
712     *
713     * @hide
714     */
715    public static boolean mDebugViewAttributes = false;
716
717    /**
718     * Used to mark a View that has no ID.
719     */
720    public static final int NO_ID = -1;
721
722    /**
723     * Signals that compatibility booleans have been initialized according to
724     * target SDK versions.
725     */
726    private static boolean sCompatibilityDone = false;
727
728    /**
729     * Use the old (broken) way of building MeasureSpecs.
730     */
731    private static boolean sUseBrokenMakeMeasureSpec = false;
732
733    /**
734     * Ignore any optimizations using the measure cache.
735     */
736    private static boolean sIgnoreMeasureCache = false;
737
738    /**
739     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
740     * calling setFlags.
741     */
742    private static final int NOT_FOCUSABLE = 0x00000000;
743
744    /**
745     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
746     * setFlags.
747     */
748    private static final int FOCUSABLE = 0x00000001;
749
750    /**
751     * Mask for use with setFlags indicating bits used for focus.
752     */
753    private static final int FOCUSABLE_MASK = 0x00000001;
754
755    /**
756     * This view will adjust its padding to fit sytem windows (e.g. status bar)
757     */
758    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
759
760    /** @hide */
761    @IntDef({VISIBLE, INVISIBLE, GONE})
762    @Retention(RetentionPolicy.SOURCE)
763    public @interface Visibility {}
764
765    /**
766     * This view is visible.
767     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
768     * android:visibility}.
769     */
770    public static final int VISIBLE = 0x00000000;
771
772    /**
773     * This view is invisible, but it still takes up space for layout purposes.
774     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
775     * android:visibility}.
776     */
777    public static final int INVISIBLE = 0x00000004;
778
779    /**
780     * This view is invisible, and it doesn't take any space for layout
781     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
782     * android:visibility}.
783     */
784    public static final int GONE = 0x00000008;
785
786    /**
787     * Mask for use with setFlags indicating bits used for visibility.
788     * {@hide}
789     */
790    static final int VISIBILITY_MASK = 0x0000000C;
791
792    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
793
794    /**
795     * This view is enabled. Interpretation varies by subclass.
796     * Use with ENABLED_MASK when calling setFlags.
797     * {@hide}
798     */
799    static final int ENABLED = 0x00000000;
800
801    /**
802     * This view is disabled. Interpretation varies by subclass.
803     * Use with ENABLED_MASK when calling setFlags.
804     * {@hide}
805     */
806    static final int DISABLED = 0x00000020;
807
808   /**
809    * Mask for use with setFlags indicating bits used for indicating whether
810    * this view is enabled
811    * {@hide}
812    */
813    static final int ENABLED_MASK = 0x00000020;
814
815    /**
816     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
817     * called and further optimizations will be performed. It is okay to have
818     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
819     * {@hide}
820     */
821    static final int WILL_NOT_DRAW = 0x00000080;
822
823    /**
824     * Mask for use with setFlags indicating bits used for indicating whether
825     * this view is will draw
826     * {@hide}
827     */
828    static final int DRAW_MASK = 0x00000080;
829
830    /**
831     * <p>This view doesn't show scrollbars.</p>
832     * {@hide}
833     */
834    static final int SCROLLBARS_NONE = 0x00000000;
835
836    /**
837     * <p>This view shows horizontal scrollbars.</p>
838     * {@hide}
839     */
840    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
841
842    /**
843     * <p>This view shows vertical scrollbars.</p>
844     * {@hide}
845     */
846    static final int SCROLLBARS_VERTICAL = 0x00000200;
847
848    /**
849     * <p>Mask for use with setFlags indicating bits used for indicating which
850     * scrollbars are enabled.</p>
851     * {@hide}
852     */
853    static final int SCROLLBARS_MASK = 0x00000300;
854
855    /**
856     * Indicates that the view should filter touches when its window is obscured.
857     * Refer to the class comments for more information about this security feature.
858     * {@hide}
859     */
860    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
861
862    /**
863     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
864     * that they are optional and should be skipped if the window has
865     * requested system UI flags that ignore those insets for layout.
866     */
867    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
868
869    /**
870     * <p>This view doesn't show fading edges.</p>
871     * {@hide}
872     */
873    static final int FADING_EDGE_NONE = 0x00000000;
874
875    /**
876     * <p>This view shows horizontal fading edges.</p>
877     * {@hide}
878     */
879    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
880
881    /**
882     * <p>This view shows vertical fading edges.</p>
883     * {@hide}
884     */
885    static final int FADING_EDGE_VERTICAL = 0x00002000;
886
887    /**
888     * <p>Mask for use with setFlags indicating bits used for indicating which
889     * fading edges are enabled.</p>
890     * {@hide}
891     */
892    static final int FADING_EDGE_MASK = 0x00003000;
893
894    /**
895     * <p>Indicates this view can be clicked. When clickable, a View reacts
896     * to clicks by notifying the OnClickListener.<p>
897     * {@hide}
898     */
899    static final int CLICKABLE = 0x00004000;
900
901    /**
902     * <p>Indicates this view is caching its drawing into a bitmap.</p>
903     * {@hide}
904     */
905    static final int DRAWING_CACHE_ENABLED = 0x00008000;
906
907    /**
908     * <p>Indicates that no icicle should be saved for this view.<p>
909     * {@hide}
910     */
911    static final int SAVE_DISABLED = 0x000010000;
912
913    /**
914     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
915     * property.</p>
916     * {@hide}
917     */
918    static final int SAVE_DISABLED_MASK = 0x000010000;
919
920    /**
921     * <p>Indicates that no drawing cache should ever be created for this view.<p>
922     * {@hide}
923     */
924    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
925
926    /**
927     * <p>Indicates this view can take / keep focus when int touch mode.</p>
928     * {@hide}
929     */
930    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
931
932    /** @hide */
933    @Retention(RetentionPolicy.SOURCE)
934    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
935    public @interface DrawingCacheQuality {}
936
937    /**
938     * <p>Enables low quality mode for the drawing cache.</p>
939     */
940    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
941
942    /**
943     * <p>Enables high quality mode for the drawing cache.</p>
944     */
945    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
946
947    /**
948     * <p>Enables automatic quality mode for the drawing cache.</p>
949     */
950    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
951
952    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
953            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
954    };
955
956    /**
957     * <p>Mask for use with setFlags indicating bits used for the cache
958     * quality property.</p>
959     * {@hide}
960     */
961    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
962
963    /**
964     * <p>
965     * Indicates this view can be long clicked. When long clickable, a View
966     * reacts to long clicks by notifying the OnLongClickListener or showing a
967     * context menu.
968     * </p>
969     * {@hide}
970     */
971    static final int LONG_CLICKABLE = 0x00200000;
972
973    /**
974     * <p>Indicates that this view gets its drawable states from its direct parent
975     * and ignores its original internal states.</p>
976     *
977     * @hide
978     */
979    static final int DUPLICATE_PARENT_STATE = 0x00400000;
980
981    /** @hide */
982    @IntDef({
983        SCROLLBARS_INSIDE_OVERLAY,
984        SCROLLBARS_INSIDE_INSET,
985        SCROLLBARS_OUTSIDE_OVERLAY,
986        SCROLLBARS_OUTSIDE_INSET
987    })
988    @Retention(RetentionPolicy.SOURCE)
989    public @interface ScrollBarStyle {}
990
991    /**
992     * The scrollbar style to display the scrollbars inside the content area,
993     * without increasing the padding. The scrollbars will be overlaid with
994     * translucency on the view's content.
995     */
996    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
997
998    /**
999     * The scrollbar style to display the scrollbars inside the padded area,
1000     * increasing the padding of the view. The scrollbars will not overlap the
1001     * content area of the view.
1002     */
1003    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1004
1005    /**
1006     * The scrollbar style to display the scrollbars at the edge of the view,
1007     * without increasing the padding. The scrollbars will be overlaid with
1008     * translucency.
1009     */
1010    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1011
1012    /**
1013     * The scrollbar style to display the scrollbars at the edge of the view,
1014     * increasing the padding of the view. The scrollbars will only overlap the
1015     * background, if any.
1016     */
1017    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1018
1019    /**
1020     * Mask to check if the scrollbar style is overlay or inset.
1021     * {@hide}
1022     */
1023    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1024
1025    /**
1026     * Mask to check if the scrollbar style is inside or outside.
1027     * {@hide}
1028     */
1029    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1030
1031    /**
1032     * Mask for scrollbar style.
1033     * {@hide}
1034     */
1035    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1036
1037    /**
1038     * View flag indicating that the screen should remain on while the
1039     * window containing this view is visible to the user.  This effectively
1040     * takes care of automatically setting the WindowManager's
1041     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1042     */
1043    public static final int KEEP_SCREEN_ON = 0x04000000;
1044
1045    /**
1046     * View flag indicating whether this view should have sound effects enabled
1047     * for events such as clicking and touching.
1048     */
1049    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1050
1051    /**
1052     * View flag indicating whether this view should have haptic feedback
1053     * enabled for events such as long presses.
1054     */
1055    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1056
1057    /**
1058     * <p>Indicates that the view hierarchy should stop saving state when
1059     * it reaches this view.  If state saving is initiated immediately at
1060     * the view, it will be allowed.
1061     * {@hide}
1062     */
1063    static final int PARENT_SAVE_DISABLED = 0x20000000;
1064
1065    /**
1066     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1067     * {@hide}
1068     */
1069    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1070
1071    /** @hide */
1072    @IntDef(flag = true,
1073            value = {
1074                FOCUSABLES_ALL,
1075                FOCUSABLES_TOUCH_MODE
1076            })
1077    @Retention(RetentionPolicy.SOURCE)
1078    public @interface FocusableMode {}
1079
1080    /**
1081     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1082     * should add all focusable Views regardless if they are focusable in touch mode.
1083     */
1084    public static final int FOCUSABLES_ALL = 0x00000000;
1085
1086    /**
1087     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1088     * should add only Views focusable in touch mode.
1089     */
1090    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1091
1092    /** @hide */
1093    @IntDef({
1094            FOCUS_BACKWARD,
1095            FOCUS_FORWARD,
1096            FOCUS_LEFT,
1097            FOCUS_UP,
1098            FOCUS_RIGHT,
1099            FOCUS_DOWN
1100    })
1101    @Retention(RetentionPolicy.SOURCE)
1102    public @interface FocusDirection {}
1103
1104    /** @hide */
1105    @IntDef({
1106            FOCUS_LEFT,
1107            FOCUS_UP,
1108            FOCUS_RIGHT,
1109            FOCUS_DOWN
1110    })
1111    @Retention(RetentionPolicy.SOURCE)
1112    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1113
1114    /**
1115     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1116     * item.
1117     */
1118    public static final int FOCUS_BACKWARD = 0x00000001;
1119
1120    /**
1121     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1122     * item.
1123     */
1124    public static final int FOCUS_FORWARD = 0x00000002;
1125
1126    /**
1127     * Use with {@link #focusSearch(int)}. Move focus to the left.
1128     */
1129    public static final int FOCUS_LEFT = 0x00000011;
1130
1131    /**
1132     * Use with {@link #focusSearch(int)}. Move focus up.
1133     */
1134    public static final int FOCUS_UP = 0x00000021;
1135
1136    /**
1137     * Use with {@link #focusSearch(int)}. Move focus to the right.
1138     */
1139    public static final int FOCUS_RIGHT = 0x00000042;
1140
1141    /**
1142     * Use with {@link #focusSearch(int)}. Move focus down.
1143     */
1144    public static final int FOCUS_DOWN = 0x00000082;
1145
1146    /**
1147     * Bits of {@link #getMeasuredWidthAndState()} and
1148     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1149     */
1150    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1151
1152    /**
1153     * Bits of {@link #getMeasuredWidthAndState()} and
1154     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1155     */
1156    public static final int MEASURED_STATE_MASK = 0xff000000;
1157
1158    /**
1159     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1160     * for functions that combine both width and height into a single int,
1161     * such as {@link #getMeasuredState()} and the childState argument of
1162     * {@link #resolveSizeAndState(int, int, int)}.
1163     */
1164    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1165
1166    /**
1167     * Bit of {@link #getMeasuredWidthAndState()} and
1168     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1169     * is smaller that the space the view would like to have.
1170     */
1171    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1172
1173    /**
1174     * Base View state sets
1175     */
1176    // Singles
1177    /**
1178     * Indicates the view has no states set. States are used with
1179     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1180     * view depending on its state.
1181     *
1182     * @see android.graphics.drawable.Drawable
1183     * @see #getDrawableState()
1184     */
1185    protected static final int[] EMPTY_STATE_SET;
1186    /**
1187     * Indicates the view is enabled. States are used with
1188     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1189     * view depending on its state.
1190     *
1191     * @see android.graphics.drawable.Drawable
1192     * @see #getDrawableState()
1193     */
1194    protected static final int[] ENABLED_STATE_SET;
1195    /**
1196     * Indicates the view is focused. States are used with
1197     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1198     * view depending on its state.
1199     *
1200     * @see android.graphics.drawable.Drawable
1201     * @see #getDrawableState()
1202     */
1203    protected static final int[] FOCUSED_STATE_SET;
1204    /**
1205     * Indicates the view is selected. States are used with
1206     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1207     * view depending on its state.
1208     *
1209     * @see android.graphics.drawable.Drawable
1210     * @see #getDrawableState()
1211     */
1212    protected static final int[] SELECTED_STATE_SET;
1213    /**
1214     * Indicates the view is pressed. States are used with
1215     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1216     * view depending on its state.
1217     *
1218     * @see android.graphics.drawable.Drawable
1219     * @see #getDrawableState()
1220     */
1221    protected static final int[] PRESSED_STATE_SET;
1222    /**
1223     * Indicates the view's window has focus. States are used with
1224     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1225     * view depending on its state.
1226     *
1227     * @see android.graphics.drawable.Drawable
1228     * @see #getDrawableState()
1229     */
1230    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1231    // Doubles
1232    /**
1233     * Indicates the view is enabled and has the focus.
1234     *
1235     * @see #ENABLED_STATE_SET
1236     * @see #FOCUSED_STATE_SET
1237     */
1238    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1239    /**
1240     * Indicates the view is enabled and selected.
1241     *
1242     * @see #ENABLED_STATE_SET
1243     * @see #SELECTED_STATE_SET
1244     */
1245    protected static final int[] ENABLED_SELECTED_STATE_SET;
1246    /**
1247     * Indicates the view is enabled and that its window has focus.
1248     *
1249     * @see #ENABLED_STATE_SET
1250     * @see #WINDOW_FOCUSED_STATE_SET
1251     */
1252    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1253    /**
1254     * Indicates the view is focused and selected.
1255     *
1256     * @see #FOCUSED_STATE_SET
1257     * @see #SELECTED_STATE_SET
1258     */
1259    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1260    /**
1261     * Indicates the view has the focus and that its window has the focus.
1262     *
1263     * @see #FOCUSED_STATE_SET
1264     * @see #WINDOW_FOCUSED_STATE_SET
1265     */
1266    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1267    /**
1268     * Indicates the view is selected and that its window has the focus.
1269     *
1270     * @see #SELECTED_STATE_SET
1271     * @see #WINDOW_FOCUSED_STATE_SET
1272     */
1273    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1274    // Triples
1275    /**
1276     * Indicates the view is enabled, focused and selected.
1277     *
1278     * @see #ENABLED_STATE_SET
1279     * @see #FOCUSED_STATE_SET
1280     * @see #SELECTED_STATE_SET
1281     */
1282    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1283    /**
1284     * Indicates the view is enabled, focused and its window has the focus.
1285     *
1286     * @see #ENABLED_STATE_SET
1287     * @see #FOCUSED_STATE_SET
1288     * @see #WINDOW_FOCUSED_STATE_SET
1289     */
1290    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1291    /**
1292     * Indicates the view is enabled, selected and its window has the focus.
1293     *
1294     * @see #ENABLED_STATE_SET
1295     * @see #SELECTED_STATE_SET
1296     * @see #WINDOW_FOCUSED_STATE_SET
1297     */
1298    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1299    /**
1300     * Indicates the view is focused, selected and its window has the focus.
1301     *
1302     * @see #FOCUSED_STATE_SET
1303     * @see #SELECTED_STATE_SET
1304     * @see #WINDOW_FOCUSED_STATE_SET
1305     */
1306    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1307    /**
1308     * Indicates the view is enabled, focused, selected and its window
1309     * has the focus.
1310     *
1311     * @see #ENABLED_STATE_SET
1312     * @see #FOCUSED_STATE_SET
1313     * @see #SELECTED_STATE_SET
1314     * @see #WINDOW_FOCUSED_STATE_SET
1315     */
1316    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1317    /**
1318     * Indicates the view is pressed and its window has the focus.
1319     *
1320     * @see #PRESSED_STATE_SET
1321     * @see #WINDOW_FOCUSED_STATE_SET
1322     */
1323    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1324    /**
1325     * Indicates the view is pressed and selected.
1326     *
1327     * @see #PRESSED_STATE_SET
1328     * @see #SELECTED_STATE_SET
1329     */
1330    protected static final int[] PRESSED_SELECTED_STATE_SET;
1331    /**
1332     * Indicates the view is pressed, selected and its window has the focus.
1333     *
1334     * @see #PRESSED_STATE_SET
1335     * @see #SELECTED_STATE_SET
1336     * @see #WINDOW_FOCUSED_STATE_SET
1337     */
1338    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1339    /**
1340     * Indicates the view is pressed and focused.
1341     *
1342     * @see #PRESSED_STATE_SET
1343     * @see #FOCUSED_STATE_SET
1344     */
1345    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1346    /**
1347     * Indicates the view is pressed, focused and its window has the focus.
1348     *
1349     * @see #PRESSED_STATE_SET
1350     * @see #FOCUSED_STATE_SET
1351     * @see #WINDOW_FOCUSED_STATE_SET
1352     */
1353    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1354    /**
1355     * Indicates the view is pressed, focused and selected.
1356     *
1357     * @see #PRESSED_STATE_SET
1358     * @see #SELECTED_STATE_SET
1359     * @see #FOCUSED_STATE_SET
1360     */
1361    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1362    /**
1363     * Indicates the view is pressed, focused, selected and its window has the focus.
1364     *
1365     * @see #PRESSED_STATE_SET
1366     * @see #FOCUSED_STATE_SET
1367     * @see #SELECTED_STATE_SET
1368     * @see #WINDOW_FOCUSED_STATE_SET
1369     */
1370    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1371    /**
1372     * Indicates the view is pressed and enabled.
1373     *
1374     * @see #PRESSED_STATE_SET
1375     * @see #ENABLED_STATE_SET
1376     */
1377    protected static final int[] PRESSED_ENABLED_STATE_SET;
1378    /**
1379     * Indicates the view is pressed, enabled and its window has the focus.
1380     *
1381     * @see #PRESSED_STATE_SET
1382     * @see #ENABLED_STATE_SET
1383     * @see #WINDOW_FOCUSED_STATE_SET
1384     */
1385    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1386    /**
1387     * Indicates the view is pressed, enabled and selected.
1388     *
1389     * @see #PRESSED_STATE_SET
1390     * @see #ENABLED_STATE_SET
1391     * @see #SELECTED_STATE_SET
1392     */
1393    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1394    /**
1395     * Indicates the view is pressed, enabled, selected and its window has the
1396     * focus.
1397     *
1398     * @see #PRESSED_STATE_SET
1399     * @see #ENABLED_STATE_SET
1400     * @see #SELECTED_STATE_SET
1401     * @see #WINDOW_FOCUSED_STATE_SET
1402     */
1403    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1404    /**
1405     * Indicates the view is pressed, enabled and focused.
1406     *
1407     * @see #PRESSED_STATE_SET
1408     * @see #ENABLED_STATE_SET
1409     * @see #FOCUSED_STATE_SET
1410     */
1411    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1412    /**
1413     * Indicates the view is pressed, enabled, focused and its window has the
1414     * focus.
1415     *
1416     * @see #PRESSED_STATE_SET
1417     * @see #ENABLED_STATE_SET
1418     * @see #FOCUSED_STATE_SET
1419     * @see #WINDOW_FOCUSED_STATE_SET
1420     */
1421    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1422    /**
1423     * Indicates the view is pressed, enabled, focused and selected.
1424     *
1425     * @see #PRESSED_STATE_SET
1426     * @see #ENABLED_STATE_SET
1427     * @see #SELECTED_STATE_SET
1428     * @see #FOCUSED_STATE_SET
1429     */
1430    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1431    /**
1432     * Indicates the view is pressed, enabled, focused, selected and its window
1433     * has the focus.
1434     *
1435     * @see #PRESSED_STATE_SET
1436     * @see #ENABLED_STATE_SET
1437     * @see #SELECTED_STATE_SET
1438     * @see #FOCUSED_STATE_SET
1439     * @see #WINDOW_FOCUSED_STATE_SET
1440     */
1441    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1442
1443    static {
1444        EMPTY_STATE_SET = StateSet.get(0);
1445
1446        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1447
1448        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1449        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1450                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1451
1452        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1453        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1454                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1455        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1456                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1457        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1458                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1459                        | StateSet.VIEW_STATE_FOCUSED);
1460
1461        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1462        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1463                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1464        ENABLED_SELECTED_STATE_SET = StateSet.get(
1465                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1466        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1467                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1468                        | StateSet.VIEW_STATE_ENABLED);
1469        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1470                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1471        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1472                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1473                        | StateSet.VIEW_STATE_ENABLED);
1474        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1475                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1476                        | StateSet.VIEW_STATE_ENABLED);
1477        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1478                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1479                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1480
1481        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1482        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1483                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1484        PRESSED_SELECTED_STATE_SET = StateSet.get(
1485                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1486        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1487                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1488                        | StateSet.VIEW_STATE_PRESSED);
1489        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1490                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1491        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1492                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1493                        | StateSet.VIEW_STATE_PRESSED);
1494        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1495                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1496                        | StateSet.VIEW_STATE_PRESSED);
1497        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1498                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1499                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1500        PRESSED_ENABLED_STATE_SET = StateSet.get(
1501                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1502        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1503                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1504                        | StateSet.VIEW_STATE_PRESSED);
1505        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1506                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1507                        | StateSet.VIEW_STATE_PRESSED);
1508        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1509                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1510                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1511        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1512                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1513                        | StateSet.VIEW_STATE_PRESSED);
1514        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1515                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1516                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1517        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1518                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1519                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1520        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1521                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1522                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1523                        | StateSet.VIEW_STATE_PRESSED);
1524    }
1525
1526    /**
1527     * Accessibility event types that are dispatched for text population.
1528     */
1529    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1530            AccessibilityEvent.TYPE_VIEW_CLICKED
1531            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1532            | AccessibilityEvent.TYPE_VIEW_SELECTED
1533            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1534            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1535            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1536            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1537            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1538            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1539            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1540            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1541
1542    /**
1543     * Temporary Rect currently for use in setBackground().  This will probably
1544     * be extended in the future to hold our own class with more than just
1545     * a Rect. :)
1546     */
1547    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1548
1549    /**
1550     * Map used to store views' tags.
1551     */
1552    private SparseArray<Object> mKeyedTags;
1553
1554    /**
1555     * The next available accessibility id.
1556     */
1557    private static int sNextAccessibilityViewId;
1558
1559    /**
1560     * The animation currently associated with this view.
1561     * @hide
1562     */
1563    protected Animation mCurrentAnimation = null;
1564
1565    /**
1566     * Width as measured during measure pass.
1567     * {@hide}
1568     */
1569    @ViewDebug.ExportedProperty(category = "measurement")
1570    int mMeasuredWidth;
1571
1572    /**
1573     * Height as measured during measure pass.
1574     * {@hide}
1575     */
1576    @ViewDebug.ExportedProperty(category = "measurement")
1577    int mMeasuredHeight;
1578
1579    /**
1580     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1581     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1582     * its display list. This flag, used only when hw accelerated, allows us to clear the
1583     * flag while retaining this information until it's needed (at getDisplayList() time and
1584     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1585     *
1586     * {@hide}
1587     */
1588    boolean mRecreateDisplayList = false;
1589
1590    /**
1591     * The view's identifier.
1592     * {@hide}
1593     *
1594     * @see #setId(int)
1595     * @see #getId()
1596     */
1597    @IdRes
1598    @ViewDebug.ExportedProperty(resolveId = true)
1599    int mID = NO_ID;
1600
1601    /**
1602     * The stable ID of this view for accessibility purposes.
1603     */
1604    int mAccessibilityViewId = NO_ID;
1605
1606    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1607
1608    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1609
1610    /**
1611     * The view's tag.
1612     * {@hide}
1613     *
1614     * @see #setTag(Object)
1615     * @see #getTag()
1616     */
1617    protected Object mTag = null;
1618
1619    // for mPrivateFlags:
1620    /** {@hide} */
1621    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1622    /** {@hide} */
1623    static final int PFLAG_FOCUSED                     = 0x00000002;
1624    /** {@hide} */
1625    static final int PFLAG_SELECTED                    = 0x00000004;
1626    /** {@hide} */
1627    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1628    /** {@hide} */
1629    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1630    /** {@hide} */
1631    static final int PFLAG_DRAWN                       = 0x00000020;
1632    /**
1633     * When this flag is set, this view is running an animation on behalf of its
1634     * children and should therefore not cancel invalidate requests, even if they
1635     * lie outside of this view's bounds.
1636     *
1637     * {@hide}
1638     */
1639    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1640    /** {@hide} */
1641    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1642    /** {@hide} */
1643    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1644    /** {@hide} */
1645    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1646    /** {@hide} */
1647    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1648    /** {@hide} */
1649    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1650    /** {@hide} */
1651    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1652    /** {@hide} */
1653    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1654
1655    private static final int PFLAG_PRESSED             = 0x00004000;
1656
1657    /** {@hide} */
1658    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1659    /**
1660     * Flag used to indicate that this view should be drawn once more (and only once
1661     * more) after its animation has completed.
1662     * {@hide}
1663     */
1664    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1665
1666    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1667
1668    /**
1669     * Indicates that the View returned true when onSetAlpha() was called and that
1670     * the alpha must be restored.
1671     * {@hide}
1672     */
1673    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1674
1675    /**
1676     * Set by {@link #setScrollContainer(boolean)}.
1677     */
1678    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1679
1680    /**
1681     * Set by {@link #setScrollContainer(boolean)}.
1682     */
1683    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1684
1685    /**
1686     * View flag indicating whether this view was invalidated (fully or partially.)
1687     *
1688     * @hide
1689     */
1690    static final int PFLAG_DIRTY                       = 0x00200000;
1691
1692    /**
1693     * View flag indicating whether this view was invalidated by an opaque
1694     * invalidate request.
1695     *
1696     * @hide
1697     */
1698    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1699
1700    /**
1701     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1702     *
1703     * @hide
1704     */
1705    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1706
1707    /**
1708     * Indicates whether the background is opaque.
1709     *
1710     * @hide
1711     */
1712    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1713
1714    /**
1715     * Indicates whether the scrollbars are opaque.
1716     *
1717     * @hide
1718     */
1719    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1720
1721    /**
1722     * Indicates whether the view is opaque.
1723     *
1724     * @hide
1725     */
1726    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1727
1728    /**
1729     * Indicates a prepressed state;
1730     * the short time between ACTION_DOWN and recognizing
1731     * a 'real' press. Prepressed is used to recognize quick taps
1732     * even when they are shorter than ViewConfiguration.getTapTimeout().
1733     *
1734     * @hide
1735     */
1736    private static final int PFLAG_PREPRESSED          = 0x02000000;
1737
1738    /**
1739     * Indicates whether the view is temporarily detached.
1740     *
1741     * @hide
1742     */
1743    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1744
1745    /**
1746     * Indicates that we should awaken scroll bars once attached
1747     *
1748     * @hide
1749     */
1750    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1751
1752    /**
1753     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1754     * @hide
1755     */
1756    private static final int PFLAG_HOVERED             = 0x10000000;
1757
1758    /**
1759     * no longer needed, should be reused
1760     */
1761    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1762
1763    /** {@hide} */
1764    static final int PFLAG_ACTIVATED                   = 0x40000000;
1765
1766    /**
1767     * Indicates that this view was specifically invalidated, not just dirtied because some
1768     * child view was invalidated. The flag is used to determine when we need to recreate
1769     * a view's display list (as opposed to just returning a reference to its existing
1770     * display list).
1771     *
1772     * @hide
1773     */
1774    static final int PFLAG_INVALIDATED                 = 0x80000000;
1775
1776    /**
1777     * Masks for mPrivateFlags2, as generated by dumpFlags():
1778     *
1779     * |-------|-------|-------|-------|
1780     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1781     *                                1  PFLAG2_DRAG_HOVERED
1782     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1783     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1784     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1785     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1786     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1787     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1788     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1789     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1790     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1791     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1792     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1793     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1794     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1795     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1796     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1797     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1798     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1799     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1800     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1801     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1802     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1803     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1804     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1805     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1806     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1807     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1808     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1809     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1810     *    1                              PFLAG2_PADDING_RESOLVED
1811     *   1                               PFLAG2_DRAWABLE_RESOLVED
1812     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1813     * |-------|-------|-------|-------|
1814     */
1815
1816    /**
1817     * Indicates that this view has reported that it can accept the current drag's content.
1818     * Cleared when the drag operation concludes.
1819     * @hide
1820     */
1821    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1822
1823    /**
1824     * Indicates that this view is currently directly under the drag location in a
1825     * drag-and-drop operation involving content that it can accept.  Cleared when
1826     * the drag exits the view, or when the drag operation concludes.
1827     * @hide
1828     */
1829    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1830
1831    /** @hide */
1832    @IntDef({
1833        LAYOUT_DIRECTION_LTR,
1834        LAYOUT_DIRECTION_RTL,
1835        LAYOUT_DIRECTION_INHERIT,
1836        LAYOUT_DIRECTION_LOCALE
1837    })
1838    @Retention(RetentionPolicy.SOURCE)
1839    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1840    public @interface LayoutDir {}
1841
1842    /** @hide */
1843    @IntDef({
1844        LAYOUT_DIRECTION_LTR,
1845        LAYOUT_DIRECTION_RTL
1846    })
1847    @Retention(RetentionPolicy.SOURCE)
1848    public @interface ResolvedLayoutDir {}
1849
1850    /**
1851     * Horizontal layout direction of this view is from Left to Right.
1852     * Use with {@link #setLayoutDirection}.
1853     */
1854    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1855
1856    /**
1857     * Horizontal layout direction of this view is from Right to Left.
1858     * Use with {@link #setLayoutDirection}.
1859     */
1860    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1861
1862    /**
1863     * Horizontal layout direction of this view is inherited from its parent.
1864     * Use with {@link #setLayoutDirection}.
1865     */
1866    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1867
1868    /**
1869     * Horizontal layout direction of this view is from deduced from the default language
1870     * script for the locale. Use with {@link #setLayoutDirection}.
1871     */
1872    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1873
1874    /**
1875     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1876     * @hide
1877     */
1878    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1879
1880    /**
1881     * Mask for use with private flags indicating bits used for horizontal layout direction.
1882     * @hide
1883     */
1884    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1885
1886    /**
1887     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1888     * right-to-left direction.
1889     * @hide
1890     */
1891    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1892
1893    /**
1894     * Indicates whether the view horizontal layout direction has been resolved.
1895     * @hide
1896     */
1897    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1898
1899    /**
1900     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1901     * @hide
1902     */
1903    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1904            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1905
1906    /*
1907     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1908     * flag value.
1909     * @hide
1910     */
1911    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1912            LAYOUT_DIRECTION_LTR,
1913            LAYOUT_DIRECTION_RTL,
1914            LAYOUT_DIRECTION_INHERIT,
1915            LAYOUT_DIRECTION_LOCALE
1916    };
1917
1918    /**
1919     * Default horizontal layout direction.
1920     */
1921    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1922
1923    /**
1924     * Default horizontal layout direction.
1925     * @hide
1926     */
1927    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1928
1929    /**
1930     * Text direction is inherited through {@link ViewGroup}
1931     */
1932    public static final int TEXT_DIRECTION_INHERIT = 0;
1933
1934    /**
1935     * Text direction is using "first strong algorithm". The first strong directional character
1936     * determines the paragraph direction. If there is no strong directional character, the
1937     * paragraph direction is the view's resolved layout direction.
1938     */
1939    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1940
1941    /**
1942     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1943     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1944     * If there are neither, the paragraph direction is the view's resolved layout direction.
1945     */
1946    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1947
1948    /**
1949     * Text direction is forced to LTR.
1950     */
1951    public static final int TEXT_DIRECTION_LTR = 3;
1952
1953    /**
1954     * Text direction is forced to RTL.
1955     */
1956    public static final int TEXT_DIRECTION_RTL = 4;
1957
1958    /**
1959     * Text direction is coming from the system Locale.
1960     */
1961    public static final int TEXT_DIRECTION_LOCALE = 5;
1962
1963    /**
1964     * Default text direction is inherited
1965     */
1966    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1967
1968    /**
1969     * Default resolved text direction
1970     * @hide
1971     */
1972    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
1973
1974    /**
1975     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1976     * @hide
1977     */
1978    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
1979
1980    /**
1981     * Mask for use with private flags indicating bits used for text direction.
1982     * @hide
1983     */
1984    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1985            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1986
1987    /**
1988     * Array of text direction flags for mapping attribute "textDirection" to correct
1989     * flag value.
1990     * @hide
1991     */
1992    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1993            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1994            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1995            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1996            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1997            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1998            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
1999    };
2000
2001    /**
2002     * Indicates whether the view text direction has been resolved.
2003     * @hide
2004     */
2005    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2006            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2007
2008    /**
2009     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2010     * @hide
2011     */
2012    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2013
2014    /**
2015     * Mask for use with private flags indicating bits used for resolved text direction.
2016     * @hide
2017     */
2018    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2019            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2020
2021    /**
2022     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2023     * @hide
2024     */
2025    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2026            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2027
2028    /** @hide */
2029    @IntDef({
2030        TEXT_ALIGNMENT_INHERIT,
2031        TEXT_ALIGNMENT_GRAVITY,
2032        TEXT_ALIGNMENT_CENTER,
2033        TEXT_ALIGNMENT_TEXT_START,
2034        TEXT_ALIGNMENT_TEXT_END,
2035        TEXT_ALIGNMENT_VIEW_START,
2036        TEXT_ALIGNMENT_VIEW_END
2037    })
2038    @Retention(RetentionPolicy.SOURCE)
2039    public @interface TextAlignment {}
2040
2041    /**
2042     * Default text alignment. The text alignment of this View is inherited from its parent.
2043     * Use with {@link #setTextAlignment(int)}
2044     */
2045    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2046
2047    /**
2048     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2049     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2050     *
2051     * Use with {@link #setTextAlignment(int)}
2052     */
2053    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2054
2055    /**
2056     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2057     *
2058     * Use with {@link #setTextAlignment(int)}
2059     */
2060    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2061
2062    /**
2063     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2064     *
2065     * Use with {@link #setTextAlignment(int)}
2066     */
2067    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2068
2069    /**
2070     * Center the paragraph, e.g. ALIGN_CENTER.
2071     *
2072     * Use with {@link #setTextAlignment(int)}
2073     */
2074    public static final int TEXT_ALIGNMENT_CENTER = 4;
2075
2076    /**
2077     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2078     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2079     *
2080     * Use with {@link #setTextAlignment(int)}
2081     */
2082    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2083
2084    /**
2085     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2086     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2087     *
2088     * Use with {@link #setTextAlignment(int)}
2089     */
2090    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2091
2092    /**
2093     * Default text alignment is inherited
2094     */
2095    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2096
2097    /**
2098     * Default resolved text alignment
2099     * @hide
2100     */
2101    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2102
2103    /**
2104      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2105      * @hide
2106      */
2107    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2108
2109    /**
2110      * Mask for use with private flags indicating bits used for text alignment.
2111      * @hide
2112      */
2113    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2114
2115    /**
2116     * Array of text direction flags for mapping attribute "textAlignment" to correct
2117     * flag value.
2118     * @hide
2119     */
2120    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2121            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2122            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2123            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2124            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2125            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2126            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2127            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2128    };
2129
2130    /**
2131     * Indicates whether the view text alignment has been resolved.
2132     * @hide
2133     */
2134    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2135
2136    /**
2137     * Bit shift to get the resolved text alignment.
2138     * @hide
2139     */
2140    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2141
2142    /**
2143     * Mask for use with private flags indicating bits used for text alignment.
2144     * @hide
2145     */
2146    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2147            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2148
2149    /**
2150     * Indicates whether if the view text alignment has been resolved to gravity
2151     */
2152    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2153            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2154
2155    // Accessiblity constants for mPrivateFlags2
2156
2157    /**
2158     * Shift for the bits in {@link #mPrivateFlags2} related to the
2159     * "importantForAccessibility" attribute.
2160     */
2161    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2162
2163    /**
2164     * Automatically determine whether a view is important for accessibility.
2165     */
2166    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2167
2168    /**
2169     * The view is important for accessibility.
2170     */
2171    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2172
2173    /**
2174     * The view is not important for accessibility.
2175     */
2176    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2177
2178    /**
2179     * The view is not important for accessibility, nor are any of its
2180     * descendant views.
2181     */
2182    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2183
2184    /**
2185     * The default whether the view is important for accessibility.
2186     */
2187    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2188
2189    /**
2190     * Mask for obtainig the bits which specify how to determine
2191     * whether a view is important for accessibility.
2192     */
2193    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2194        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2195        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2196        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2197
2198    /**
2199     * Shift for the bits in {@link #mPrivateFlags2} related to the
2200     * "accessibilityLiveRegion" attribute.
2201     */
2202    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2203
2204    /**
2205     * Live region mode specifying that accessibility services should not
2206     * automatically announce changes to this view. This is the default live
2207     * region mode for most views.
2208     * <p>
2209     * Use with {@link #setAccessibilityLiveRegion(int)}.
2210     */
2211    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2212
2213    /**
2214     * Live region mode specifying that accessibility services should announce
2215     * changes to this view.
2216     * <p>
2217     * Use with {@link #setAccessibilityLiveRegion(int)}.
2218     */
2219    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2220
2221    /**
2222     * Live region mode specifying that accessibility services should interrupt
2223     * ongoing speech to immediately announce changes to this view.
2224     * <p>
2225     * Use with {@link #setAccessibilityLiveRegion(int)}.
2226     */
2227    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2228
2229    /**
2230     * The default whether the view is important for accessibility.
2231     */
2232    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2233
2234    /**
2235     * Mask for obtaining the bits which specify a view's accessibility live
2236     * region mode.
2237     */
2238    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2239            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2240            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2241
2242    /**
2243     * Flag indicating whether a view has accessibility focus.
2244     */
2245    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2246
2247    /**
2248     * Flag whether the accessibility state of the subtree rooted at this view changed.
2249     */
2250    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2251
2252    /**
2253     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2254     * is used to check whether later changes to the view's transform should invalidate the
2255     * view to force the quickReject test to run again.
2256     */
2257    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2258
2259    /**
2260     * Flag indicating that start/end padding has been resolved into left/right padding
2261     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2262     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2263     * during measurement. In some special cases this is required such as when an adapter-based
2264     * view measures prospective children without attaching them to a window.
2265     */
2266    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2267
2268    /**
2269     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2270     */
2271    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2272
2273    /**
2274     * Indicates that the view is tracking some sort of transient state
2275     * that the app should not need to be aware of, but that the framework
2276     * should take special care to preserve.
2277     */
2278    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2279
2280    /**
2281     * Group of bits indicating that RTL properties resolution is done.
2282     */
2283    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2284            PFLAG2_TEXT_DIRECTION_RESOLVED |
2285            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2286            PFLAG2_PADDING_RESOLVED |
2287            PFLAG2_DRAWABLE_RESOLVED;
2288
2289    // There are a couple of flags left in mPrivateFlags2
2290
2291    /* End of masks for mPrivateFlags2 */
2292
2293    /**
2294     * Masks for mPrivateFlags3, as generated by dumpFlags():
2295     *
2296     * |-------|-------|-------|-------|
2297     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2298     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2299     *                               1   PFLAG3_IS_LAID_OUT
2300     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2301     *                             1     PFLAG3_CALLED_SUPER
2302     * |-------|-------|-------|-------|
2303     */
2304
2305    /**
2306     * Flag indicating that view has a transform animation set on it. This is used to track whether
2307     * an animation is cleared between successive frames, in order to tell the associated
2308     * DisplayList to clear its animation matrix.
2309     */
2310    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2311
2312    /**
2313     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2314     * animation is cleared between successive frames, in order to tell the associated
2315     * DisplayList to restore its alpha value.
2316     */
2317    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2318
2319    /**
2320     * Flag indicating that the view has been through at least one layout since it
2321     * was last attached to a window.
2322     */
2323    static final int PFLAG3_IS_LAID_OUT = 0x4;
2324
2325    /**
2326     * Flag indicating that a call to measure() was skipped and should be done
2327     * instead when layout() is invoked.
2328     */
2329    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2330
2331    /**
2332     * Flag indicating that an overridden method correctly called down to
2333     * the superclass implementation as required by the API spec.
2334     */
2335    static final int PFLAG3_CALLED_SUPER = 0x10;
2336
2337    /**
2338     * Flag indicating that we're in the process of applying window insets.
2339     */
2340    static final int PFLAG3_APPLYING_INSETS = 0x20;
2341
2342    /**
2343     * Flag indicating that we're in the process of fitting system windows using the old method.
2344     */
2345    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2346
2347    /**
2348     * Flag indicating that nested scrolling is enabled for this view.
2349     * The view will optionally cooperate with views up its parent chain to allow for
2350     * integrated nested scrolling along the same axis.
2351     */
2352    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2353
2354    /* End of masks for mPrivateFlags3 */
2355
2356    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2357
2358    /**
2359     * Always allow a user to over-scroll this view, provided it is a
2360     * view that can scroll.
2361     *
2362     * @see #getOverScrollMode()
2363     * @see #setOverScrollMode(int)
2364     */
2365    public static final int OVER_SCROLL_ALWAYS = 0;
2366
2367    /**
2368     * Allow a user to over-scroll this view only if the content is large
2369     * enough to meaningfully scroll, provided it is a view that can scroll.
2370     *
2371     * @see #getOverScrollMode()
2372     * @see #setOverScrollMode(int)
2373     */
2374    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2375
2376    /**
2377     * Never allow a user to over-scroll this view.
2378     *
2379     * @see #getOverScrollMode()
2380     * @see #setOverScrollMode(int)
2381     */
2382    public static final int OVER_SCROLL_NEVER = 2;
2383
2384    /**
2385     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2386     * requested the system UI (status bar) to be visible (the default).
2387     *
2388     * @see #setSystemUiVisibility(int)
2389     */
2390    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2391
2392    /**
2393     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2394     * system UI to enter an unobtrusive "low profile" mode.
2395     *
2396     * <p>This is for use in games, book readers, video players, or any other
2397     * "immersive" application where the usual system chrome is deemed too distracting.
2398     *
2399     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2400     *
2401     * @see #setSystemUiVisibility(int)
2402     */
2403    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2404
2405    /**
2406     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2407     * system navigation be temporarily hidden.
2408     *
2409     * <p>This is an even less obtrusive state than that called for by
2410     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2411     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2412     * those to disappear. This is useful (in conjunction with the
2413     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2414     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2415     * window flags) for displaying content using every last pixel on the display.
2416     *
2417     * <p>There is a limitation: because navigation controls are so important, the least user
2418     * interaction will cause them to reappear immediately.  When this happens, both
2419     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2420     * so that both elements reappear at the same time.
2421     *
2422     * @see #setSystemUiVisibility(int)
2423     */
2424    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2425
2426    /**
2427     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2428     * into the normal fullscreen mode so that its content can take over the screen
2429     * while still allowing the user to interact with the application.
2430     *
2431     * <p>This has the same visual effect as
2432     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2433     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2434     * meaning that non-critical screen decorations (such as the status bar) will be
2435     * hidden while the user is in the View's window, focusing the experience on
2436     * that content.  Unlike the window flag, if you are using ActionBar in
2437     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2438     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2439     * hide the action bar.
2440     *
2441     * <p>This approach to going fullscreen is best used over the window flag when
2442     * it is a transient state -- that is, the application does this at certain
2443     * points in its user interaction where it wants to allow the user to focus
2444     * on content, but not as a continuous state.  For situations where the application
2445     * would like to simply stay full screen the entire time (such as a game that
2446     * wants to take over the screen), the
2447     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2448     * is usually a better approach.  The state set here will be removed by the system
2449     * in various situations (such as the user moving to another application) like
2450     * the other system UI states.
2451     *
2452     * <p>When using this flag, the application should provide some easy facility
2453     * for the user to go out of it.  A common example would be in an e-book
2454     * reader, where tapping on the screen brings back whatever screen and UI
2455     * decorations that had been hidden while the user was immersed in reading
2456     * the book.
2457     *
2458     * @see #setSystemUiVisibility(int)
2459     */
2460    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2461
2462    /**
2463     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2464     * flags, we would like a stable view of the content insets given to
2465     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2466     * will always represent the worst case that the application can expect
2467     * as a continuous state.  In the stock Android UI this is the space for
2468     * the system bar, nav bar, and status bar, but not more transient elements
2469     * such as an input method.
2470     *
2471     * The stable layout your UI sees is based on the system UI modes you can
2472     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2473     * then you will get a stable layout for changes of the
2474     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2475     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2476     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2477     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2478     * with a stable layout.  (Note that you should avoid using
2479     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2480     *
2481     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2482     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2483     * then a hidden status bar will be considered a "stable" state for purposes
2484     * here.  This allows your UI to continually hide the status bar, while still
2485     * using the system UI flags to hide the action bar while still retaining
2486     * a stable layout.  Note that changing the window fullscreen flag will never
2487     * provide a stable layout for a clean transition.
2488     *
2489     * <p>If you are using ActionBar in
2490     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2491     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2492     * insets it adds to those given to the application.
2493     */
2494    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2495
2496    /**
2497     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2498     * to be laid out as if it has requested
2499     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2500     * allows it to avoid artifacts when switching in and out of that mode, at
2501     * the expense that some of its user interface may be covered by screen
2502     * decorations when they are shown.  You can perform layout of your inner
2503     * UI elements to account for the navigation system UI through the
2504     * {@link #fitSystemWindows(Rect)} method.
2505     */
2506    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2507
2508    /**
2509     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2510     * to be laid out as if it has requested
2511     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2512     * allows it to avoid artifacts when switching in and out of that mode, at
2513     * the expense that some of its user interface may be covered by screen
2514     * decorations when they are shown.  You can perform layout of your inner
2515     * UI elements to account for non-fullscreen system UI through the
2516     * {@link #fitSystemWindows(Rect)} method.
2517     */
2518    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2519
2520    /**
2521     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2522     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2523     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2524     * user interaction.
2525     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2526     * has an effect when used in combination with that flag.</p>
2527     */
2528    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2529
2530    /**
2531     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2532     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2533     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2534     * experience while also hiding the system bars.  If this flag is not set,
2535     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2536     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2537     * if the user swipes from the top of the screen.
2538     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2539     * system gestures, such as swiping from the top of the screen.  These transient system bars
2540     * will overlay app’s content, may have some degree of transparency, and will automatically
2541     * hide after a short timeout.
2542     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2543     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2544     * with one or both of those flags.</p>
2545     */
2546    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2547
2548    /**
2549     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2550     * is compatible with light status bar backgrounds.
2551     *
2552     * <p>For this to take effect, the window must request
2553     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2554     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2555     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2556     *         FLAG_TRANSLUCENT_STATUS}.
2557     *
2558     * @see android.R.attr#windowHasLightStatusBar
2559     */
2560    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2561
2562    /**
2563     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2564     */
2565    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2566
2567    /**
2568     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2569     */
2570    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2571
2572    /**
2573     * @hide
2574     *
2575     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2576     * out of the public fields to keep the undefined bits out of the developer's way.
2577     *
2578     * Flag to make the status bar not expandable.  Unless you also
2579     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2580     */
2581    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2582
2583    /**
2584     * @hide
2585     *
2586     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2587     * out of the public fields to keep the undefined bits out of the developer's way.
2588     *
2589     * Flag to hide notification icons and scrolling ticker text.
2590     */
2591    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2592
2593    /**
2594     * @hide
2595     *
2596     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2597     * out of the public fields to keep the undefined bits out of the developer's way.
2598     *
2599     * Flag to disable incoming notification alerts.  This will not block
2600     * icons, but it will block sound, vibrating and other visual or aural notifications.
2601     */
2602    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2603
2604    /**
2605     * @hide
2606     *
2607     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2608     * out of the public fields to keep the undefined bits out of the developer's way.
2609     *
2610     * Flag to hide only the scrolling ticker.  Note that
2611     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2612     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2613     */
2614    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2615
2616    /**
2617     * @hide
2618     *
2619     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2620     * out of the public fields to keep the undefined bits out of the developer's way.
2621     *
2622     * Flag to hide the center system info area.
2623     */
2624    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2625
2626    /**
2627     * @hide
2628     *
2629     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2630     * out of the public fields to keep the undefined bits out of the developer's way.
2631     *
2632     * Flag to hide only the home button.  Don't use this
2633     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2634     */
2635    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2636
2637    /**
2638     * @hide
2639     *
2640     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2641     * out of the public fields to keep the undefined bits out of the developer's way.
2642     *
2643     * Flag to hide only the back button. Don't use this
2644     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2645     */
2646    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2647
2648    /**
2649     * @hide
2650     *
2651     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2652     * out of the public fields to keep the undefined bits out of the developer's way.
2653     *
2654     * Flag to hide only the clock.  You might use this if your activity has
2655     * its own clock making the status bar's clock redundant.
2656     */
2657    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2658
2659    /**
2660     * @hide
2661     *
2662     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2663     * out of the public fields to keep the undefined bits out of the developer's way.
2664     *
2665     * Flag to hide only the recent apps button. Don't use this
2666     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2667     */
2668    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2669
2670    /**
2671     * @hide
2672     *
2673     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2674     * out of the public fields to keep the undefined bits out of the developer's way.
2675     *
2676     * Flag to disable the global search gesture. Don't use this
2677     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2678     */
2679    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2680
2681    /**
2682     * @hide
2683     *
2684     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2685     * out of the public fields to keep the undefined bits out of the developer's way.
2686     *
2687     * Flag to specify that the status bar is displayed in transient mode.
2688     */
2689    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2690
2691    /**
2692     * @hide
2693     *
2694     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2695     * out of the public fields to keep the undefined bits out of the developer's way.
2696     *
2697     * Flag to specify that the navigation bar is displayed in transient mode.
2698     */
2699    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2700
2701    /**
2702     * @hide
2703     *
2704     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2705     * out of the public fields to keep the undefined bits out of the developer's way.
2706     *
2707     * Flag to specify that the hidden status bar would like to be shown.
2708     */
2709    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2710
2711    /**
2712     * @hide
2713     *
2714     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2715     * out of the public fields to keep the undefined bits out of the developer's way.
2716     *
2717     * Flag to specify that the hidden navigation bar would like to be shown.
2718     */
2719    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2720
2721    /**
2722     * @hide
2723     *
2724     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2725     * out of the public fields to keep the undefined bits out of the developer's way.
2726     *
2727     * Flag to specify that the status bar is displayed in translucent mode.
2728     */
2729    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2730
2731    /**
2732     * @hide
2733     *
2734     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2735     * out of the public fields to keep the undefined bits out of the developer's way.
2736     *
2737     * Flag to specify that the navigation bar is displayed in translucent mode.
2738     */
2739    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2740
2741    /**
2742     * @hide
2743     *
2744     * Whether Recents is visible or not.
2745     */
2746    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2747
2748    /**
2749     * @hide
2750     *
2751     * Makes system ui transparent.
2752     */
2753    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2754
2755    /**
2756     * @hide
2757     */
2758    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2759
2760    /**
2761     * These are the system UI flags that can be cleared by events outside
2762     * of an application.  Currently this is just the ability to tap on the
2763     * screen while hiding the navigation bar to have it return.
2764     * @hide
2765     */
2766    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2767            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2768            | SYSTEM_UI_FLAG_FULLSCREEN;
2769
2770    /**
2771     * Flags that can impact the layout in relation to system UI.
2772     */
2773    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2774            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2775            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2776
2777    /** @hide */
2778    @IntDef(flag = true,
2779            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2780    @Retention(RetentionPolicy.SOURCE)
2781    public @interface FindViewFlags {}
2782
2783    /**
2784     * Find views that render the specified text.
2785     *
2786     * @see #findViewsWithText(ArrayList, CharSequence, int)
2787     */
2788    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2789
2790    /**
2791     * Find find views that contain the specified content description.
2792     *
2793     * @see #findViewsWithText(ArrayList, CharSequence, int)
2794     */
2795    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2796
2797    /**
2798     * Find views that contain {@link AccessibilityNodeProvider}. Such
2799     * a View is a root of virtual view hierarchy and may contain the searched
2800     * text. If this flag is set Views with providers are automatically
2801     * added and it is a responsibility of the client to call the APIs of
2802     * the provider to determine whether the virtual tree rooted at this View
2803     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2804     * representing the virtual views with this text.
2805     *
2806     * @see #findViewsWithText(ArrayList, CharSequence, int)
2807     *
2808     * @hide
2809     */
2810    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2811
2812    /**
2813     * The undefined cursor position.
2814     *
2815     * @hide
2816     */
2817    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2818
2819    /**
2820     * Indicates that the screen has changed state and is now off.
2821     *
2822     * @see #onScreenStateChanged(int)
2823     */
2824    public static final int SCREEN_STATE_OFF = 0x0;
2825
2826    /**
2827     * Indicates that the screen has changed state and is now on.
2828     *
2829     * @see #onScreenStateChanged(int)
2830     */
2831    public static final int SCREEN_STATE_ON = 0x1;
2832
2833    /**
2834     * Indicates no axis of view scrolling.
2835     */
2836    public static final int SCROLL_AXIS_NONE = 0;
2837
2838    /**
2839     * Indicates scrolling along the horizontal axis.
2840     */
2841    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2842
2843    /**
2844     * Indicates scrolling along the vertical axis.
2845     */
2846    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2847
2848    /**
2849     * Controls the over-scroll mode for this view.
2850     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2851     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2852     * and {@link #OVER_SCROLL_NEVER}.
2853     */
2854    private int mOverScrollMode;
2855
2856    /**
2857     * The parent this view is attached to.
2858     * {@hide}
2859     *
2860     * @see #getParent()
2861     */
2862    protected ViewParent mParent;
2863
2864    /**
2865     * {@hide}
2866     */
2867    AttachInfo mAttachInfo;
2868
2869    /**
2870     * {@hide}
2871     */
2872    @ViewDebug.ExportedProperty(flagMapping = {
2873        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2874                name = "FORCE_LAYOUT"),
2875        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2876                name = "LAYOUT_REQUIRED"),
2877        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2878            name = "DRAWING_CACHE_INVALID", outputIf = false),
2879        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2880        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2881        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2882        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2883    }, formatToHexString = true)
2884    int mPrivateFlags;
2885    int mPrivateFlags2;
2886    int mPrivateFlags3;
2887
2888    /**
2889     * This view's request for the visibility of the status bar.
2890     * @hide
2891     */
2892    @ViewDebug.ExportedProperty(flagMapping = {
2893        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2894                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2895                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2896        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2897                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2898                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2899        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2900                                equals = SYSTEM_UI_FLAG_VISIBLE,
2901                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2902    }, formatToHexString = true)
2903    int mSystemUiVisibility;
2904
2905    /**
2906     * Reference count for transient state.
2907     * @see #setHasTransientState(boolean)
2908     */
2909    int mTransientStateCount = 0;
2910
2911    /**
2912     * Count of how many windows this view has been attached to.
2913     */
2914    int mWindowAttachCount;
2915
2916    /**
2917     * The layout parameters associated with this view and used by the parent
2918     * {@link android.view.ViewGroup} to determine how this view should be
2919     * laid out.
2920     * {@hide}
2921     */
2922    protected ViewGroup.LayoutParams mLayoutParams;
2923
2924    /**
2925     * The view flags hold various views states.
2926     * {@hide}
2927     */
2928    @ViewDebug.ExportedProperty(formatToHexString = true)
2929    int mViewFlags;
2930
2931    static class TransformationInfo {
2932        /**
2933         * The transform matrix for the View. This transform is calculated internally
2934         * based on the translation, rotation, and scale properties.
2935         *
2936         * Do *not* use this variable directly; instead call getMatrix(), which will
2937         * load the value from the View's RenderNode.
2938         */
2939        private final Matrix mMatrix = new Matrix();
2940
2941        /**
2942         * The inverse transform matrix for the View. This transform is calculated
2943         * internally based on the translation, rotation, and scale properties.
2944         *
2945         * Do *not* use this variable directly; instead call getInverseMatrix(),
2946         * which will load the value from the View's RenderNode.
2947         */
2948        private Matrix mInverseMatrix;
2949
2950        /**
2951         * The opacity of the View. This is a value from 0 to 1, where 0 means
2952         * completely transparent and 1 means completely opaque.
2953         */
2954        @ViewDebug.ExportedProperty
2955        float mAlpha = 1f;
2956
2957        /**
2958         * The opacity of the view as manipulated by the Fade transition. This is a hidden
2959         * property only used by transitions, which is composited with the other alpha
2960         * values to calculate the final visual alpha value.
2961         */
2962        float mTransitionAlpha = 1f;
2963    }
2964
2965    TransformationInfo mTransformationInfo;
2966
2967    /**
2968     * Current clip bounds. to which all drawing of this view are constrained.
2969     */
2970    Rect mClipBounds = null;
2971
2972    private boolean mLastIsOpaque;
2973
2974    /**
2975     * The distance in pixels from the left edge of this view's parent
2976     * to the left edge of this view.
2977     * {@hide}
2978     */
2979    @ViewDebug.ExportedProperty(category = "layout")
2980    protected int mLeft;
2981    /**
2982     * The distance in pixels from the left edge of this view's parent
2983     * to the right edge of this view.
2984     * {@hide}
2985     */
2986    @ViewDebug.ExportedProperty(category = "layout")
2987    protected int mRight;
2988    /**
2989     * The distance in pixels from the top edge of this view's parent
2990     * to the top edge of this view.
2991     * {@hide}
2992     */
2993    @ViewDebug.ExportedProperty(category = "layout")
2994    protected int mTop;
2995    /**
2996     * The distance in pixels from the top edge of this view's parent
2997     * to the bottom edge of this view.
2998     * {@hide}
2999     */
3000    @ViewDebug.ExportedProperty(category = "layout")
3001    protected int mBottom;
3002
3003    /**
3004     * The offset, in pixels, by which the content of this view is scrolled
3005     * horizontally.
3006     * {@hide}
3007     */
3008    @ViewDebug.ExportedProperty(category = "scrolling")
3009    protected int mScrollX;
3010    /**
3011     * The offset, in pixels, by which the content of this view is scrolled
3012     * vertically.
3013     * {@hide}
3014     */
3015    @ViewDebug.ExportedProperty(category = "scrolling")
3016    protected int mScrollY;
3017
3018    /**
3019     * The left padding in pixels, that is the distance in pixels between the
3020     * left edge of this view and the left edge of its content.
3021     * {@hide}
3022     */
3023    @ViewDebug.ExportedProperty(category = "padding")
3024    protected int mPaddingLeft = 0;
3025    /**
3026     * The right padding in pixels, that is the distance in pixels between the
3027     * right edge of this view and the right edge of its content.
3028     * {@hide}
3029     */
3030    @ViewDebug.ExportedProperty(category = "padding")
3031    protected int mPaddingRight = 0;
3032    /**
3033     * The top padding in pixels, that is the distance in pixels between the
3034     * top edge of this view and the top edge of its content.
3035     * {@hide}
3036     */
3037    @ViewDebug.ExportedProperty(category = "padding")
3038    protected int mPaddingTop;
3039    /**
3040     * The bottom padding in pixels, that is the distance in pixels between the
3041     * bottom edge of this view and the bottom edge of its content.
3042     * {@hide}
3043     */
3044    @ViewDebug.ExportedProperty(category = "padding")
3045    protected int mPaddingBottom;
3046
3047    /**
3048     * The layout insets in pixels, that is the distance in pixels between the
3049     * visible edges of this view its bounds.
3050     */
3051    private Insets mLayoutInsets;
3052
3053    /**
3054     * Briefly describes the view and is primarily used for accessibility support.
3055     */
3056    private CharSequence mContentDescription;
3057
3058    /**
3059     * Specifies the id of a view for which this view serves as a label for
3060     * accessibility purposes.
3061     */
3062    private int mLabelForId = View.NO_ID;
3063
3064    /**
3065     * Predicate for matching labeled view id with its label for
3066     * accessibility purposes.
3067     */
3068    private MatchLabelForPredicate mMatchLabelForPredicate;
3069
3070    /**
3071     * Specifies a view before which this one is visited in accessibility traversal.
3072     */
3073    private int mAccessibilityTraversalBeforeId = NO_ID;
3074
3075    /**
3076     * Specifies a view after which this one is visited in accessibility traversal.
3077     */
3078    private int mAccessibilityTraversalAfterId = NO_ID;
3079
3080    /**
3081     * Predicate for matching a view by its id.
3082     */
3083    private MatchIdPredicate mMatchIdPredicate;
3084
3085    /**
3086     * Cache the paddingRight set by the user to append to the scrollbar's size.
3087     *
3088     * @hide
3089     */
3090    @ViewDebug.ExportedProperty(category = "padding")
3091    protected int mUserPaddingRight;
3092
3093    /**
3094     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3095     *
3096     * @hide
3097     */
3098    @ViewDebug.ExportedProperty(category = "padding")
3099    protected int mUserPaddingBottom;
3100
3101    /**
3102     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3103     *
3104     * @hide
3105     */
3106    @ViewDebug.ExportedProperty(category = "padding")
3107    protected int mUserPaddingLeft;
3108
3109    /**
3110     * Cache the paddingStart set by the user to append to the scrollbar's size.
3111     *
3112     */
3113    @ViewDebug.ExportedProperty(category = "padding")
3114    int mUserPaddingStart;
3115
3116    /**
3117     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3118     *
3119     */
3120    @ViewDebug.ExportedProperty(category = "padding")
3121    int mUserPaddingEnd;
3122
3123    /**
3124     * Cache initial left padding.
3125     *
3126     * @hide
3127     */
3128    int mUserPaddingLeftInitial;
3129
3130    /**
3131     * Cache initial right padding.
3132     *
3133     * @hide
3134     */
3135    int mUserPaddingRightInitial;
3136
3137    /**
3138     * Default undefined padding
3139     */
3140    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3141
3142    /**
3143     * Cache if a left padding has been defined
3144     */
3145    private boolean mLeftPaddingDefined = false;
3146
3147    /**
3148     * Cache if a right padding has been defined
3149     */
3150    private boolean mRightPaddingDefined = false;
3151
3152    /**
3153     * @hide
3154     */
3155    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3156    /**
3157     * @hide
3158     */
3159    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3160
3161    private LongSparseLongArray mMeasureCache;
3162
3163    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3164    private Drawable mBackground;
3165    private TintInfo mBackgroundTint;
3166
3167    /**
3168     * RenderNode used for backgrounds.
3169     * <p>
3170     * When non-null and valid, this is expected to contain an up-to-date copy
3171     * of the background drawable. It is cleared on temporary detach, and reset
3172     * on cleanup.
3173     */
3174    private RenderNode mBackgroundRenderNode;
3175
3176    private int mBackgroundResource;
3177    private boolean mBackgroundSizeChanged;
3178
3179    private String mTransitionName;
3180
3181    private static class TintInfo {
3182        ColorStateList mTintList;
3183        PorterDuff.Mode mTintMode;
3184        boolean mHasTintMode;
3185        boolean mHasTintList;
3186    }
3187
3188    static class ListenerInfo {
3189        /**
3190         * Listener used to dispatch focus change events.
3191         * This field should be made private, so it is hidden from the SDK.
3192         * {@hide}
3193         */
3194        protected OnFocusChangeListener mOnFocusChangeListener;
3195
3196        /**
3197         * Listeners for layout change events.
3198         */
3199        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3200
3201        protected OnScrollChangeListener mOnScrollChangeListener;
3202
3203        /**
3204         * Listeners for attach events.
3205         */
3206        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3207
3208        /**
3209         * Listener used to dispatch click events.
3210         * This field should be made private, so it is hidden from the SDK.
3211         * {@hide}
3212         */
3213        public OnClickListener mOnClickListener;
3214
3215        /**
3216         * Listener used to dispatch long click events.
3217         * This field should be made private, so it is hidden from the SDK.
3218         * {@hide}
3219         */
3220        protected OnLongClickListener mOnLongClickListener;
3221
3222        /**
3223         * Listener used to build the context menu.
3224         * This field should be made private, so it is hidden from the SDK.
3225         * {@hide}
3226         */
3227        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3228
3229        private OnKeyListener mOnKeyListener;
3230
3231        private OnTouchListener mOnTouchListener;
3232
3233        private OnHoverListener mOnHoverListener;
3234
3235        private OnGenericMotionListener mOnGenericMotionListener;
3236
3237        private OnDragListener mOnDragListener;
3238
3239        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3240
3241        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3242    }
3243
3244    ListenerInfo mListenerInfo;
3245
3246    /**
3247     * The application environment this view lives in.
3248     * This field should be made private, so it is hidden from the SDK.
3249     * {@hide}
3250     */
3251    @ViewDebug.ExportedProperty(deepExport = true)
3252    protected Context mContext;
3253
3254    private final Resources mResources;
3255
3256    private ScrollabilityCache mScrollCache;
3257
3258    private int[] mDrawableState = null;
3259
3260    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3261
3262    /**
3263     * Animator that automatically runs based on state changes.
3264     */
3265    private StateListAnimator mStateListAnimator;
3266
3267    /**
3268     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3269     * the user may specify which view to go to next.
3270     */
3271    private int mNextFocusLeftId = View.NO_ID;
3272
3273    /**
3274     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3275     * the user may specify which view to go to next.
3276     */
3277    private int mNextFocusRightId = View.NO_ID;
3278
3279    /**
3280     * When this view has focus and the next focus is {@link #FOCUS_UP},
3281     * the user may specify which view to go to next.
3282     */
3283    private int mNextFocusUpId = View.NO_ID;
3284
3285    /**
3286     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3287     * the user may specify which view to go to next.
3288     */
3289    private int mNextFocusDownId = View.NO_ID;
3290
3291    /**
3292     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3293     * the user may specify which view to go to next.
3294     */
3295    int mNextFocusForwardId = View.NO_ID;
3296
3297    private CheckForLongPress mPendingCheckForLongPress;
3298    private CheckForTap mPendingCheckForTap = null;
3299    private PerformClick mPerformClick;
3300    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3301
3302    private UnsetPressedState mUnsetPressedState;
3303
3304    /**
3305     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3306     * up event while a long press is invoked as soon as the long press duration is reached, so
3307     * a long press could be performed before the tap is checked, in which case the tap's action
3308     * should not be invoked.
3309     */
3310    private boolean mHasPerformedLongPress;
3311
3312    /**
3313     * The minimum height of the view. We'll try our best to have the height
3314     * of this view to at least this amount.
3315     */
3316    @ViewDebug.ExportedProperty(category = "measurement")
3317    private int mMinHeight;
3318
3319    /**
3320     * The minimum width of the view. We'll try our best to have the width
3321     * of this view to at least this amount.
3322     */
3323    @ViewDebug.ExportedProperty(category = "measurement")
3324    private int mMinWidth;
3325
3326    /**
3327     * The delegate to handle touch events that are physically in this view
3328     * but should be handled by another view.
3329     */
3330    private TouchDelegate mTouchDelegate = null;
3331
3332    /**
3333     * Solid color to use as a background when creating the drawing cache. Enables
3334     * the cache to use 16 bit bitmaps instead of 32 bit.
3335     */
3336    private int mDrawingCacheBackgroundColor = 0;
3337
3338    /**
3339     * Special tree observer used when mAttachInfo is null.
3340     */
3341    private ViewTreeObserver mFloatingTreeObserver;
3342
3343    /**
3344     * Cache the touch slop from the context that created the view.
3345     */
3346    private int mTouchSlop;
3347
3348    /**
3349     * Object that handles automatic animation of view properties.
3350     */
3351    private ViewPropertyAnimator mAnimator = null;
3352
3353    /**
3354     * Flag indicating that a drag can cross window boundaries.  When
3355     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3356     * with this flag set, all visible applications will be able to participate
3357     * in the drag operation and receive the dragged content.
3358     *
3359     * @hide
3360     */
3361    public static final int DRAG_FLAG_GLOBAL = 1;
3362
3363    /**
3364     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3365     */
3366    private float mVerticalScrollFactor;
3367
3368    /**
3369     * Position of the vertical scroll bar.
3370     */
3371    private int mVerticalScrollbarPosition;
3372
3373    /**
3374     * Position the scroll bar at the default position as determined by the system.
3375     */
3376    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3377
3378    /**
3379     * Position the scroll bar along the left edge.
3380     */
3381    public static final int SCROLLBAR_POSITION_LEFT = 1;
3382
3383    /**
3384     * Position the scroll bar along the right edge.
3385     */
3386    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3387
3388    /**
3389     * Indicates that the view does not have a layer.
3390     *
3391     * @see #getLayerType()
3392     * @see #setLayerType(int, android.graphics.Paint)
3393     * @see #LAYER_TYPE_SOFTWARE
3394     * @see #LAYER_TYPE_HARDWARE
3395     */
3396    public static final int LAYER_TYPE_NONE = 0;
3397
3398    /**
3399     * <p>Indicates that the view has a software layer. A software layer is backed
3400     * by a bitmap and causes the view to be rendered using Android's software
3401     * rendering pipeline, even if hardware acceleration is enabled.</p>
3402     *
3403     * <p>Software layers have various usages:</p>
3404     * <p>When the application is not using hardware acceleration, a software layer
3405     * is useful to apply a specific color filter and/or blending mode and/or
3406     * translucency to a view and all its children.</p>
3407     * <p>When the application is using hardware acceleration, a software layer
3408     * is useful to render drawing primitives not supported by the hardware
3409     * accelerated pipeline. It can also be used to cache a complex view tree
3410     * into a texture and reduce the complexity of drawing operations. For instance,
3411     * when animating a complex view tree with a translation, a software layer can
3412     * be used to render the view tree only once.</p>
3413     * <p>Software layers should be avoided when the affected view tree updates
3414     * often. Every update will require to re-render the software layer, which can
3415     * potentially be slow (particularly when hardware acceleration is turned on
3416     * since the layer will have to be uploaded into a hardware texture after every
3417     * update.)</p>
3418     *
3419     * @see #getLayerType()
3420     * @see #setLayerType(int, android.graphics.Paint)
3421     * @see #LAYER_TYPE_NONE
3422     * @see #LAYER_TYPE_HARDWARE
3423     */
3424    public static final int LAYER_TYPE_SOFTWARE = 1;
3425
3426    /**
3427     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3428     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3429     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3430     * rendering pipeline, but only if hardware acceleration is turned on for the
3431     * view hierarchy. When hardware acceleration is turned off, hardware layers
3432     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3433     *
3434     * <p>A hardware layer is useful to apply a specific color filter and/or
3435     * blending mode and/or translucency to a view and all its children.</p>
3436     * <p>A hardware layer can be used to cache a complex view tree into a
3437     * texture and reduce the complexity of drawing operations. For instance,
3438     * when animating a complex view tree with a translation, a hardware layer can
3439     * be used to render the view tree only once.</p>
3440     * <p>A hardware layer can also be used to increase the rendering quality when
3441     * rotation transformations are applied on a view. It can also be used to
3442     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3443     *
3444     * @see #getLayerType()
3445     * @see #setLayerType(int, android.graphics.Paint)
3446     * @see #LAYER_TYPE_NONE
3447     * @see #LAYER_TYPE_SOFTWARE
3448     */
3449    public static final int LAYER_TYPE_HARDWARE = 2;
3450
3451    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3452            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3453            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3454            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3455    })
3456    int mLayerType = LAYER_TYPE_NONE;
3457    Paint mLayerPaint;
3458
3459    /**
3460     * Set to true when drawing cache is enabled and cannot be created.
3461     *
3462     * @hide
3463     */
3464    public boolean mCachingFailed;
3465    private Bitmap mDrawingCache;
3466    private Bitmap mUnscaledDrawingCache;
3467
3468    /**
3469     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3470     * <p>
3471     * When non-null and valid, this is expected to contain an up-to-date copy
3472     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3473     * cleanup.
3474     */
3475    final RenderNode mRenderNode;
3476
3477    /**
3478     * Set to true when the view is sending hover accessibility events because it
3479     * is the innermost hovered view.
3480     */
3481    private boolean mSendingHoverAccessibilityEvents;
3482
3483    /**
3484     * Delegate for injecting accessibility functionality.
3485     */
3486    AccessibilityDelegate mAccessibilityDelegate;
3487
3488    /**
3489     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3490     * and add/remove objects to/from the overlay directly through the Overlay methods.
3491     */
3492    ViewOverlay mOverlay;
3493
3494    /**
3495     * The currently active parent view for receiving delegated nested scrolling events.
3496     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3497     * by {@link #stopNestedScroll()} at the same point where we clear
3498     * requestDisallowInterceptTouchEvent.
3499     */
3500    private ViewParent mNestedScrollingParent;
3501
3502    /**
3503     * Consistency verifier for debugging purposes.
3504     * @hide
3505     */
3506    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3507            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3508                    new InputEventConsistencyVerifier(this, 0) : null;
3509
3510    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3511
3512    private int[] mTempNestedScrollConsumed;
3513
3514    /**
3515     * An overlay is going to draw this View instead of being drawn as part of this
3516     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3517     * when this view is invalidated.
3518     */
3519    GhostView mGhostView;
3520
3521    /**
3522     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3523     * @hide
3524     */
3525    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3526    public String[] mAttributes;
3527
3528    /**
3529     * Maps a Resource id to its name.
3530     */
3531    private static SparseArray<String> mAttributeMap;
3532
3533    /**
3534     * Simple constructor to use when creating a view from code.
3535     *
3536     * @param context The Context the view is running in, through which it can
3537     *        access the current theme, resources, etc.
3538     */
3539    public View(Context context) {
3540        mContext = context;
3541        mResources = context != null ? context.getResources() : null;
3542        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3543        // Set some flags defaults
3544        mPrivateFlags2 =
3545                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3546                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3547                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3548                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3549                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3550                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3551        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3552        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3553        mUserPaddingStart = UNDEFINED_PADDING;
3554        mUserPaddingEnd = UNDEFINED_PADDING;
3555        mRenderNode = RenderNode.create(getClass().getName(), this);
3556
3557        if (!sCompatibilityDone && context != null) {
3558            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3559
3560            // Older apps may need this compatibility hack for measurement.
3561            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3562
3563            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3564            // of whether a layout was requested on that View.
3565            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3566
3567            sCompatibilityDone = true;
3568        }
3569    }
3570
3571    /**
3572     * Constructor that is called when inflating a view from XML. This is called
3573     * when a view is being constructed from an XML file, supplying attributes
3574     * that were specified in the XML file. This version uses a default style of
3575     * 0, so the only attribute values applied are those in the Context's Theme
3576     * and the given AttributeSet.
3577     *
3578     * <p>
3579     * The method onFinishInflate() will be called after all children have been
3580     * added.
3581     *
3582     * @param context The Context the view is running in, through which it can
3583     *        access the current theme, resources, etc.
3584     * @param attrs The attributes of the XML tag that is inflating the view.
3585     * @see #View(Context, AttributeSet, int)
3586     */
3587    public View(Context context, @Nullable AttributeSet attrs) {
3588        this(context, attrs, 0);
3589    }
3590
3591    /**
3592     * Perform inflation from XML and apply a class-specific base style from a
3593     * theme attribute. This constructor of View allows subclasses to use their
3594     * own base style when they are inflating. For example, a Button class's
3595     * constructor would call this version of the super class constructor and
3596     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3597     * allows the theme's button style to modify all of the base view attributes
3598     * (in particular its background) as well as the Button class's attributes.
3599     *
3600     * @param context The Context the view is running in, through which it can
3601     *        access the current theme, resources, etc.
3602     * @param attrs The attributes of the XML tag that is inflating the view.
3603     * @param defStyleAttr An attribute in the current theme that contains a
3604     *        reference to a style resource that supplies default values for
3605     *        the view. Can be 0 to not look for defaults.
3606     * @see #View(Context, AttributeSet)
3607     */
3608    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3609        this(context, attrs, defStyleAttr, 0);
3610    }
3611
3612    /**
3613     * Perform inflation from XML and apply a class-specific base style from a
3614     * theme attribute or style resource. This constructor of View allows
3615     * subclasses to use their own base style when they are inflating.
3616     * <p>
3617     * When determining the final value of a particular attribute, there are
3618     * four inputs that come into play:
3619     * <ol>
3620     * <li>Any attribute values in the given AttributeSet.
3621     * <li>The style resource specified in the AttributeSet (named "style").
3622     * <li>The default style specified by <var>defStyleAttr</var>.
3623     * <li>The default style specified by <var>defStyleRes</var>.
3624     * <li>The base values in this theme.
3625     * </ol>
3626     * <p>
3627     * Each of these inputs is considered in-order, with the first listed taking
3628     * precedence over the following ones. In other words, if in the
3629     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3630     * , then the button's text will <em>always</em> be black, regardless of
3631     * what is specified in any of the styles.
3632     *
3633     * @param context The Context the view is running in, through which it can
3634     *        access the current theme, resources, etc.
3635     * @param attrs The attributes of the XML tag that is inflating the view.
3636     * @param defStyleAttr An attribute in the current theme that contains a
3637     *        reference to a style resource that supplies default values for
3638     *        the view. Can be 0 to not look for defaults.
3639     * @param defStyleRes A resource identifier of a style resource that
3640     *        supplies default values for the view, used only if
3641     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3642     *        to not look for defaults.
3643     * @see #View(Context, AttributeSet, int)
3644     */
3645    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3646        this(context);
3647
3648        final TypedArray a = context.obtainStyledAttributes(
3649                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3650
3651        if (mDebugViewAttributes) {
3652            saveAttributeData(attrs, a);
3653        }
3654
3655        Drawable background = null;
3656
3657        int leftPadding = -1;
3658        int topPadding = -1;
3659        int rightPadding = -1;
3660        int bottomPadding = -1;
3661        int startPadding = UNDEFINED_PADDING;
3662        int endPadding = UNDEFINED_PADDING;
3663
3664        int padding = -1;
3665
3666        int viewFlagValues = 0;
3667        int viewFlagMasks = 0;
3668
3669        boolean setScrollContainer = false;
3670
3671        int x = 0;
3672        int y = 0;
3673
3674        float tx = 0;
3675        float ty = 0;
3676        float tz = 0;
3677        float elevation = 0;
3678        float rotation = 0;
3679        float rotationX = 0;
3680        float rotationY = 0;
3681        float sx = 1f;
3682        float sy = 1f;
3683        boolean transformSet = false;
3684
3685        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3686        int overScrollMode = mOverScrollMode;
3687        boolean initializeScrollbars = false;
3688
3689        boolean startPaddingDefined = false;
3690        boolean endPaddingDefined = false;
3691        boolean leftPaddingDefined = false;
3692        boolean rightPaddingDefined = false;
3693
3694        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3695
3696        final int N = a.getIndexCount();
3697        for (int i = 0; i < N; i++) {
3698            int attr = a.getIndex(i);
3699            switch (attr) {
3700                case com.android.internal.R.styleable.View_background:
3701                    background = a.getDrawable(attr);
3702                    break;
3703                case com.android.internal.R.styleable.View_padding:
3704                    padding = a.getDimensionPixelSize(attr, -1);
3705                    mUserPaddingLeftInitial = padding;
3706                    mUserPaddingRightInitial = padding;
3707                    leftPaddingDefined = true;
3708                    rightPaddingDefined = true;
3709                    break;
3710                 case com.android.internal.R.styleable.View_paddingLeft:
3711                    leftPadding = a.getDimensionPixelSize(attr, -1);
3712                    mUserPaddingLeftInitial = leftPadding;
3713                    leftPaddingDefined = true;
3714                    break;
3715                case com.android.internal.R.styleable.View_paddingTop:
3716                    topPadding = a.getDimensionPixelSize(attr, -1);
3717                    break;
3718                case com.android.internal.R.styleable.View_paddingRight:
3719                    rightPadding = a.getDimensionPixelSize(attr, -1);
3720                    mUserPaddingRightInitial = rightPadding;
3721                    rightPaddingDefined = true;
3722                    break;
3723                case com.android.internal.R.styleable.View_paddingBottom:
3724                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3725                    break;
3726                case com.android.internal.R.styleable.View_paddingStart:
3727                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3728                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3729                    break;
3730                case com.android.internal.R.styleable.View_paddingEnd:
3731                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3732                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3733                    break;
3734                case com.android.internal.R.styleable.View_scrollX:
3735                    x = a.getDimensionPixelOffset(attr, 0);
3736                    break;
3737                case com.android.internal.R.styleable.View_scrollY:
3738                    y = a.getDimensionPixelOffset(attr, 0);
3739                    break;
3740                case com.android.internal.R.styleable.View_alpha:
3741                    setAlpha(a.getFloat(attr, 1f));
3742                    break;
3743                case com.android.internal.R.styleable.View_transformPivotX:
3744                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3745                    break;
3746                case com.android.internal.R.styleable.View_transformPivotY:
3747                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3748                    break;
3749                case com.android.internal.R.styleable.View_translationX:
3750                    tx = a.getDimensionPixelOffset(attr, 0);
3751                    transformSet = true;
3752                    break;
3753                case com.android.internal.R.styleable.View_translationY:
3754                    ty = a.getDimensionPixelOffset(attr, 0);
3755                    transformSet = true;
3756                    break;
3757                case com.android.internal.R.styleable.View_translationZ:
3758                    tz = a.getDimensionPixelOffset(attr, 0);
3759                    transformSet = true;
3760                    break;
3761                case com.android.internal.R.styleable.View_elevation:
3762                    elevation = a.getDimensionPixelOffset(attr, 0);
3763                    transformSet = true;
3764                    break;
3765                case com.android.internal.R.styleable.View_rotation:
3766                    rotation = a.getFloat(attr, 0);
3767                    transformSet = true;
3768                    break;
3769                case com.android.internal.R.styleable.View_rotationX:
3770                    rotationX = a.getFloat(attr, 0);
3771                    transformSet = true;
3772                    break;
3773                case com.android.internal.R.styleable.View_rotationY:
3774                    rotationY = a.getFloat(attr, 0);
3775                    transformSet = true;
3776                    break;
3777                case com.android.internal.R.styleable.View_scaleX:
3778                    sx = a.getFloat(attr, 1f);
3779                    transformSet = true;
3780                    break;
3781                case com.android.internal.R.styleable.View_scaleY:
3782                    sy = a.getFloat(attr, 1f);
3783                    transformSet = true;
3784                    break;
3785                case com.android.internal.R.styleable.View_id:
3786                    mID = a.getResourceId(attr, NO_ID);
3787                    break;
3788                case com.android.internal.R.styleable.View_tag:
3789                    mTag = a.getText(attr);
3790                    break;
3791                case com.android.internal.R.styleable.View_fitsSystemWindows:
3792                    if (a.getBoolean(attr, false)) {
3793                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3794                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3795                    }
3796                    break;
3797                case com.android.internal.R.styleable.View_focusable:
3798                    if (a.getBoolean(attr, false)) {
3799                        viewFlagValues |= FOCUSABLE;
3800                        viewFlagMasks |= FOCUSABLE_MASK;
3801                    }
3802                    break;
3803                case com.android.internal.R.styleable.View_focusableInTouchMode:
3804                    if (a.getBoolean(attr, false)) {
3805                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3806                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3807                    }
3808                    break;
3809                case com.android.internal.R.styleable.View_clickable:
3810                    if (a.getBoolean(attr, false)) {
3811                        viewFlagValues |= CLICKABLE;
3812                        viewFlagMasks |= CLICKABLE;
3813                    }
3814                    break;
3815                case com.android.internal.R.styleable.View_longClickable:
3816                    if (a.getBoolean(attr, false)) {
3817                        viewFlagValues |= LONG_CLICKABLE;
3818                        viewFlagMasks |= LONG_CLICKABLE;
3819                    }
3820                    break;
3821                case com.android.internal.R.styleable.View_saveEnabled:
3822                    if (!a.getBoolean(attr, true)) {
3823                        viewFlagValues |= SAVE_DISABLED;
3824                        viewFlagMasks |= SAVE_DISABLED_MASK;
3825                    }
3826                    break;
3827                case com.android.internal.R.styleable.View_duplicateParentState:
3828                    if (a.getBoolean(attr, false)) {
3829                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3830                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3831                    }
3832                    break;
3833                case com.android.internal.R.styleable.View_visibility:
3834                    final int visibility = a.getInt(attr, 0);
3835                    if (visibility != 0) {
3836                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3837                        viewFlagMasks |= VISIBILITY_MASK;
3838                    }
3839                    break;
3840                case com.android.internal.R.styleable.View_layoutDirection:
3841                    // Clear any layout direction flags (included resolved bits) already set
3842                    mPrivateFlags2 &=
3843                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3844                    // Set the layout direction flags depending on the value of the attribute
3845                    final int layoutDirection = a.getInt(attr, -1);
3846                    final int value = (layoutDirection != -1) ?
3847                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3848                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3849                    break;
3850                case com.android.internal.R.styleable.View_drawingCacheQuality:
3851                    final int cacheQuality = a.getInt(attr, 0);
3852                    if (cacheQuality != 0) {
3853                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3854                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3855                    }
3856                    break;
3857                case com.android.internal.R.styleable.View_contentDescription:
3858                    setContentDescription(a.getString(attr));
3859                    break;
3860                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
3861                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
3862                    break;
3863                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
3864                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
3865                    break;
3866                case com.android.internal.R.styleable.View_labelFor:
3867                    setLabelFor(a.getResourceId(attr, NO_ID));
3868                    break;
3869                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3870                    if (!a.getBoolean(attr, true)) {
3871                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3872                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3873                    }
3874                    break;
3875                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3876                    if (!a.getBoolean(attr, true)) {
3877                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3878                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3879                    }
3880                    break;
3881                case R.styleable.View_scrollbars:
3882                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3883                    if (scrollbars != SCROLLBARS_NONE) {
3884                        viewFlagValues |= scrollbars;
3885                        viewFlagMasks |= SCROLLBARS_MASK;
3886                        initializeScrollbars = true;
3887                    }
3888                    break;
3889                //noinspection deprecation
3890                case R.styleable.View_fadingEdge:
3891                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3892                        // Ignore the attribute starting with ICS
3893                        break;
3894                    }
3895                    // With builds < ICS, fall through and apply fading edges
3896                case R.styleable.View_requiresFadingEdge:
3897                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3898                    if (fadingEdge != FADING_EDGE_NONE) {
3899                        viewFlagValues |= fadingEdge;
3900                        viewFlagMasks |= FADING_EDGE_MASK;
3901                        initializeFadingEdgeInternal(a);
3902                    }
3903                    break;
3904                case R.styleable.View_scrollbarStyle:
3905                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3906                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3907                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3908                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3909                    }
3910                    break;
3911                case R.styleable.View_isScrollContainer:
3912                    setScrollContainer = true;
3913                    if (a.getBoolean(attr, false)) {
3914                        setScrollContainer(true);
3915                    }
3916                    break;
3917                case com.android.internal.R.styleable.View_keepScreenOn:
3918                    if (a.getBoolean(attr, false)) {
3919                        viewFlagValues |= KEEP_SCREEN_ON;
3920                        viewFlagMasks |= KEEP_SCREEN_ON;
3921                    }
3922                    break;
3923                case R.styleable.View_filterTouchesWhenObscured:
3924                    if (a.getBoolean(attr, false)) {
3925                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3926                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3927                    }
3928                    break;
3929                case R.styleable.View_nextFocusLeft:
3930                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3931                    break;
3932                case R.styleable.View_nextFocusRight:
3933                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3934                    break;
3935                case R.styleable.View_nextFocusUp:
3936                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3937                    break;
3938                case R.styleable.View_nextFocusDown:
3939                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3940                    break;
3941                case R.styleable.View_nextFocusForward:
3942                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3943                    break;
3944                case R.styleable.View_minWidth:
3945                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3946                    break;
3947                case R.styleable.View_minHeight:
3948                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3949                    break;
3950                case R.styleable.View_onClick:
3951                    if (context.isRestricted()) {
3952                        throw new IllegalStateException("The android:onClick attribute cannot "
3953                                + "be used within a restricted context");
3954                    }
3955
3956                    final String handlerName = a.getString(attr);
3957                    if (handlerName != null) {
3958                        setOnClickListener(new OnClickListener() {
3959                            private Method mHandler;
3960
3961                            public void onClick(View v) {
3962                                if (mHandler == null) {
3963                                    try {
3964                                        mHandler = getContext().getClass().getMethod(handlerName,
3965                                                View.class);
3966                                    } catch (NoSuchMethodException e) {
3967                                        int id = getId();
3968                                        String idText = id == NO_ID ? "" : " with id '"
3969                                                + getContext().getResources().getResourceEntryName(
3970                                                    id) + "'";
3971                                        throw new IllegalStateException("Could not find a method " +
3972                                                handlerName + "(View) in the activity "
3973                                                + getContext().getClass() + " for onClick handler"
3974                                                + " on view " + View.this.getClass() + idText, e);
3975                                    }
3976                                }
3977
3978                                try {
3979                                    mHandler.invoke(getContext(), View.this);
3980                                } catch (IllegalAccessException e) {
3981                                    throw new IllegalStateException("Could not execute non "
3982                                            + "public method of the activity", e);
3983                                } catch (InvocationTargetException e) {
3984                                    throw new IllegalStateException("Could not execute "
3985                                            + "method of the activity", e);
3986                                }
3987                            }
3988                        });
3989                    }
3990                    break;
3991                case R.styleable.View_overScrollMode:
3992                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3993                    break;
3994                case R.styleable.View_verticalScrollbarPosition:
3995                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3996                    break;
3997                case R.styleable.View_layerType:
3998                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3999                    break;
4000                case R.styleable.View_textDirection:
4001                    // Clear any text direction flag already set
4002                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4003                    // Set the text direction flags depending on the value of the attribute
4004                    final int textDirection = a.getInt(attr, -1);
4005                    if (textDirection != -1) {
4006                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4007                    }
4008                    break;
4009                case R.styleable.View_textAlignment:
4010                    // Clear any text alignment flag already set
4011                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4012                    // Set the text alignment flag depending on the value of the attribute
4013                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4014                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4015                    break;
4016                case R.styleable.View_importantForAccessibility:
4017                    setImportantForAccessibility(a.getInt(attr,
4018                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4019                    break;
4020                case R.styleable.View_accessibilityLiveRegion:
4021                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4022                    break;
4023                case R.styleable.View_transitionName:
4024                    setTransitionName(a.getString(attr));
4025                    break;
4026                case R.styleable.View_nestedScrollingEnabled:
4027                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4028                    break;
4029                case R.styleable.View_stateListAnimator:
4030                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4031                            a.getResourceId(attr, 0)));
4032                    break;
4033                case R.styleable.View_backgroundTint:
4034                    // This will get applied later during setBackground().
4035                    if (mBackgroundTint == null) {
4036                        mBackgroundTint = new TintInfo();
4037                    }
4038                    mBackgroundTint.mTintList = a.getColorStateList(
4039                            R.styleable.View_backgroundTint);
4040                    mBackgroundTint.mHasTintList = true;
4041                    break;
4042                case R.styleable.View_backgroundTintMode:
4043                    // This will get applied later during setBackground().
4044                    if (mBackgroundTint == null) {
4045                        mBackgroundTint = new TintInfo();
4046                    }
4047                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4048                            R.styleable.View_backgroundTintMode, -1), null);
4049                    mBackgroundTint.mHasTintMode = true;
4050                    break;
4051                case R.styleable.View_outlineProvider:
4052                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4053                            PROVIDER_BACKGROUND));
4054                    break;
4055            }
4056        }
4057
4058        setOverScrollMode(overScrollMode);
4059
4060        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4061        // the resolved layout direction). Those cached values will be used later during padding
4062        // resolution.
4063        mUserPaddingStart = startPadding;
4064        mUserPaddingEnd = endPadding;
4065
4066        if (background != null) {
4067            setBackground(background);
4068        }
4069
4070        // setBackground above will record that padding is currently provided by the background.
4071        // If we have padding specified via xml, record that here instead and use it.
4072        mLeftPaddingDefined = leftPaddingDefined;
4073        mRightPaddingDefined = rightPaddingDefined;
4074
4075        if (padding >= 0) {
4076            leftPadding = padding;
4077            topPadding = padding;
4078            rightPadding = padding;
4079            bottomPadding = padding;
4080            mUserPaddingLeftInitial = padding;
4081            mUserPaddingRightInitial = padding;
4082        }
4083
4084        if (isRtlCompatibilityMode()) {
4085            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4086            // left / right padding are used if defined (meaning here nothing to do). If they are not
4087            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4088            // start / end and resolve them as left / right (layout direction is not taken into account).
4089            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4090            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4091            // defined.
4092            if (!mLeftPaddingDefined && startPaddingDefined) {
4093                leftPadding = startPadding;
4094            }
4095            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4096            if (!mRightPaddingDefined && endPaddingDefined) {
4097                rightPadding = endPadding;
4098            }
4099            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4100        } else {
4101            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4102            // values defined. Otherwise, left /right values are used.
4103            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4104            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4105            // defined.
4106            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4107
4108            if (mLeftPaddingDefined && !hasRelativePadding) {
4109                mUserPaddingLeftInitial = leftPadding;
4110            }
4111            if (mRightPaddingDefined && !hasRelativePadding) {
4112                mUserPaddingRightInitial = rightPadding;
4113            }
4114        }
4115
4116        internalSetPadding(
4117                mUserPaddingLeftInitial,
4118                topPadding >= 0 ? topPadding : mPaddingTop,
4119                mUserPaddingRightInitial,
4120                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4121
4122        if (viewFlagMasks != 0) {
4123            setFlags(viewFlagValues, viewFlagMasks);
4124        }
4125
4126        if (initializeScrollbars) {
4127            initializeScrollbarsInternal(a);
4128        }
4129
4130        a.recycle();
4131
4132        // Needs to be called after mViewFlags is set
4133        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4134            recomputePadding();
4135        }
4136
4137        if (x != 0 || y != 0) {
4138            scrollTo(x, y);
4139        }
4140
4141        if (transformSet) {
4142            setTranslationX(tx);
4143            setTranslationY(ty);
4144            setTranslationZ(tz);
4145            setElevation(elevation);
4146            setRotation(rotation);
4147            setRotationX(rotationX);
4148            setRotationY(rotationY);
4149            setScaleX(sx);
4150            setScaleY(sy);
4151        }
4152
4153        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4154            setScrollContainer(true);
4155        }
4156
4157        computeOpaqueFlags();
4158    }
4159
4160    /**
4161     * Non-public constructor for use in testing
4162     */
4163    View() {
4164        mResources = null;
4165        mRenderNode = RenderNode.create(getClass().getName(), this);
4166    }
4167
4168    private static SparseArray<String> getAttributeMap() {
4169        if (mAttributeMap == null) {
4170            mAttributeMap = new SparseArray<String>();
4171        }
4172        return mAttributeMap;
4173    }
4174
4175    private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4176        int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4177        mAttributes = new String[length];
4178
4179        int i = 0;
4180        if (attrs != null) {
4181            for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4182                mAttributes[i] = attrs.getAttributeName(i);
4183                mAttributes[i + 1] = attrs.getAttributeValue(i);
4184            }
4185
4186        }
4187
4188        SparseArray<String> attributeMap = getAttributeMap();
4189        for (int j = 0; j < a.length(); ++j) {
4190            if (a.hasValue(j)) {
4191                try {
4192                    int resourceId = a.getResourceId(j, 0);
4193                    if (resourceId == 0) {
4194                        continue;
4195                    }
4196
4197                    String resourceName = attributeMap.get(resourceId);
4198                    if (resourceName == null) {
4199                        resourceName = a.getResources().getResourceName(resourceId);
4200                        attributeMap.put(resourceId, resourceName);
4201                    }
4202
4203                    mAttributes[i] = resourceName;
4204                    mAttributes[i + 1] = a.getText(j).toString();
4205                    i += 2;
4206                } catch (Resources.NotFoundException e) {
4207                    // if we can't get the resource name, we just ignore it
4208                }
4209            }
4210        }
4211    }
4212
4213    public String toString() {
4214        StringBuilder out = new StringBuilder(128);
4215        out.append(getClass().getName());
4216        out.append('{');
4217        out.append(Integer.toHexString(System.identityHashCode(this)));
4218        out.append(' ');
4219        switch (mViewFlags&VISIBILITY_MASK) {
4220            case VISIBLE: out.append('V'); break;
4221            case INVISIBLE: out.append('I'); break;
4222            case GONE: out.append('G'); break;
4223            default: out.append('.'); break;
4224        }
4225        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4226        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4227        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4228        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4229        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4230        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4231        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4232        out.append(' ');
4233        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4234        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4235        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4236        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4237            out.append('p');
4238        } else {
4239            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4240        }
4241        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4242        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4243        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4244        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4245        out.append(' ');
4246        out.append(mLeft);
4247        out.append(',');
4248        out.append(mTop);
4249        out.append('-');
4250        out.append(mRight);
4251        out.append(',');
4252        out.append(mBottom);
4253        final int id = getId();
4254        if (id != NO_ID) {
4255            out.append(" #");
4256            out.append(Integer.toHexString(id));
4257            final Resources r = mResources;
4258            if (Resources.resourceHasPackage(id) && r != null) {
4259                try {
4260                    String pkgname;
4261                    switch (id&0xff000000) {
4262                        case 0x7f000000:
4263                            pkgname="app";
4264                            break;
4265                        case 0x01000000:
4266                            pkgname="android";
4267                            break;
4268                        default:
4269                            pkgname = r.getResourcePackageName(id);
4270                            break;
4271                    }
4272                    String typename = r.getResourceTypeName(id);
4273                    String entryname = r.getResourceEntryName(id);
4274                    out.append(" ");
4275                    out.append(pkgname);
4276                    out.append(":");
4277                    out.append(typename);
4278                    out.append("/");
4279                    out.append(entryname);
4280                } catch (Resources.NotFoundException e) {
4281                }
4282            }
4283        }
4284        out.append("}");
4285        return out.toString();
4286    }
4287
4288    /**
4289     * <p>
4290     * Initializes the fading edges from a given set of styled attributes. This
4291     * method should be called by subclasses that need fading edges and when an
4292     * instance of these subclasses is created programmatically rather than
4293     * being inflated from XML. This method is automatically called when the XML
4294     * is inflated.
4295     * </p>
4296     *
4297     * @param a the styled attributes set to initialize the fading edges from
4298     *
4299     * @removed
4300     */
4301    protected void initializeFadingEdge(TypedArray a) {
4302        // This method probably shouldn't have been included in the SDK to begin with.
4303        // It relies on 'a' having been initialized using an attribute filter array that is
4304        // not publicly available to the SDK. The old method has been renamed
4305        // to initializeFadingEdgeInternal and hidden for framework use only;
4306        // this one initializes using defaults to make it safe to call for apps.
4307
4308        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4309
4310        initializeFadingEdgeInternal(arr);
4311
4312        arr.recycle();
4313    }
4314
4315    /**
4316     * <p>
4317     * Initializes the fading edges from a given set of styled attributes. This
4318     * method should be called by subclasses that need fading edges and when an
4319     * instance of these subclasses is created programmatically rather than
4320     * being inflated from XML. This method is automatically called when the XML
4321     * is inflated.
4322     * </p>
4323     *
4324     * @param a the styled attributes set to initialize the fading edges from
4325     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4326     */
4327    protected void initializeFadingEdgeInternal(TypedArray a) {
4328        initScrollCache();
4329
4330        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4331                R.styleable.View_fadingEdgeLength,
4332                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4333    }
4334
4335    /**
4336     * Returns the size of the vertical faded edges used to indicate that more
4337     * content in this view is visible.
4338     *
4339     * @return The size in pixels of the vertical faded edge or 0 if vertical
4340     *         faded edges are not enabled for this view.
4341     * @attr ref android.R.styleable#View_fadingEdgeLength
4342     */
4343    public int getVerticalFadingEdgeLength() {
4344        if (isVerticalFadingEdgeEnabled()) {
4345            ScrollabilityCache cache = mScrollCache;
4346            if (cache != null) {
4347                return cache.fadingEdgeLength;
4348            }
4349        }
4350        return 0;
4351    }
4352
4353    /**
4354     * Set the size of the faded edge used to indicate that more content in this
4355     * view is available.  Will not change whether the fading edge is enabled; use
4356     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4357     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4358     * for the vertical or horizontal fading edges.
4359     *
4360     * @param length The size in pixels of the faded edge used to indicate that more
4361     *        content in this view is visible.
4362     */
4363    public void setFadingEdgeLength(int length) {
4364        initScrollCache();
4365        mScrollCache.fadingEdgeLength = length;
4366    }
4367
4368    /**
4369     * Returns the size of the horizontal faded edges used to indicate that more
4370     * content in this view is visible.
4371     *
4372     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4373     *         faded edges are not enabled for this view.
4374     * @attr ref android.R.styleable#View_fadingEdgeLength
4375     */
4376    public int getHorizontalFadingEdgeLength() {
4377        if (isHorizontalFadingEdgeEnabled()) {
4378            ScrollabilityCache cache = mScrollCache;
4379            if (cache != null) {
4380                return cache.fadingEdgeLength;
4381            }
4382        }
4383        return 0;
4384    }
4385
4386    /**
4387     * Returns the width of the vertical scrollbar.
4388     *
4389     * @return The width in pixels of the vertical scrollbar or 0 if there
4390     *         is no vertical scrollbar.
4391     */
4392    public int getVerticalScrollbarWidth() {
4393        ScrollabilityCache cache = mScrollCache;
4394        if (cache != null) {
4395            ScrollBarDrawable scrollBar = cache.scrollBar;
4396            if (scrollBar != null) {
4397                int size = scrollBar.getSize(true);
4398                if (size <= 0) {
4399                    size = cache.scrollBarSize;
4400                }
4401                return size;
4402            }
4403            return 0;
4404        }
4405        return 0;
4406    }
4407
4408    /**
4409     * Returns the height of the horizontal scrollbar.
4410     *
4411     * @return The height in pixels of the horizontal scrollbar or 0 if
4412     *         there is no horizontal scrollbar.
4413     */
4414    protected int getHorizontalScrollbarHeight() {
4415        ScrollabilityCache cache = mScrollCache;
4416        if (cache != null) {
4417            ScrollBarDrawable scrollBar = cache.scrollBar;
4418            if (scrollBar != null) {
4419                int size = scrollBar.getSize(false);
4420                if (size <= 0) {
4421                    size = cache.scrollBarSize;
4422                }
4423                return size;
4424            }
4425            return 0;
4426        }
4427        return 0;
4428    }
4429
4430    /**
4431     * <p>
4432     * Initializes the scrollbars from a given set of styled attributes. This
4433     * method should be called by subclasses that need scrollbars and when an
4434     * instance of these subclasses is created programmatically rather than
4435     * being inflated from XML. This method is automatically called when the XML
4436     * is inflated.
4437     * </p>
4438     *
4439     * @param a the styled attributes set to initialize the scrollbars from
4440     *
4441     * @removed
4442     */
4443    protected void initializeScrollbars(TypedArray a) {
4444        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4445        // using the View filter array which is not available to the SDK. As such, internal
4446        // framework usage now uses initializeScrollbarsInternal and we grab a default
4447        // TypedArray with the right filter instead here.
4448        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4449
4450        initializeScrollbarsInternal(arr);
4451
4452        // We ignored the method parameter. Recycle the one we actually did use.
4453        arr.recycle();
4454    }
4455
4456    /**
4457     * <p>
4458     * Initializes the scrollbars from a given set of styled attributes. This
4459     * method should be called by subclasses that need scrollbars and when an
4460     * instance of these subclasses is created programmatically rather than
4461     * being inflated from XML. This method is automatically called when the XML
4462     * is inflated.
4463     * </p>
4464     *
4465     * @param a the styled attributes set to initialize the scrollbars from
4466     * @hide
4467     */
4468    protected void initializeScrollbarsInternal(TypedArray a) {
4469        initScrollCache();
4470
4471        final ScrollabilityCache scrollabilityCache = mScrollCache;
4472
4473        if (scrollabilityCache.scrollBar == null) {
4474            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4475            scrollabilityCache.scrollBar.setCallback(this);
4476            scrollabilityCache.scrollBar.setState(getDrawableState());
4477        }
4478
4479        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4480
4481        if (!fadeScrollbars) {
4482            scrollabilityCache.state = ScrollabilityCache.ON;
4483        }
4484        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4485
4486
4487        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4488                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4489                        .getScrollBarFadeDuration());
4490        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4491                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4492                ViewConfiguration.getScrollDefaultDelay());
4493
4494
4495        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4496                com.android.internal.R.styleable.View_scrollbarSize,
4497                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4498
4499        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4500        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4501
4502        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4503        if (thumb != null) {
4504            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4505        }
4506
4507        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4508                false);
4509        if (alwaysDraw) {
4510            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4511        }
4512
4513        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4514        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4515
4516        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4517        if (thumb != null) {
4518            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4519        }
4520
4521        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4522                false);
4523        if (alwaysDraw) {
4524            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4525        }
4526
4527        // Apply layout direction to the new Drawables if needed
4528        final int layoutDirection = getLayoutDirection();
4529        if (track != null) {
4530            track.setLayoutDirection(layoutDirection);
4531        }
4532        if (thumb != null) {
4533            thumb.setLayoutDirection(layoutDirection);
4534        }
4535
4536        // Re-apply user/background padding so that scrollbar(s) get added
4537        resolvePadding();
4538    }
4539
4540    /**
4541     * <p>
4542     * Initalizes the scrollability cache if necessary.
4543     * </p>
4544     */
4545    private void initScrollCache() {
4546        if (mScrollCache == null) {
4547            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4548        }
4549    }
4550
4551    private ScrollabilityCache getScrollCache() {
4552        initScrollCache();
4553        return mScrollCache;
4554    }
4555
4556    /**
4557     * Set the position of the vertical scroll bar. Should be one of
4558     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4559     * {@link #SCROLLBAR_POSITION_RIGHT}.
4560     *
4561     * @param position Where the vertical scroll bar should be positioned.
4562     */
4563    public void setVerticalScrollbarPosition(int position) {
4564        if (mVerticalScrollbarPosition != position) {
4565            mVerticalScrollbarPosition = position;
4566            computeOpaqueFlags();
4567            resolvePadding();
4568        }
4569    }
4570
4571    /**
4572     * @return The position where the vertical scroll bar will show, if applicable.
4573     * @see #setVerticalScrollbarPosition(int)
4574     */
4575    public int getVerticalScrollbarPosition() {
4576        return mVerticalScrollbarPosition;
4577    }
4578
4579    ListenerInfo getListenerInfo() {
4580        if (mListenerInfo != null) {
4581            return mListenerInfo;
4582        }
4583        mListenerInfo = new ListenerInfo();
4584        return mListenerInfo;
4585    }
4586
4587    /**
4588     * Register a callback to be invoked when the scroll X or Y positions of
4589     * this view change.
4590     * <p>
4591     * <b>Note:</b> Some views handle scrolling independently from View and may
4592     * have their own separate listeners for scroll-type events. For example,
4593     * {@link android.widget.ListView ListView} allows clients to register an
4594     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
4595     * to listen for changes in list scroll position.
4596     *
4597     * @param l The listener to notify when the scroll X or Y position changes.
4598     * @see android.view.View#getScrollX()
4599     * @see android.view.View#getScrollY()
4600     */
4601    public void setOnScrollChangeListener(OnScrollChangeListener l) {
4602        getListenerInfo().mOnScrollChangeListener = l;
4603    }
4604
4605    /**
4606     * Register a callback to be invoked when focus of this view changed.
4607     *
4608     * @param l The callback that will run.
4609     */
4610    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4611        getListenerInfo().mOnFocusChangeListener = l;
4612    }
4613
4614    /**
4615     * Add a listener that will be called when the bounds of the view change due to
4616     * layout processing.
4617     *
4618     * @param listener The listener that will be called when layout bounds change.
4619     */
4620    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4621        ListenerInfo li = getListenerInfo();
4622        if (li.mOnLayoutChangeListeners == null) {
4623            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4624        }
4625        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4626            li.mOnLayoutChangeListeners.add(listener);
4627        }
4628    }
4629
4630    /**
4631     * Remove a listener for layout changes.
4632     *
4633     * @param listener The listener for layout bounds change.
4634     */
4635    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4636        ListenerInfo li = mListenerInfo;
4637        if (li == null || li.mOnLayoutChangeListeners == null) {
4638            return;
4639        }
4640        li.mOnLayoutChangeListeners.remove(listener);
4641    }
4642
4643    /**
4644     * Add a listener for attach state changes.
4645     *
4646     * This listener will be called whenever this view is attached or detached
4647     * from a window. Remove the listener using
4648     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4649     *
4650     * @param listener Listener to attach
4651     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4652     */
4653    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4654        ListenerInfo li = getListenerInfo();
4655        if (li.mOnAttachStateChangeListeners == null) {
4656            li.mOnAttachStateChangeListeners
4657                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4658        }
4659        li.mOnAttachStateChangeListeners.add(listener);
4660    }
4661
4662    /**
4663     * Remove a listener for attach state changes. The listener will receive no further
4664     * notification of window attach/detach events.
4665     *
4666     * @param listener Listener to remove
4667     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4668     */
4669    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4670        ListenerInfo li = mListenerInfo;
4671        if (li == null || li.mOnAttachStateChangeListeners == null) {
4672            return;
4673        }
4674        li.mOnAttachStateChangeListeners.remove(listener);
4675    }
4676
4677    /**
4678     * Returns the focus-change callback registered for this view.
4679     *
4680     * @return The callback, or null if one is not registered.
4681     */
4682    public OnFocusChangeListener getOnFocusChangeListener() {
4683        ListenerInfo li = mListenerInfo;
4684        return li != null ? li.mOnFocusChangeListener : null;
4685    }
4686
4687    /**
4688     * Register a callback to be invoked when this view is clicked. If this view is not
4689     * clickable, it becomes clickable.
4690     *
4691     * @param l The callback that will run
4692     *
4693     * @see #setClickable(boolean)
4694     */
4695    public void setOnClickListener(@Nullable OnClickListener l) {
4696        if (!isClickable()) {
4697            setClickable(true);
4698        }
4699        getListenerInfo().mOnClickListener = l;
4700    }
4701
4702    /**
4703     * Return whether this view has an attached OnClickListener.  Returns
4704     * true if there is a listener, false if there is none.
4705     */
4706    public boolean hasOnClickListeners() {
4707        ListenerInfo li = mListenerInfo;
4708        return (li != null && li.mOnClickListener != null);
4709    }
4710
4711    /**
4712     * Register a callback to be invoked when this view is clicked and held. If this view is not
4713     * long clickable, it becomes long clickable.
4714     *
4715     * @param l The callback that will run
4716     *
4717     * @see #setLongClickable(boolean)
4718     */
4719    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
4720        if (!isLongClickable()) {
4721            setLongClickable(true);
4722        }
4723        getListenerInfo().mOnLongClickListener = l;
4724    }
4725
4726    /**
4727     * Register a callback to be invoked when the context menu for this view is
4728     * being built. If this view is not long clickable, it becomes long clickable.
4729     *
4730     * @param l The callback that will run
4731     *
4732     */
4733    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4734        if (!isLongClickable()) {
4735            setLongClickable(true);
4736        }
4737        getListenerInfo().mOnCreateContextMenuListener = l;
4738    }
4739
4740    /**
4741     * Call this view's OnClickListener, if it is defined.  Performs all normal
4742     * actions associated with clicking: reporting accessibility event, playing
4743     * a sound, etc.
4744     *
4745     * @return True there was an assigned OnClickListener that was called, false
4746     *         otherwise is returned.
4747     */
4748    public boolean performClick() {
4749        final boolean result;
4750        final ListenerInfo li = mListenerInfo;
4751        if (li != null && li.mOnClickListener != null) {
4752            playSoundEffect(SoundEffectConstants.CLICK);
4753            li.mOnClickListener.onClick(this);
4754            result = true;
4755        } else {
4756            result = false;
4757        }
4758
4759        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4760        return result;
4761    }
4762
4763    /**
4764     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4765     * this only calls the listener, and does not do any associated clicking
4766     * actions like reporting an accessibility event.
4767     *
4768     * @return True there was an assigned OnClickListener that was called, false
4769     *         otherwise is returned.
4770     */
4771    public boolean callOnClick() {
4772        ListenerInfo li = mListenerInfo;
4773        if (li != null && li.mOnClickListener != null) {
4774            li.mOnClickListener.onClick(this);
4775            return true;
4776        }
4777        return false;
4778    }
4779
4780    /**
4781     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4782     * OnLongClickListener did not consume the event.
4783     *
4784     * @return True if one of the above receivers consumed the event, false otherwise.
4785     */
4786    public boolean performLongClick() {
4787        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4788
4789        boolean handled = false;
4790        ListenerInfo li = mListenerInfo;
4791        if (li != null && li.mOnLongClickListener != null) {
4792            handled = li.mOnLongClickListener.onLongClick(View.this);
4793        }
4794        if (!handled) {
4795            handled = showContextMenu();
4796        }
4797        if (handled) {
4798            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4799        }
4800        return handled;
4801    }
4802
4803    /**
4804     * Performs button-related actions during a touch down event.
4805     *
4806     * @param event The event.
4807     * @return True if the down was consumed.
4808     *
4809     * @hide
4810     */
4811    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4812        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4813            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4814                return true;
4815            }
4816        }
4817        return false;
4818    }
4819
4820    /**
4821     * Bring up the context menu for this view.
4822     *
4823     * @return Whether a context menu was displayed.
4824     */
4825    public boolean showContextMenu() {
4826        return getParent().showContextMenuForChild(this);
4827    }
4828
4829    /**
4830     * Bring up the context menu for this view, referring to the item under the specified point.
4831     *
4832     * @param x The referenced x coordinate.
4833     * @param y The referenced y coordinate.
4834     * @param metaState The keyboard modifiers that were pressed.
4835     * @return Whether a context menu was displayed.
4836     *
4837     * @hide
4838     */
4839    public boolean showContextMenu(float x, float y, int metaState) {
4840        return showContextMenu();
4841    }
4842
4843    /**
4844     * Start an action mode.
4845     *
4846     * @param callback Callback that will control the lifecycle of the action mode
4847     * @return The new action mode if it is started, null otherwise
4848     *
4849     * @see ActionMode
4850     */
4851    public ActionMode startActionMode(ActionMode.Callback callback) {
4852        ViewParent parent = getParent();
4853        if (parent == null) return null;
4854        return parent.startActionModeForChild(this, callback);
4855    }
4856
4857    /**
4858     * Register a callback to be invoked when a hardware key is pressed in this view.
4859     * Key presses in software input methods will generally not trigger the methods of
4860     * this listener.
4861     * @param l the key listener to attach to this view
4862     */
4863    public void setOnKeyListener(OnKeyListener l) {
4864        getListenerInfo().mOnKeyListener = l;
4865    }
4866
4867    /**
4868     * Register a callback to be invoked when a touch event is sent to this view.
4869     * @param l the touch listener to attach to this view
4870     */
4871    public void setOnTouchListener(OnTouchListener l) {
4872        getListenerInfo().mOnTouchListener = l;
4873    }
4874
4875    /**
4876     * Register a callback to be invoked when a generic motion event is sent to this view.
4877     * @param l the generic motion listener to attach to this view
4878     */
4879    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4880        getListenerInfo().mOnGenericMotionListener = l;
4881    }
4882
4883    /**
4884     * Register a callback to be invoked when a hover event is sent to this view.
4885     * @param l the hover listener to attach to this view
4886     */
4887    public void setOnHoverListener(OnHoverListener l) {
4888        getListenerInfo().mOnHoverListener = l;
4889    }
4890
4891    /**
4892     * Register a drag event listener callback object for this View. The parameter is
4893     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4894     * View, the system calls the
4895     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4896     * @param l An implementation of {@link android.view.View.OnDragListener}.
4897     */
4898    public void setOnDragListener(OnDragListener l) {
4899        getListenerInfo().mOnDragListener = l;
4900    }
4901
4902    /**
4903     * Give this view focus. This will cause
4904     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4905     *
4906     * Note: this does not check whether this {@link View} should get focus, it just
4907     * gives it focus no matter what.  It should only be called internally by framework
4908     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4909     *
4910     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4911     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4912     *        focus moved when requestFocus() is called. It may not always
4913     *        apply, in which case use the default View.FOCUS_DOWN.
4914     * @param previouslyFocusedRect The rectangle of the view that had focus
4915     *        prior in this View's coordinate system.
4916     */
4917    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4918        if (DBG) {
4919            System.out.println(this + " requestFocus()");
4920        }
4921
4922        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4923            mPrivateFlags |= PFLAG_FOCUSED;
4924
4925            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4926
4927            if (mParent != null) {
4928                mParent.requestChildFocus(this, this);
4929            }
4930
4931            if (mAttachInfo != null) {
4932                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4933            }
4934
4935            onFocusChanged(true, direction, previouslyFocusedRect);
4936            refreshDrawableState();
4937        }
4938    }
4939
4940    /**
4941     * Populates <code>outRect</code> with the hotspot bounds. By default,
4942     * the hotspot bounds are identical to the screen bounds.
4943     *
4944     * @param outRect rect to populate with hotspot bounds
4945     * @hide Only for internal use by views and widgets.
4946     */
4947    public void getHotspotBounds(Rect outRect) {
4948        final Drawable background = getBackground();
4949        if (background != null) {
4950            background.getHotspotBounds(outRect);
4951        } else {
4952            getBoundsOnScreen(outRect);
4953        }
4954    }
4955
4956    /**
4957     * Request that a rectangle of this view be visible on the screen,
4958     * scrolling if necessary just enough.
4959     *
4960     * <p>A View should call this if it maintains some notion of which part
4961     * of its content is interesting.  For example, a text editing view
4962     * should call this when its cursor moves.
4963     *
4964     * @param rectangle The rectangle.
4965     * @return Whether any parent scrolled.
4966     */
4967    public boolean requestRectangleOnScreen(Rect rectangle) {
4968        return requestRectangleOnScreen(rectangle, false);
4969    }
4970
4971    /**
4972     * Request that a rectangle of this view be visible on the screen,
4973     * scrolling if necessary just enough.
4974     *
4975     * <p>A View should call this if it maintains some notion of which part
4976     * of its content is interesting.  For example, a text editing view
4977     * should call this when its cursor moves.
4978     *
4979     * <p>When <code>immediate</code> is set to true, scrolling will not be
4980     * animated.
4981     *
4982     * @param rectangle The rectangle.
4983     * @param immediate True to forbid animated scrolling, false otherwise
4984     * @return Whether any parent scrolled.
4985     */
4986    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4987        if (mParent == null) {
4988            return false;
4989        }
4990
4991        View child = this;
4992
4993        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
4994        position.set(rectangle);
4995
4996        ViewParent parent = mParent;
4997        boolean scrolled = false;
4998        while (parent != null) {
4999            rectangle.set((int) position.left, (int) position.top,
5000                    (int) position.right, (int) position.bottom);
5001
5002            scrolled |= parent.requestChildRectangleOnScreen(child,
5003                    rectangle, immediate);
5004
5005            if (!child.hasIdentityMatrix()) {
5006                child.getMatrix().mapRect(position);
5007            }
5008
5009            position.offset(child.mLeft, child.mTop);
5010
5011            if (!(parent instanceof View)) {
5012                break;
5013            }
5014
5015            View parentView = (View) parent;
5016
5017            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5018
5019            child = parentView;
5020            parent = child.getParent();
5021        }
5022
5023        return scrolled;
5024    }
5025
5026    /**
5027     * Called when this view wants to give up focus. If focus is cleared
5028     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5029     * <p>
5030     * <strong>Note:</strong> When a View clears focus the framework is trying
5031     * to give focus to the first focusable View from the top. Hence, if this
5032     * View is the first from the top that can take focus, then all callbacks
5033     * related to clearing focus will be invoked after which the framework will
5034     * give focus to this view.
5035     * </p>
5036     */
5037    public void clearFocus() {
5038        if (DBG) {
5039            System.out.println(this + " clearFocus()");
5040        }
5041
5042        clearFocusInternal(null, true, true);
5043    }
5044
5045    /**
5046     * Clears focus from the view, optionally propagating the change up through
5047     * the parent hierarchy and requesting that the root view place new focus.
5048     *
5049     * @param propagate whether to propagate the change up through the parent
5050     *            hierarchy
5051     * @param refocus when propagate is true, specifies whether to request the
5052     *            root view place new focus
5053     */
5054    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5055        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5056            mPrivateFlags &= ~PFLAG_FOCUSED;
5057
5058            if (propagate && mParent != null) {
5059                mParent.clearChildFocus(this);
5060            }
5061
5062            onFocusChanged(false, 0, null);
5063            refreshDrawableState();
5064
5065            if (propagate && (!refocus || !rootViewRequestFocus())) {
5066                notifyGlobalFocusCleared(this);
5067            }
5068        }
5069    }
5070
5071    void notifyGlobalFocusCleared(View oldFocus) {
5072        if (oldFocus != null && mAttachInfo != null) {
5073            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5074        }
5075    }
5076
5077    boolean rootViewRequestFocus() {
5078        final View root = getRootView();
5079        return root != null && root.requestFocus();
5080    }
5081
5082    /**
5083     * Called internally by the view system when a new view is getting focus.
5084     * This is what clears the old focus.
5085     * <p>
5086     * <b>NOTE:</b> The parent view's focused child must be updated manually
5087     * after calling this method. Otherwise, the view hierarchy may be left in
5088     * an inconstent state.
5089     */
5090    void unFocus(View focused) {
5091        if (DBG) {
5092            System.out.println(this + " unFocus()");
5093        }
5094
5095        clearFocusInternal(focused, false, false);
5096    }
5097
5098    /**
5099     * Returns true if this view has focus itself, or is the ancestor of the
5100     * view that has focus.
5101     *
5102     * @return True if this view has or contains focus, false otherwise.
5103     */
5104    @ViewDebug.ExportedProperty(category = "focus")
5105    public boolean hasFocus() {
5106        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5107    }
5108
5109    /**
5110     * Returns true if this view is focusable or if it contains a reachable View
5111     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5112     * is a View whose parents do not block descendants focus.
5113     *
5114     * Only {@link #VISIBLE} views are considered focusable.
5115     *
5116     * @return True if the view is focusable or if the view contains a focusable
5117     *         View, false otherwise.
5118     *
5119     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5120     * @see ViewGroup#getTouchscreenBlocksFocus()
5121     */
5122    public boolean hasFocusable() {
5123        if (!isFocusableInTouchMode()) {
5124            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5125                final ViewGroup g = (ViewGroup) p;
5126                if (g.shouldBlockFocusForTouchscreen()) {
5127                    return false;
5128                }
5129            }
5130        }
5131        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5132    }
5133
5134    /**
5135     * Called by the view system when the focus state of this view changes.
5136     * When the focus change event is caused by directional navigation, direction
5137     * and previouslyFocusedRect provide insight into where the focus is coming from.
5138     * When overriding, be sure to call up through to the super class so that
5139     * the standard focus handling will occur.
5140     *
5141     * @param gainFocus True if the View has focus; false otherwise.
5142     * @param direction The direction focus has moved when requestFocus()
5143     *                  is called to give this view focus. Values are
5144     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5145     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5146     *                  It may not always apply, in which case use the default.
5147     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5148     *        system, of the previously focused view.  If applicable, this will be
5149     *        passed in as finer grained information about where the focus is coming
5150     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5151     */
5152    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5153            @Nullable Rect previouslyFocusedRect) {
5154        if (gainFocus) {
5155            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5156        } else {
5157            notifyViewAccessibilityStateChangedIfNeeded(
5158                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5159        }
5160
5161        InputMethodManager imm = InputMethodManager.peekInstance();
5162        if (!gainFocus) {
5163            if (isPressed()) {
5164                setPressed(false);
5165            }
5166            if (imm != null && mAttachInfo != null
5167                    && mAttachInfo.mHasWindowFocus) {
5168                imm.focusOut(this);
5169            }
5170            onFocusLost();
5171        } else if (imm != null && mAttachInfo != null
5172                && mAttachInfo.mHasWindowFocus) {
5173            imm.focusIn(this);
5174        }
5175
5176        invalidate(true);
5177        ListenerInfo li = mListenerInfo;
5178        if (li != null && li.mOnFocusChangeListener != null) {
5179            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5180        }
5181
5182        if (mAttachInfo != null) {
5183            mAttachInfo.mKeyDispatchState.reset(this);
5184        }
5185    }
5186
5187    /**
5188     * Sends an accessibility event of the given type. If accessibility is
5189     * not enabled this method has no effect. The default implementation calls
5190     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5191     * to populate information about the event source (this View), then calls
5192     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5193     * populate the text content of the event source including its descendants,
5194     * and last calls
5195     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5196     * on its parent to request sending of the event to interested parties.
5197     * <p>
5198     * If an {@link AccessibilityDelegate} has been specified via calling
5199     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5200     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5201     * responsible for handling this call.
5202     * </p>
5203     *
5204     * @param eventType The type of the event to send, as defined by several types from
5205     * {@link android.view.accessibility.AccessibilityEvent}, such as
5206     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5207     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5208     *
5209     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5210     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5211     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5212     * @see AccessibilityDelegate
5213     */
5214    public void sendAccessibilityEvent(int eventType) {
5215        if (mAccessibilityDelegate != null) {
5216            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5217        } else {
5218            sendAccessibilityEventInternal(eventType);
5219        }
5220    }
5221
5222    /**
5223     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5224     * {@link AccessibilityEvent} to make an announcement which is related to some
5225     * sort of a context change for which none of the events representing UI transitions
5226     * is a good fit. For example, announcing a new page in a book. If accessibility
5227     * is not enabled this method does nothing.
5228     *
5229     * @param text The announcement text.
5230     */
5231    public void announceForAccessibility(CharSequence text) {
5232        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5233            AccessibilityEvent event = AccessibilityEvent.obtain(
5234                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5235            onInitializeAccessibilityEvent(event);
5236            event.getText().add(text);
5237            event.setContentDescription(null);
5238            mParent.requestSendAccessibilityEvent(this, event);
5239        }
5240    }
5241
5242    /**
5243     * @see #sendAccessibilityEvent(int)
5244     *
5245     * Note: Called from the default {@link AccessibilityDelegate}.
5246     *
5247     * @hide
5248     */
5249    public void sendAccessibilityEventInternal(int eventType) {
5250        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5251            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5252        }
5253    }
5254
5255    /**
5256     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5257     * takes as an argument an empty {@link AccessibilityEvent} and does not
5258     * perform a check whether accessibility is enabled.
5259     * <p>
5260     * If an {@link AccessibilityDelegate} has been specified via calling
5261     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5262     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5263     * is responsible for handling this call.
5264     * </p>
5265     *
5266     * @param event The event to send.
5267     *
5268     * @see #sendAccessibilityEvent(int)
5269     */
5270    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5271        if (mAccessibilityDelegate != null) {
5272            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5273        } else {
5274            sendAccessibilityEventUncheckedInternal(event);
5275        }
5276    }
5277
5278    /**
5279     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5280     *
5281     * Note: Called from the default {@link AccessibilityDelegate}.
5282     *
5283     * @hide
5284     */
5285    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5286        if (!isShown()) {
5287            return;
5288        }
5289        onInitializeAccessibilityEvent(event);
5290        // Only a subset of accessibility events populates text content.
5291        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5292            dispatchPopulateAccessibilityEvent(event);
5293        }
5294        // In the beginning we called #isShown(), so we know that getParent() is not null.
5295        getParent().requestSendAccessibilityEvent(this, event);
5296    }
5297
5298    /**
5299     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5300     * to its children for adding their text content to the event. Note that the
5301     * event text is populated in a separate dispatch path since we add to the
5302     * event not only the text of the source but also the text of all its descendants.
5303     * A typical implementation will call
5304     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5305     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5306     * on each child. Override this method if custom population of the event text
5307     * content is required.
5308     * <p>
5309     * If an {@link AccessibilityDelegate} has been specified via calling
5310     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5311     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5312     * is responsible for handling this call.
5313     * </p>
5314     * <p>
5315     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5316     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5317     * </p>
5318     *
5319     * @param event The event.
5320     *
5321     * @return True if the event population was completed.
5322     */
5323    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5324        if (mAccessibilityDelegate != null) {
5325            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5326        } else {
5327            return dispatchPopulateAccessibilityEventInternal(event);
5328        }
5329    }
5330
5331    /**
5332     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5333     *
5334     * Note: Called from the default {@link AccessibilityDelegate}.
5335     *
5336     * @hide
5337     */
5338    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5339        onPopulateAccessibilityEvent(event);
5340        return false;
5341    }
5342
5343    /**
5344     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5345     * giving a chance to this View to populate the accessibility event with its
5346     * text content. While this method is free to modify event
5347     * attributes other than text content, doing so should normally be performed in
5348     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5349     * <p>
5350     * Example: Adding formatted date string to an accessibility event in addition
5351     *          to the text added by the super implementation:
5352     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5353     *     super.onPopulateAccessibilityEvent(event);
5354     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5355     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5356     *         mCurrentDate.getTimeInMillis(), flags);
5357     *     event.getText().add(selectedDateUtterance);
5358     * }</pre>
5359     * <p>
5360     * If an {@link AccessibilityDelegate} has been specified via calling
5361     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5362     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5363     * is responsible for handling this call.
5364     * </p>
5365     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5366     * information to the event, in case the default implementation has basic information to add.
5367     * </p>
5368     *
5369     * @param event The accessibility event which to populate.
5370     *
5371     * @see #sendAccessibilityEvent(int)
5372     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5373     */
5374    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5375        if (mAccessibilityDelegate != null) {
5376            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5377        } else {
5378            onPopulateAccessibilityEventInternal(event);
5379        }
5380    }
5381
5382    /**
5383     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5384     *
5385     * Note: Called from the default {@link AccessibilityDelegate}.
5386     *
5387     * @hide
5388     */
5389    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5390    }
5391
5392    /**
5393     * Initializes an {@link AccessibilityEvent} with information about
5394     * this View which is the event source. In other words, the source of
5395     * an accessibility event is the view whose state change triggered firing
5396     * the event.
5397     * <p>
5398     * Example: Setting the password property of an event in addition
5399     *          to properties set by the super implementation:
5400     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5401     *     super.onInitializeAccessibilityEvent(event);
5402     *     event.setPassword(true);
5403     * }</pre>
5404     * <p>
5405     * If an {@link AccessibilityDelegate} has been specified via calling
5406     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5407     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5408     * is responsible for handling this call.
5409     * </p>
5410     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5411     * information to the event, in case the default implementation has basic information to add.
5412     * </p>
5413     * @param event The event to initialize.
5414     *
5415     * @see #sendAccessibilityEvent(int)
5416     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5417     */
5418    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5419        if (mAccessibilityDelegate != null) {
5420            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5421        } else {
5422            onInitializeAccessibilityEventInternal(event);
5423        }
5424    }
5425
5426    /**
5427     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5428     *
5429     * Note: Called from the default {@link AccessibilityDelegate}.
5430     *
5431     * @hide
5432     */
5433    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5434        event.setSource(this);
5435        event.setClassName(getAccessibilityClassName());
5436        event.setPackageName(getContext().getPackageName());
5437        event.setEnabled(isEnabled());
5438        event.setContentDescription(mContentDescription);
5439
5440        switch (event.getEventType()) {
5441            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5442                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5443                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5444                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5445                event.setItemCount(focusablesTempList.size());
5446                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5447                if (mAttachInfo != null) {
5448                    focusablesTempList.clear();
5449                }
5450            } break;
5451            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5452                CharSequence text = getIterableTextForAccessibility();
5453                if (text != null && text.length() > 0) {
5454                    event.setFromIndex(getAccessibilitySelectionStart());
5455                    event.setToIndex(getAccessibilitySelectionEnd());
5456                    event.setItemCount(text.length());
5457                }
5458            } break;
5459        }
5460    }
5461
5462    /**
5463     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5464     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5465     * This method is responsible for obtaining an accessibility node info from a
5466     * pool of reusable instances and calling
5467     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5468     * initialize the former.
5469     * <p>
5470     * Note: The client is responsible for recycling the obtained instance by calling
5471     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5472     * </p>
5473     *
5474     * @return A populated {@link AccessibilityNodeInfo}.
5475     *
5476     * @see AccessibilityNodeInfo
5477     */
5478    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5479        if (mAccessibilityDelegate != null) {
5480            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5481        } else {
5482            return createAccessibilityNodeInfoInternal();
5483        }
5484    }
5485
5486    /**
5487     * @see #createAccessibilityNodeInfo()
5488     *
5489     * @hide
5490     */
5491    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5492        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5493        if (provider != null) {
5494            return provider.createAccessibilityNodeInfo(View.NO_ID);
5495        } else {
5496            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5497            onInitializeAccessibilityNodeInfo(info);
5498            return info;
5499        }
5500    }
5501
5502    /**
5503     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5504     * The base implementation sets:
5505     * <ul>
5506     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5507     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5508     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5509     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5510     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5511     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5512     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5513     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5514     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5515     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5516     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5517     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5518     * </ul>
5519     * <p>
5520     * Subclasses should override this method, call the super implementation,
5521     * and set additional attributes.
5522     * </p>
5523     * <p>
5524     * If an {@link AccessibilityDelegate} has been specified via calling
5525     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5526     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5527     * is responsible for handling this call.
5528     * </p>
5529     *
5530     * @param info The instance to initialize.
5531     */
5532    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5533        if (mAccessibilityDelegate != null) {
5534            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5535        } else {
5536            onInitializeAccessibilityNodeInfoInternal(info);
5537        }
5538    }
5539
5540    /**
5541     * Gets the location of this view in screen coordinates.
5542     *
5543     * @param outRect The output location
5544     * @hide
5545     */
5546    public void getBoundsOnScreen(Rect outRect) {
5547        getBoundsOnScreen(outRect, false);
5548    }
5549
5550    /**
5551     * Gets the location of this view in screen coordinates.
5552     *
5553     * @param outRect The output location
5554     * @param clipToParent Whether to clip child bounds to the parent ones.
5555     * @hide
5556     */
5557    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
5558        if (mAttachInfo == null) {
5559            return;
5560        }
5561
5562        RectF position = mAttachInfo.mTmpTransformRect;
5563        position.set(0, 0, mRight - mLeft, mBottom - mTop);
5564
5565        if (!hasIdentityMatrix()) {
5566            getMatrix().mapRect(position);
5567        }
5568
5569        position.offset(mLeft, mTop);
5570
5571        ViewParent parent = mParent;
5572        while (parent instanceof View) {
5573            View parentView = (View) parent;
5574
5575            position.offset(-parentView.mScrollX, -parentView.mScrollY);
5576
5577            if (clipToParent) {
5578                position.left = Math.max(position.left, 0);
5579                position.top = Math.max(position.top, 0);
5580                position.right = Math.min(position.right, parentView.getWidth());
5581                position.bottom = Math.min(position.bottom, parentView.getHeight());
5582            }
5583
5584            if (!parentView.hasIdentityMatrix()) {
5585                parentView.getMatrix().mapRect(position);
5586            }
5587
5588            position.offset(parentView.mLeft, parentView.mTop);
5589
5590            parent = parentView.mParent;
5591        }
5592
5593        if (parent instanceof ViewRootImpl) {
5594            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5595            position.offset(0, -viewRootImpl.mCurScrollY);
5596        }
5597
5598        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5599
5600        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5601                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5602    }
5603
5604    /**
5605     * Return the class name of this object to be used for accessibility purposes.
5606     * Subclasses should only override this if they are implementing something that
5607     * should be seen as a completely new class of view when used by accessibility,
5608     * unrelated to the class it is deriving from.  This is used to fill in
5609     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
5610     */
5611    public CharSequence getAccessibilityClassName() {
5612        return View.class.getName();
5613    }
5614
5615    /**
5616     * Called when assist data is being retrieved from a view as part of
5617     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
5618     * @param data
5619     * @param extras
5620     */
5621    public void onProvideAssistData(ViewAssistData data, Bundle extras) {
5622    }
5623
5624    /**
5625     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5626     *
5627     * Note: Called from the default {@link AccessibilityDelegate}.
5628     *
5629     * @hide
5630     */
5631    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5632        Rect bounds = mAttachInfo.mTmpInvalRect;
5633
5634        getDrawingRect(bounds);
5635        info.setBoundsInParent(bounds);
5636
5637        getBoundsOnScreen(bounds, true);
5638        info.setBoundsInScreen(bounds);
5639
5640        ViewParent parent = getParentForAccessibility();
5641        if (parent instanceof View) {
5642            info.setParent((View) parent);
5643        }
5644
5645        if (mID != View.NO_ID) {
5646            View rootView = getRootView();
5647            if (rootView == null) {
5648                rootView = this;
5649            }
5650
5651            View label = rootView.findLabelForView(this, mID);
5652            if (label != null) {
5653                info.setLabeledBy(label);
5654            }
5655
5656            if ((mAttachInfo.mAccessibilityFetchFlags
5657                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5658                    && Resources.resourceHasPackage(mID)) {
5659                try {
5660                    String viewId = getResources().getResourceName(mID);
5661                    info.setViewIdResourceName(viewId);
5662                } catch (Resources.NotFoundException nfe) {
5663                    /* ignore */
5664                }
5665            }
5666        }
5667
5668        if (mLabelForId != View.NO_ID) {
5669            View rootView = getRootView();
5670            if (rootView == null) {
5671                rootView = this;
5672            }
5673            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5674            if (labeled != null) {
5675                info.setLabelFor(labeled);
5676            }
5677        }
5678
5679        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
5680            View rootView = getRootView();
5681            if (rootView == null) {
5682                rootView = this;
5683            }
5684            View next = rootView.findViewInsideOutShouldExist(this,
5685                    mAccessibilityTraversalBeforeId);
5686            if (next != null) {
5687                info.setTraversalBefore(next);
5688            }
5689        }
5690
5691        if (mAccessibilityTraversalAfterId != View.NO_ID) {
5692            View rootView = getRootView();
5693            if (rootView == null) {
5694                rootView = this;
5695            }
5696            View next = rootView.findViewInsideOutShouldExist(this,
5697                    mAccessibilityTraversalAfterId);
5698            if (next != null) {
5699                info.setTraversalAfter(next);
5700            }
5701        }
5702
5703        info.setVisibleToUser(isVisibleToUser());
5704
5705        info.setPackageName(mContext.getPackageName());
5706        info.setClassName(getAccessibilityClassName());
5707        info.setContentDescription(getContentDescription());
5708
5709        info.setEnabled(isEnabled());
5710        info.setClickable(isClickable());
5711        info.setFocusable(isFocusable());
5712        info.setFocused(isFocused());
5713        info.setAccessibilityFocused(isAccessibilityFocused());
5714        info.setSelected(isSelected());
5715        info.setLongClickable(isLongClickable());
5716        info.setLiveRegion(getAccessibilityLiveRegion());
5717
5718        // TODO: These make sense only if we are in an AdapterView but all
5719        // views can be selected. Maybe from accessibility perspective
5720        // we should report as selectable view in an AdapterView.
5721        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5722        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5723
5724        if (isFocusable()) {
5725            if (isFocused()) {
5726                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5727            } else {
5728                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5729            }
5730        }
5731
5732        if (!isAccessibilityFocused()) {
5733            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5734        } else {
5735            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5736        }
5737
5738        if (isClickable() && isEnabled()) {
5739            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5740        }
5741
5742        if (isLongClickable() && isEnabled()) {
5743            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5744        }
5745
5746        CharSequence text = getIterableTextForAccessibility();
5747        if (text != null && text.length() > 0) {
5748            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5749
5750            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5751            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5752            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5753            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5754                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5755                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5756        }
5757    }
5758
5759    private View findLabelForView(View view, int labeledId) {
5760        if (mMatchLabelForPredicate == null) {
5761            mMatchLabelForPredicate = new MatchLabelForPredicate();
5762        }
5763        mMatchLabelForPredicate.mLabeledId = labeledId;
5764        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5765    }
5766
5767    /**
5768     * Computes whether this view is visible to the user. Such a view is
5769     * attached, visible, all its predecessors are visible, it is not clipped
5770     * entirely by its predecessors, and has an alpha greater than zero.
5771     *
5772     * @return Whether the view is visible on the screen.
5773     *
5774     * @hide
5775     */
5776    protected boolean isVisibleToUser() {
5777        return isVisibleToUser(null);
5778    }
5779
5780    /**
5781     * Computes whether the given portion of this view is visible to the user.
5782     * Such a view is attached, visible, all its predecessors are visible,
5783     * has an alpha greater than zero, and the specified portion is not
5784     * clipped entirely by its predecessors.
5785     *
5786     * @param boundInView the portion of the view to test; coordinates should be relative; may be
5787     *                    <code>null</code>, and the entire view will be tested in this case.
5788     *                    When <code>true</code> is returned by the function, the actual visible
5789     *                    region will be stored in this parameter; that is, if boundInView is fully
5790     *                    contained within the view, no modification will be made, otherwise regions
5791     *                    outside of the visible area of the view will be clipped.
5792     *
5793     * @return Whether the specified portion of the view is visible on the screen.
5794     *
5795     * @hide
5796     */
5797    protected boolean isVisibleToUser(Rect boundInView) {
5798        if (mAttachInfo != null) {
5799            // Attached to invisible window means this view is not visible.
5800            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5801                return false;
5802            }
5803            // An invisible predecessor or one with alpha zero means
5804            // that this view is not visible to the user.
5805            Object current = this;
5806            while (current instanceof View) {
5807                View view = (View) current;
5808                // We have attach info so this view is attached and there is no
5809                // need to check whether we reach to ViewRootImpl on the way up.
5810                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5811                        view.getVisibility() != VISIBLE) {
5812                    return false;
5813                }
5814                current = view.mParent;
5815            }
5816            // Check if the view is entirely covered by its predecessors.
5817            Rect visibleRect = mAttachInfo.mTmpInvalRect;
5818            Point offset = mAttachInfo.mPoint;
5819            if (!getGlobalVisibleRect(visibleRect, offset)) {
5820                return false;
5821            }
5822            // Check if the visible portion intersects the rectangle of interest.
5823            if (boundInView != null) {
5824                visibleRect.offset(-offset.x, -offset.y);
5825                return boundInView.intersect(visibleRect);
5826            }
5827            return true;
5828        }
5829        return false;
5830    }
5831
5832    /**
5833     * Returns the delegate for implementing accessibility support via
5834     * composition. For more details see {@link AccessibilityDelegate}.
5835     *
5836     * @return The delegate, or null if none set.
5837     *
5838     * @hide
5839     */
5840    public AccessibilityDelegate getAccessibilityDelegate() {
5841        return mAccessibilityDelegate;
5842    }
5843
5844    /**
5845     * Sets a delegate for implementing accessibility support via composition as
5846     * opposed to inheritance. The delegate's primary use is for implementing
5847     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5848     *
5849     * @param delegate The delegate instance.
5850     *
5851     * @see AccessibilityDelegate
5852     */
5853    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
5854        mAccessibilityDelegate = delegate;
5855    }
5856
5857    /**
5858     * Gets the provider for managing a virtual view hierarchy rooted at this View
5859     * and reported to {@link android.accessibilityservice.AccessibilityService}s
5860     * that explore the window content.
5861     * <p>
5862     * If this method returns an instance, this instance is responsible for managing
5863     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5864     * View including the one representing the View itself. Similarly the returned
5865     * instance is responsible for performing accessibility actions on any virtual
5866     * view or the root view itself.
5867     * </p>
5868     * <p>
5869     * If an {@link AccessibilityDelegate} has been specified via calling
5870     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5871     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5872     * is responsible for handling this call.
5873     * </p>
5874     *
5875     * @return The provider.
5876     *
5877     * @see AccessibilityNodeProvider
5878     */
5879    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5880        if (mAccessibilityDelegate != null) {
5881            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5882        } else {
5883            return null;
5884        }
5885    }
5886
5887    /**
5888     * Gets the unique identifier of this view on the screen for accessibility purposes.
5889     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5890     *
5891     * @return The view accessibility id.
5892     *
5893     * @hide
5894     */
5895    public int getAccessibilityViewId() {
5896        if (mAccessibilityViewId == NO_ID) {
5897            mAccessibilityViewId = sNextAccessibilityViewId++;
5898        }
5899        return mAccessibilityViewId;
5900    }
5901
5902    /**
5903     * Gets the unique identifier of the window in which this View reseides.
5904     *
5905     * @return The window accessibility id.
5906     *
5907     * @hide
5908     */
5909    public int getAccessibilityWindowId() {
5910        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5911                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5912    }
5913
5914    /**
5915     * Gets the {@link View} description. It briefly describes the view and is
5916     * primarily used for accessibility support. Set this property to enable
5917     * better accessibility support for your application. This is especially
5918     * true for views that do not have textual representation (For example,
5919     * ImageButton).
5920     *
5921     * @return The content description.
5922     *
5923     * @attr ref android.R.styleable#View_contentDescription
5924     */
5925    @ViewDebug.ExportedProperty(category = "accessibility")
5926    public CharSequence getContentDescription() {
5927        return mContentDescription;
5928    }
5929
5930    /**
5931     * Sets the {@link View} description. It briefly describes the view and is
5932     * primarily used for accessibility support. Set this property to enable
5933     * better accessibility support for your application. This is especially
5934     * true for views that do not have textual representation (For example,
5935     * ImageButton).
5936     *
5937     * @param contentDescription The content description.
5938     *
5939     * @attr ref android.R.styleable#View_contentDescription
5940     */
5941    @RemotableViewMethod
5942    public void setContentDescription(CharSequence contentDescription) {
5943        if (mContentDescription == null) {
5944            if (contentDescription == null) {
5945                return;
5946            }
5947        } else if (mContentDescription.equals(contentDescription)) {
5948            return;
5949        }
5950        mContentDescription = contentDescription;
5951        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5952        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5953            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5954            notifySubtreeAccessibilityStateChangedIfNeeded();
5955        } else {
5956            notifyViewAccessibilityStateChangedIfNeeded(
5957                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
5958        }
5959    }
5960
5961    /**
5962     * Sets the id of a view before which this one is visited in accessibility traversal.
5963     * A screen-reader must visit the content of this view before the content of the one
5964     * it precedes. For example, if view B is set to be before view A, then a screen-reader
5965     * will traverse the entire content of B before traversing the entire content of A,
5966     * regardles of what traversal strategy it is using.
5967     * <p>
5968     * Views that do not have specified before/after relationships are traversed in order
5969     * determined by the screen-reader.
5970     * </p>
5971     * <p>
5972     * Setting that this view is before a view that is not important for accessibility
5973     * or if this view is not important for accessibility will have no effect as the
5974     * screen-reader is not aware of unimportant views.
5975     * </p>
5976     *
5977     * @param beforeId The id of a view this one precedes in accessibility traversal.
5978     *
5979     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
5980     *
5981     * @see #setImportantForAccessibility(int)
5982     */
5983    @RemotableViewMethod
5984    public void setAccessibilityTraversalBefore(int beforeId) {
5985        if (mAccessibilityTraversalBeforeId == beforeId) {
5986            return;
5987        }
5988        mAccessibilityTraversalBeforeId = beforeId;
5989        notifyViewAccessibilityStateChangedIfNeeded(
5990                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5991    }
5992
5993    /**
5994     * Gets the id of a view before which this one is visited in accessibility traversal.
5995     *
5996     * @return The id of a view this one precedes in accessibility traversal if
5997     *         specified, otherwise {@link #NO_ID}.
5998     *
5999     * @see #setAccessibilityTraversalBefore(int)
6000     */
6001    public int getAccessibilityTraversalBefore() {
6002        return mAccessibilityTraversalBeforeId;
6003    }
6004
6005    /**
6006     * Sets the id of a view after which this one is visited in accessibility traversal.
6007     * A screen-reader must visit the content of the other view before the content of this
6008     * one. For example, if view B is set to be after view A, then a screen-reader
6009     * will traverse the entire content of A before traversing the entire content of B,
6010     * regardles of what traversal strategy it is using.
6011     * <p>
6012     * Views that do not have specified before/after relationships are traversed in order
6013     * determined by the screen-reader.
6014     * </p>
6015     * <p>
6016     * Setting that this view is after a view that is not important for accessibility
6017     * or if this view is not important for accessibility will have no effect as the
6018     * screen-reader is not aware of unimportant views.
6019     * </p>
6020     *
6021     * @param afterId The id of a view this one succedees in accessibility traversal.
6022     *
6023     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6024     *
6025     * @see #setImportantForAccessibility(int)
6026     */
6027    @RemotableViewMethod
6028    public void setAccessibilityTraversalAfter(int afterId) {
6029        if (mAccessibilityTraversalAfterId == afterId) {
6030            return;
6031        }
6032        mAccessibilityTraversalAfterId = afterId;
6033        notifyViewAccessibilityStateChangedIfNeeded(
6034                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6035    }
6036
6037    /**
6038     * Gets the id of a view after which this one is visited in accessibility traversal.
6039     *
6040     * @return The id of a view this one succeedes in accessibility traversal if
6041     *         specified, otherwise {@link #NO_ID}.
6042     *
6043     * @see #setAccessibilityTraversalAfter(int)
6044     */
6045    public int getAccessibilityTraversalAfter() {
6046        return mAccessibilityTraversalAfterId;
6047    }
6048
6049    /**
6050     * Gets the id of a view for which this view serves as a label for
6051     * accessibility purposes.
6052     *
6053     * @return The labeled view id.
6054     */
6055    @ViewDebug.ExportedProperty(category = "accessibility")
6056    public int getLabelFor() {
6057        return mLabelForId;
6058    }
6059
6060    /**
6061     * Sets the id of a view for which this view serves as a label for
6062     * accessibility purposes.
6063     *
6064     * @param id The labeled view id.
6065     */
6066    @RemotableViewMethod
6067    public void setLabelFor(@IdRes int id) {
6068        if (mLabelForId == id) {
6069            return;
6070        }
6071        mLabelForId = id;
6072        if (mLabelForId != View.NO_ID
6073                && mID == View.NO_ID) {
6074            mID = generateViewId();
6075        }
6076        notifyViewAccessibilityStateChangedIfNeeded(
6077                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6078    }
6079
6080    /**
6081     * Invoked whenever this view loses focus, either by losing window focus or by losing
6082     * focus within its window. This method can be used to clear any state tied to the
6083     * focus. For instance, if a button is held pressed with the trackball and the window
6084     * loses focus, this method can be used to cancel the press.
6085     *
6086     * Subclasses of View overriding this method should always call super.onFocusLost().
6087     *
6088     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6089     * @see #onWindowFocusChanged(boolean)
6090     *
6091     * @hide pending API council approval
6092     */
6093    protected void onFocusLost() {
6094        resetPressedState();
6095    }
6096
6097    private void resetPressedState() {
6098        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6099            return;
6100        }
6101
6102        if (isPressed()) {
6103            setPressed(false);
6104
6105            if (!mHasPerformedLongPress) {
6106                removeLongPressCallback();
6107            }
6108        }
6109    }
6110
6111    /**
6112     * Returns true if this view has focus
6113     *
6114     * @return True if this view has focus, false otherwise.
6115     */
6116    @ViewDebug.ExportedProperty(category = "focus")
6117    public boolean isFocused() {
6118        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6119    }
6120
6121    /**
6122     * Find the view in the hierarchy rooted at this view that currently has
6123     * focus.
6124     *
6125     * @return The view that currently has focus, or null if no focused view can
6126     *         be found.
6127     */
6128    public View findFocus() {
6129        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6130    }
6131
6132    /**
6133     * Indicates whether this view is one of the set of scrollable containers in
6134     * its window.
6135     *
6136     * @return whether this view is one of the set of scrollable containers in
6137     * its window
6138     *
6139     * @attr ref android.R.styleable#View_isScrollContainer
6140     */
6141    public boolean isScrollContainer() {
6142        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6143    }
6144
6145    /**
6146     * Change whether this view is one of the set of scrollable containers in
6147     * its window.  This will be used to determine whether the window can
6148     * resize or must pan when a soft input area is open -- scrollable
6149     * containers allow the window to use resize mode since the container
6150     * will appropriately shrink.
6151     *
6152     * @attr ref android.R.styleable#View_isScrollContainer
6153     */
6154    public void setScrollContainer(boolean isScrollContainer) {
6155        if (isScrollContainer) {
6156            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6157                mAttachInfo.mScrollContainers.add(this);
6158                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6159            }
6160            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6161        } else {
6162            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6163                mAttachInfo.mScrollContainers.remove(this);
6164            }
6165            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6166        }
6167    }
6168
6169    /**
6170     * Returns the quality of the drawing cache.
6171     *
6172     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6173     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6174     *
6175     * @see #setDrawingCacheQuality(int)
6176     * @see #setDrawingCacheEnabled(boolean)
6177     * @see #isDrawingCacheEnabled()
6178     *
6179     * @attr ref android.R.styleable#View_drawingCacheQuality
6180     */
6181    @DrawingCacheQuality
6182    public int getDrawingCacheQuality() {
6183        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6184    }
6185
6186    /**
6187     * Set the drawing cache quality of this view. This value is used only when the
6188     * drawing cache is enabled
6189     *
6190     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6191     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6192     *
6193     * @see #getDrawingCacheQuality()
6194     * @see #setDrawingCacheEnabled(boolean)
6195     * @see #isDrawingCacheEnabled()
6196     *
6197     * @attr ref android.R.styleable#View_drawingCacheQuality
6198     */
6199    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6200        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6201    }
6202
6203    /**
6204     * Returns whether the screen should remain on, corresponding to the current
6205     * value of {@link #KEEP_SCREEN_ON}.
6206     *
6207     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6208     *
6209     * @see #setKeepScreenOn(boolean)
6210     *
6211     * @attr ref android.R.styleable#View_keepScreenOn
6212     */
6213    public boolean getKeepScreenOn() {
6214        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6215    }
6216
6217    /**
6218     * Controls whether the screen should remain on, modifying the
6219     * value of {@link #KEEP_SCREEN_ON}.
6220     *
6221     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6222     *
6223     * @see #getKeepScreenOn()
6224     *
6225     * @attr ref android.R.styleable#View_keepScreenOn
6226     */
6227    public void setKeepScreenOn(boolean keepScreenOn) {
6228        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6229    }
6230
6231    /**
6232     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6233     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6234     *
6235     * @attr ref android.R.styleable#View_nextFocusLeft
6236     */
6237    public int getNextFocusLeftId() {
6238        return mNextFocusLeftId;
6239    }
6240
6241    /**
6242     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6243     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6244     * decide automatically.
6245     *
6246     * @attr ref android.R.styleable#View_nextFocusLeft
6247     */
6248    public void setNextFocusLeftId(int nextFocusLeftId) {
6249        mNextFocusLeftId = nextFocusLeftId;
6250    }
6251
6252    /**
6253     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6254     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6255     *
6256     * @attr ref android.R.styleable#View_nextFocusRight
6257     */
6258    public int getNextFocusRightId() {
6259        return mNextFocusRightId;
6260    }
6261
6262    /**
6263     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6264     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6265     * decide automatically.
6266     *
6267     * @attr ref android.R.styleable#View_nextFocusRight
6268     */
6269    public void setNextFocusRightId(int nextFocusRightId) {
6270        mNextFocusRightId = nextFocusRightId;
6271    }
6272
6273    /**
6274     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6275     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6276     *
6277     * @attr ref android.R.styleable#View_nextFocusUp
6278     */
6279    public int getNextFocusUpId() {
6280        return mNextFocusUpId;
6281    }
6282
6283    /**
6284     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6285     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6286     * decide automatically.
6287     *
6288     * @attr ref android.R.styleable#View_nextFocusUp
6289     */
6290    public void setNextFocusUpId(int nextFocusUpId) {
6291        mNextFocusUpId = nextFocusUpId;
6292    }
6293
6294    /**
6295     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6296     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6297     *
6298     * @attr ref android.R.styleable#View_nextFocusDown
6299     */
6300    public int getNextFocusDownId() {
6301        return mNextFocusDownId;
6302    }
6303
6304    /**
6305     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6306     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6307     * decide automatically.
6308     *
6309     * @attr ref android.R.styleable#View_nextFocusDown
6310     */
6311    public void setNextFocusDownId(int nextFocusDownId) {
6312        mNextFocusDownId = nextFocusDownId;
6313    }
6314
6315    /**
6316     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6317     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6318     *
6319     * @attr ref android.R.styleable#View_nextFocusForward
6320     */
6321    public int getNextFocusForwardId() {
6322        return mNextFocusForwardId;
6323    }
6324
6325    /**
6326     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6327     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6328     * decide automatically.
6329     *
6330     * @attr ref android.R.styleable#View_nextFocusForward
6331     */
6332    public void setNextFocusForwardId(int nextFocusForwardId) {
6333        mNextFocusForwardId = nextFocusForwardId;
6334    }
6335
6336    /**
6337     * Returns the visibility of this view and all of its ancestors
6338     *
6339     * @return True if this view and all of its ancestors are {@link #VISIBLE}
6340     */
6341    public boolean isShown() {
6342        View current = this;
6343        //noinspection ConstantConditions
6344        do {
6345            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6346                return false;
6347            }
6348            ViewParent parent = current.mParent;
6349            if (parent == null) {
6350                return false; // We are not attached to the view root
6351            }
6352            if (!(parent instanceof View)) {
6353                return true;
6354            }
6355            current = (View) parent;
6356        } while (current != null);
6357
6358        return false;
6359    }
6360
6361    /**
6362     * Called by the view hierarchy when the content insets for a window have
6363     * changed, to allow it to adjust its content to fit within those windows.
6364     * The content insets tell you the space that the status bar, input method,
6365     * and other system windows infringe on the application's window.
6366     *
6367     * <p>You do not normally need to deal with this function, since the default
6368     * window decoration given to applications takes care of applying it to the
6369     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6370     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6371     * and your content can be placed under those system elements.  You can then
6372     * use this method within your view hierarchy if you have parts of your UI
6373     * which you would like to ensure are not being covered.
6374     *
6375     * <p>The default implementation of this method simply applies the content
6376     * insets to the view's padding, consuming that content (modifying the
6377     * insets to be 0), and returning true.  This behavior is off by default, but can
6378     * be enabled through {@link #setFitsSystemWindows(boolean)}.
6379     *
6380     * <p>This function's traversal down the hierarchy is depth-first.  The same content
6381     * insets object is propagated down the hierarchy, so any changes made to it will
6382     * be seen by all following views (including potentially ones above in
6383     * the hierarchy since this is a depth-first traversal).  The first view
6384     * that returns true will abort the entire traversal.
6385     *
6386     * <p>The default implementation works well for a situation where it is
6387     * used with a container that covers the entire window, allowing it to
6388     * apply the appropriate insets to its content on all edges.  If you need
6389     * a more complicated layout (such as two different views fitting system
6390     * windows, one on the top of the window, and one on the bottom),
6391     * you can override the method and handle the insets however you would like.
6392     * Note that the insets provided by the framework are always relative to the
6393     * far edges of the window, not accounting for the location of the called view
6394     * within that window.  (In fact when this method is called you do not yet know
6395     * where the layout will place the view, as it is done before layout happens.)
6396     *
6397     * <p>Note: unlike many View methods, there is no dispatch phase to this
6398     * call.  If you are overriding it in a ViewGroup and want to allow the
6399     * call to continue to your children, you must be sure to call the super
6400     * implementation.
6401     *
6402     * <p>Here is a sample layout that makes use of fitting system windows
6403     * to have controls for a video view placed inside of the window decorations
6404     * that it hides and shows.  This can be used with code like the second
6405     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6406     *
6407     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6408     *
6409     * @param insets Current content insets of the window.  Prior to
6410     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6411     * the insets or else you and Android will be unhappy.
6412     *
6413     * @return {@code true} if this view applied the insets and it should not
6414     * continue propagating further down the hierarchy, {@code false} otherwise.
6415     * @see #getFitsSystemWindows()
6416     * @see #setFitsSystemWindows(boolean)
6417     * @see #setSystemUiVisibility(int)
6418     *
6419     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6420     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6421     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6422     * to implement handling their own insets.
6423     */
6424    protected boolean fitSystemWindows(Rect insets) {
6425        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6426            if (insets == null) {
6427                // Null insets by definition have already been consumed.
6428                // This call cannot apply insets since there are none to apply,
6429                // so return false.
6430                return false;
6431            }
6432            // If we're not in the process of dispatching the newer apply insets call,
6433            // that means we're not in the compatibility path. Dispatch into the newer
6434            // apply insets path and take things from there.
6435            try {
6436                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6437                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6438            } finally {
6439                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6440            }
6441        } else {
6442            // We're being called from the newer apply insets path.
6443            // Perform the standard fallback behavior.
6444            return fitSystemWindowsInt(insets);
6445        }
6446    }
6447
6448    private boolean fitSystemWindowsInt(Rect insets) {
6449        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6450            mUserPaddingStart = UNDEFINED_PADDING;
6451            mUserPaddingEnd = UNDEFINED_PADDING;
6452            Rect localInsets = sThreadLocal.get();
6453            if (localInsets == null) {
6454                localInsets = new Rect();
6455                sThreadLocal.set(localInsets);
6456            }
6457            boolean res = computeFitSystemWindows(insets, localInsets);
6458            mUserPaddingLeftInitial = localInsets.left;
6459            mUserPaddingRightInitial = localInsets.right;
6460            internalSetPadding(localInsets.left, localInsets.top,
6461                    localInsets.right, localInsets.bottom);
6462            return res;
6463        }
6464        return false;
6465    }
6466
6467    /**
6468     * Called when the view should apply {@link WindowInsets} according to its internal policy.
6469     *
6470     * <p>This method should be overridden by views that wish to apply a policy different from or
6471     * in addition to the default behavior. Clients that wish to force a view subtree
6472     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6473     *
6474     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6475     * it will be called during dispatch instead of this method. The listener may optionally
6476     * call this method from its own implementation if it wishes to apply the view's default
6477     * insets policy in addition to its own.</p>
6478     *
6479     * <p>Implementations of this method should either return the insets parameter unchanged
6480     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6481     * that this view applied itself. This allows new inset types added in future platform
6482     * versions to pass through existing implementations unchanged without being erroneously
6483     * consumed.</p>
6484     *
6485     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6486     * property is set then the view will consume the system window insets and apply them
6487     * as padding for the view.</p>
6488     *
6489     * @param insets Insets to apply
6490     * @return The supplied insets with any applied insets consumed
6491     */
6492    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6493        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6494            // We weren't called from within a direct call to fitSystemWindows,
6495            // call into it as a fallback in case we're in a class that overrides it
6496            // and has logic to perform.
6497            if (fitSystemWindows(insets.getSystemWindowInsets())) {
6498                return insets.consumeSystemWindowInsets();
6499            }
6500        } else {
6501            // We were called from within a direct call to fitSystemWindows.
6502            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6503                return insets.consumeSystemWindowInsets();
6504            }
6505        }
6506        return insets;
6507    }
6508
6509    /**
6510     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6511     * window insets to this view. The listener's
6512     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6513     * method will be called instead of the view's
6514     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6515     *
6516     * @param listener Listener to set
6517     *
6518     * @see #onApplyWindowInsets(WindowInsets)
6519     */
6520    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6521        getListenerInfo().mOnApplyWindowInsetsListener = listener;
6522    }
6523
6524    /**
6525     * Request to apply the given window insets to this view or another view in its subtree.
6526     *
6527     * <p>This method should be called by clients wishing to apply insets corresponding to areas
6528     * obscured by window decorations or overlays. This can include the status and navigation bars,
6529     * action bars, input methods and more. New inset categories may be added in the future.
6530     * The method returns the insets provided minus any that were applied by this view or its
6531     * children.</p>
6532     *
6533     * <p>Clients wishing to provide custom behavior should override the
6534     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6535     * {@link OnApplyWindowInsetsListener} via the
6536     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6537     * method.</p>
6538     *
6539     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6540     * </p>
6541     *
6542     * @param insets Insets to apply
6543     * @return The provided insets minus the insets that were consumed
6544     */
6545    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6546        try {
6547            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6548            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6549                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6550            } else {
6551                return onApplyWindowInsets(insets);
6552            }
6553        } finally {
6554            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6555        }
6556    }
6557
6558    /**
6559     * @hide Compute the insets that should be consumed by this view and the ones
6560     * that should propagate to those under it.
6561     */
6562    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6563        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6564                || mAttachInfo == null
6565                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6566                        && !mAttachInfo.mOverscanRequested)) {
6567            outLocalInsets.set(inoutInsets);
6568            inoutInsets.set(0, 0, 0, 0);
6569            return true;
6570        } else {
6571            // The application wants to take care of fitting system window for
6572            // the content...  however we still need to take care of any overscan here.
6573            final Rect overscan = mAttachInfo.mOverscanInsets;
6574            outLocalInsets.set(overscan);
6575            inoutInsets.left -= overscan.left;
6576            inoutInsets.top -= overscan.top;
6577            inoutInsets.right -= overscan.right;
6578            inoutInsets.bottom -= overscan.bottom;
6579            return false;
6580        }
6581    }
6582
6583    /**
6584     * Compute insets that should be consumed by this view and the ones that should propagate
6585     * to those under it.
6586     *
6587     * @param in Insets currently being processed by this View, likely received as a parameter
6588     *           to {@link #onApplyWindowInsets(WindowInsets)}.
6589     * @param outLocalInsets A Rect that will receive the insets that should be consumed
6590     *                       by this view
6591     * @return Insets that should be passed along to views under this one
6592     */
6593    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6594        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6595                || mAttachInfo == null
6596                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6597            outLocalInsets.set(in.getSystemWindowInsets());
6598            return in.consumeSystemWindowInsets();
6599        } else {
6600            outLocalInsets.set(0, 0, 0, 0);
6601            return in;
6602        }
6603    }
6604
6605    /**
6606     * Sets whether or not this view should account for system screen decorations
6607     * such as the status bar and inset its content; that is, controlling whether
6608     * the default implementation of {@link #fitSystemWindows(Rect)} will be
6609     * executed.  See that method for more details.
6610     *
6611     * <p>Note that if you are providing your own implementation of
6612     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6613     * flag to true -- your implementation will be overriding the default
6614     * implementation that checks this flag.
6615     *
6616     * @param fitSystemWindows If true, then the default implementation of
6617     * {@link #fitSystemWindows(Rect)} will be executed.
6618     *
6619     * @attr ref android.R.styleable#View_fitsSystemWindows
6620     * @see #getFitsSystemWindows()
6621     * @see #fitSystemWindows(Rect)
6622     * @see #setSystemUiVisibility(int)
6623     */
6624    public void setFitsSystemWindows(boolean fitSystemWindows) {
6625        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6626    }
6627
6628    /**
6629     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6630     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6631     * will be executed.
6632     *
6633     * @return {@code true} if the default implementation of
6634     * {@link #fitSystemWindows(Rect)} will be executed.
6635     *
6636     * @attr ref android.R.styleable#View_fitsSystemWindows
6637     * @see #setFitsSystemWindows(boolean)
6638     * @see #fitSystemWindows(Rect)
6639     * @see #setSystemUiVisibility(int)
6640     */
6641    @ViewDebug.ExportedProperty
6642    public boolean getFitsSystemWindows() {
6643        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6644    }
6645
6646    /** @hide */
6647    public boolean fitsSystemWindows() {
6648        return getFitsSystemWindows();
6649    }
6650
6651    /**
6652     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6653     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6654     */
6655    public void requestFitSystemWindows() {
6656        if (mParent != null) {
6657            mParent.requestFitSystemWindows();
6658        }
6659    }
6660
6661    /**
6662     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6663     */
6664    public void requestApplyInsets() {
6665        requestFitSystemWindows();
6666    }
6667
6668    /**
6669     * For use by PhoneWindow to make its own system window fitting optional.
6670     * @hide
6671     */
6672    public void makeOptionalFitsSystemWindows() {
6673        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6674    }
6675
6676    /**
6677     * Returns the visibility status for this view.
6678     *
6679     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6680     * @attr ref android.R.styleable#View_visibility
6681     */
6682    @ViewDebug.ExportedProperty(mapping = {
6683        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6684        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6685        @ViewDebug.IntToString(from = GONE,      to = "GONE")
6686    })
6687    @Visibility
6688    public int getVisibility() {
6689        return mViewFlags & VISIBILITY_MASK;
6690    }
6691
6692    /**
6693     * Set the enabled state of this view.
6694     *
6695     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6696     * @attr ref android.R.styleable#View_visibility
6697     */
6698    @RemotableViewMethod
6699    public void setVisibility(@Visibility int visibility) {
6700        setFlags(visibility, VISIBILITY_MASK);
6701    }
6702
6703    /**
6704     * Returns the enabled status for this view. The interpretation of the
6705     * enabled state varies by subclass.
6706     *
6707     * @return True if this view is enabled, false otherwise.
6708     */
6709    @ViewDebug.ExportedProperty
6710    public boolean isEnabled() {
6711        return (mViewFlags & ENABLED_MASK) == ENABLED;
6712    }
6713
6714    /**
6715     * Set the enabled state of this view. The interpretation of the enabled
6716     * state varies by subclass.
6717     *
6718     * @param enabled True if this view is enabled, false otherwise.
6719     */
6720    @RemotableViewMethod
6721    public void setEnabled(boolean enabled) {
6722        if (enabled == isEnabled()) return;
6723
6724        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6725
6726        /*
6727         * The View most likely has to change its appearance, so refresh
6728         * the drawable state.
6729         */
6730        refreshDrawableState();
6731
6732        // Invalidate too, since the default behavior for views is to be
6733        // be drawn at 50% alpha rather than to change the drawable.
6734        invalidate(true);
6735
6736        if (!enabled) {
6737            cancelPendingInputEvents();
6738        }
6739    }
6740
6741    /**
6742     * Set whether this view can receive the focus.
6743     *
6744     * Setting this to false will also ensure that this view is not focusable
6745     * in touch mode.
6746     *
6747     * @param focusable If true, this view can receive the focus.
6748     *
6749     * @see #setFocusableInTouchMode(boolean)
6750     * @attr ref android.R.styleable#View_focusable
6751     */
6752    public void setFocusable(boolean focusable) {
6753        if (!focusable) {
6754            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6755        }
6756        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6757    }
6758
6759    /**
6760     * Set whether this view can receive focus while in touch mode.
6761     *
6762     * Setting this to true will also ensure that this view is focusable.
6763     *
6764     * @param focusableInTouchMode If true, this view can receive the focus while
6765     *   in touch mode.
6766     *
6767     * @see #setFocusable(boolean)
6768     * @attr ref android.R.styleable#View_focusableInTouchMode
6769     */
6770    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6771        // Focusable in touch mode should always be set before the focusable flag
6772        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6773        // which, in touch mode, will not successfully request focus on this view
6774        // because the focusable in touch mode flag is not set
6775        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6776        if (focusableInTouchMode) {
6777            setFlags(FOCUSABLE, FOCUSABLE_MASK);
6778        }
6779    }
6780
6781    /**
6782     * Set whether this view should have sound effects enabled for events such as
6783     * clicking and touching.
6784     *
6785     * <p>You may wish to disable sound effects for a view if you already play sounds,
6786     * for instance, a dial key that plays dtmf tones.
6787     *
6788     * @param soundEffectsEnabled whether sound effects are enabled for this view.
6789     * @see #isSoundEffectsEnabled()
6790     * @see #playSoundEffect(int)
6791     * @attr ref android.R.styleable#View_soundEffectsEnabled
6792     */
6793    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6794        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6795    }
6796
6797    /**
6798     * @return whether this view should have sound effects enabled for events such as
6799     *     clicking and touching.
6800     *
6801     * @see #setSoundEffectsEnabled(boolean)
6802     * @see #playSoundEffect(int)
6803     * @attr ref android.R.styleable#View_soundEffectsEnabled
6804     */
6805    @ViewDebug.ExportedProperty
6806    public boolean isSoundEffectsEnabled() {
6807        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6808    }
6809
6810    /**
6811     * Set whether this view should have haptic feedback for events such as
6812     * long presses.
6813     *
6814     * <p>You may wish to disable haptic feedback if your view already controls
6815     * its own haptic feedback.
6816     *
6817     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6818     * @see #isHapticFeedbackEnabled()
6819     * @see #performHapticFeedback(int)
6820     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6821     */
6822    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6823        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6824    }
6825
6826    /**
6827     * @return whether this view should have haptic feedback enabled for events
6828     * long presses.
6829     *
6830     * @see #setHapticFeedbackEnabled(boolean)
6831     * @see #performHapticFeedback(int)
6832     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6833     */
6834    @ViewDebug.ExportedProperty
6835    public boolean isHapticFeedbackEnabled() {
6836        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6837    }
6838
6839    /**
6840     * Returns the layout direction for this view.
6841     *
6842     * @return One of {@link #LAYOUT_DIRECTION_LTR},
6843     *   {@link #LAYOUT_DIRECTION_RTL},
6844     *   {@link #LAYOUT_DIRECTION_INHERIT} or
6845     *   {@link #LAYOUT_DIRECTION_LOCALE}.
6846     *
6847     * @attr ref android.R.styleable#View_layoutDirection
6848     *
6849     * @hide
6850     */
6851    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6852        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
6853        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
6854        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6855        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
6856    })
6857    @LayoutDir
6858    public int getRawLayoutDirection() {
6859        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6860    }
6861
6862    /**
6863     * Set the layout direction for this view. This will propagate a reset of layout direction
6864     * resolution to the view's children and resolve layout direction for this view.
6865     *
6866     * @param layoutDirection the layout direction to set. Should be one of:
6867     *
6868     * {@link #LAYOUT_DIRECTION_LTR},
6869     * {@link #LAYOUT_DIRECTION_RTL},
6870     * {@link #LAYOUT_DIRECTION_INHERIT},
6871     * {@link #LAYOUT_DIRECTION_LOCALE}.
6872     *
6873     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6874     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6875     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6876     *
6877     * @attr ref android.R.styleable#View_layoutDirection
6878     */
6879    @RemotableViewMethod
6880    public void setLayoutDirection(@LayoutDir int layoutDirection) {
6881        if (getRawLayoutDirection() != layoutDirection) {
6882            // Reset the current layout direction and the resolved one
6883            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6884            resetRtlProperties();
6885            // Set the new layout direction (filtered)
6886            mPrivateFlags2 |=
6887                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6888            // We need to resolve all RTL properties as they all depend on layout direction
6889            resolveRtlPropertiesIfNeeded();
6890            requestLayout();
6891            invalidate(true);
6892        }
6893    }
6894
6895    /**
6896     * Returns the resolved layout direction for this view.
6897     *
6898     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6899     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6900     *
6901     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6902     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6903     *
6904     * @attr ref android.R.styleable#View_layoutDirection
6905     */
6906    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6907        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6908        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6909    })
6910    @ResolvedLayoutDir
6911    public int getLayoutDirection() {
6912        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6913        if (targetSdkVersion < JELLY_BEAN_MR1) {
6914            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6915            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6916        }
6917        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6918                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6919    }
6920
6921    /**
6922     * Indicates whether or not this view's layout is right-to-left. This is resolved from
6923     * layout attribute and/or the inherited value from the parent
6924     *
6925     * @return true if the layout is right-to-left.
6926     *
6927     * @hide
6928     */
6929    @ViewDebug.ExportedProperty(category = "layout")
6930    public boolean isLayoutRtl() {
6931        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6932    }
6933
6934    /**
6935     * Indicates whether the view is currently tracking transient state that the
6936     * app should not need to concern itself with saving and restoring, but that
6937     * the framework should take special note to preserve when possible.
6938     *
6939     * <p>A view with transient state cannot be trivially rebound from an external
6940     * data source, such as an adapter binding item views in a list. This may be
6941     * because the view is performing an animation, tracking user selection
6942     * of content, or similar.</p>
6943     *
6944     * @return true if the view has transient state
6945     */
6946    @ViewDebug.ExportedProperty(category = "layout")
6947    public boolean hasTransientState() {
6948        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6949    }
6950
6951    /**
6952     * Set whether this view is currently tracking transient state that the
6953     * framework should attempt to preserve when possible. This flag is reference counted,
6954     * so every call to setHasTransientState(true) should be paired with a later call
6955     * to setHasTransientState(false).
6956     *
6957     * <p>A view with transient state cannot be trivially rebound from an external
6958     * data source, such as an adapter binding item views in a list. This may be
6959     * because the view is performing an animation, tracking user selection
6960     * of content, or similar.</p>
6961     *
6962     * @param hasTransientState true if this view has transient state
6963     */
6964    public void setHasTransientState(boolean hasTransientState) {
6965        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6966                mTransientStateCount - 1;
6967        if (mTransientStateCount < 0) {
6968            mTransientStateCount = 0;
6969            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6970                    "unmatched pair of setHasTransientState calls");
6971        } else if ((hasTransientState && mTransientStateCount == 1) ||
6972                (!hasTransientState && mTransientStateCount == 0)) {
6973            // update flag if we've just incremented up from 0 or decremented down to 0
6974            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6975                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6976            if (mParent != null) {
6977                try {
6978                    mParent.childHasTransientStateChanged(this, hasTransientState);
6979                } catch (AbstractMethodError e) {
6980                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6981                            " does not fully implement ViewParent", e);
6982                }
6983            }
6984        }
6985    }
6986
6987    /**
6988     * Returns true if this view is currently attached to a window.
6989     */
6990    public boolean isAttachedToWindow() {
6991        return mAttachInfo != null;
6992    }
6993
6994    /**
6995     * Returns true if this view has been through at least one layout since it
6996     * was last attached to or detached from a window.
6997     */
6998    public boolean isLaidOut() {
6999        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7000    }
7001
7002    /**
7003     * If this view doesn't do any drawing on its own, set this flag to
7004     * allow further optimizations. By default, this flag is not set on
7005     * View, but could be set on some View subclasses such as ViewGroup.
7006     *
7007     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7008     * you should clear this flag.
7009     *
7010     * @param willNotDraw whether or not this View draw on its own
7011     */
7012    public void setWillNotDraw(boolean willNotDraw) {
7013        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7014    }
7015
7016    /**
7017     * Returns whether or not this View draws on its own.
7018     *
7019     * @return true if this view has nothing to draw, false otherwise
7020     */
7021    @ViewDebug.ExportedProperty(category = "drawing")
7022    public boolean willNotDraw() {
7023        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7024    }
7025
7026    /**
7027     * When a View's drawing cache is enabled, drawing is redirected to an
7028     * offscreen bitmap. Some views, like an ImageView, must be able to
7029     * bypass this mechanism if they already draw a single bitmap, to avoid
7030     * unnecessary usage of the memory.
7031     *
7032     * @param willNotCacheDrawing true if this view does not cache its
7033     *        drawing, false otherwise
7034     */
7035    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7036        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7037    }
7038
7039    /**
7040     * Returns whether or not this View can cache its drawing or not.
7041     *
7042     * @return true if this view does not cache its drawing, false otherwise
7043     */
7044    @ViewDebug.ExportedProperty(category = "drawing")
7045    public boolean willNotCacheDrawing() {
7046        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7047    }
7048
7049    /**
7050     * Indicates whether this view reacts to click events or not.
7051     *
7052     * @return true if the view is clickable, false otherwise
7053     *
7054     * @see #setClickable(boolean)
7055     * @attr ref android.R.styleable#View_clickable
7056     */
7057    @ViewDebug.ExportedProperty
7058    public boolean isClickable() {
7059        return (mViewFlags & CLICKABLE) == CLICKABLE;
7060    }
7061
7062    /**
7063     * Enables or disables click events for this view. When a view
7064     * is clickable it will change its state to "pressed" on every click.
7065     * Subclasses should set the view clickable to visually react to
7066     * user's clicks.
7067     *
7068     * @param clickable true to make the view clickable, false otherwise
7069     *
7070     * @see #isClickable()
7071     * @attr ref android.R.styleable#View_clickable
7072     */
7073    public void setClickable(boolean clickable) {
7074        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7075    }
7076
7077    /**
7078     * Indicates whether this view reacts to long click events or not.
7079     *
7080     * @return true if the view is long clickable, false otherwise
7081     *
7082     * @see #setLongClickable(boolean)
7083     * @attr ref android.R.styleable#View_longClickable
7084     */
7085    public boolean isLongClickable() {
7086        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7087    }
7088
7089    /**
7090     * Enables or disables long click events for this view. When a view is long
7091     * clickable it reacts to the user holding down the button for a longer
7092     * duration than a tap. This event can either launch the listener or a
7093     * context menu.
7094     *
7095     * @param longClickable true to make the view long clickable, false otherwise
7096     * @see #isLongClickable()
7097     * @attr ref android.R.styleable#View_longClickable
7098     */
7099    public void setLongClickable(boolean longClickable) {
7100        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7101    }
7102
7103    /**
7104     * Sets the pressed state for this view and provides a touch coordinate for
7105     * animation hinting.
7106     *
7107     * @param pressed Pass true to set the View's internal state to "pressed",
7108     *            or false to reverts the View's internal state from a
7109     *            previously set "pressed" state.
7110     * @param x The x coordinate of the touch that caused the press
7111     * @param y The y coordinate of the touch that caused the press
7112     */
7113    private void setPressed(boolean pressed, float x, float y) {
7114        if (pressed) {
7115            drawableHotspotChanged(x, y);
7116        }
7117
7118        setPressed(pressed);
7119    }
7120
7121    /**
7122     * Sets the pressed state for this view.
7123     *
7124     * @see #isClickable()
7125     * @see #setClickable(boolean)
7126     *
7127     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7128     *        the View's internal state from a previously set "pressed" state.
7129     */
7130    public void setPressed(boolean pressed) {
7131        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7132
7133        if (pressed) {
7134            mPrivateFlags |= PFLAG_PRESSED;
7135        } else {
7136            mPrivateFlags &= ~PFLAG_PRESSED;
7137        }
7138
7139        if (needsRefresh) {
7140            refreshDrawableState();
7141        }
7142        dispatchSetPressed(pressed);
7143    }
7144
7145    /**
7146     * Dispatch setPressed to all of this View's children.
7147     *
7148     * @see #setPressed(boolean)
7149     *
7150     * @param pressed The new pressed state
7151     */
7152    protected void dispatchSetPressed(boolean pressed) {
7153    }
7154
7155    /**
7156     * Indicates whether the view is currently in pressed state. Unless
7157     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7158     * the pressed state.
7159     *
7160     * @see #setPressed(boolean)
7161     * @see #isClickable()
7162     * @see #setClickable(boolean)
7163     *
7164     * @return true if the view is currently pressed, false otherwise
7165     */
7166    @ViewDebug.ExportedProperty
7167    public boolean isPressed() {
7168        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7169    }
7170
7171    /**
7172     * Indicates whether this view will save its state (that is,
7173     * whether its {@link #onSaveInstanceState} method will be called).
7174     *
7175     * @return Returns true if the view state saving is enabled, else false.
7176     *
7177     * @see #setSaveEnabled(boolean)
7178     * @attr ref android.R.styleable#View_saveEnabled
7179     */
7180    public boolean isSaveEnabled() {
7181        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7182    }
7183
7184    /**
7185     * Controls whether the saving of this view's state is
7186     * enabled (that is, whether its {@link #onSaveInstanceState} method
7187     * will be called).  Note that even if freezing is enabled, the
7188     * view still must have an id assigned to it (via {@link #setId(int)})
7189     * for its state to be saved.  This flag can only disable the
7190     * saving of this view; any child views may still have their state saved.
7191     *
7192     * @param enabled Set to false to <em>disable</em> state saving, or true
7193     * (the default) to allow it.
7194     *
7195     * @see #isSaveEnabled()
7196     * @see #setId(int)
7197     * @see #onSaveInstanceState()
7198     * @attr ref android.R.styleable#View_saveEnabled
7199     */
7200    public void setSaveEnabled(boolean enabled) {
7201        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7202    }
7203
7204    /**
7205     * Gets whether the framework should discard touches when the view's
7206     * window is obscured by another visible window.
7207     * Refer to the {@link View} security documentation for more details.
7208     *
7209     * @return True if touch filtering is enabled.
7210     *
7211     * @see #setFilterTouchesWhenObscured(boolean)
7212     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7213     */
7214    @ViewDebug.ExportedProperty
7215    public boolean getFilterTouchesWhenObscured() {
7216        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7217    }
7218
7219    /**
7220     * Sets whether the framework should discard touches when the view's
7221     * window is obscured by another visible window.
7222     * Refer to the {@link View} security documentation for more details.
7223     *
7224     * @param enabled True if touch filtering should be enabled.
7225     *
7226     * @see #getFilterTouchesWhenObscured
7227     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7228     */
7229    public void setFilterTouchesWhenObscured(boolean enabled) {
7230        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7231                FILTER_TOUCHES_WHEN_OBSCURED);
7232    }
7233
7234    /**
7235     * Indicates whether the entire hierarchy under this view will save its
7236     * state when a state saving traversal occurs from its parent.  The default
7237     * is true; if false, these views will not be saved unless
7238     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7239     *
7240     * @return Returns true if the view state saving from parent is enabled, else false.
7241     *
7242     * @see #setSaveFromParentEnabled(boolean)
7243     */
7244    public boolean isSaveFromParentEnabled() {
7245        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7246    }
7247
7248    /**
7249     * Controls whether the entire hierarchy under this view will save its
7250     * state when a state saving traversal occurs from its parent.  The default
7251     * is true; if false, these views will not be saved unless
7252     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7253     *
7254     * @param enabled Set to false to <em>disable</em> state saving, or true
7255     * (the default) to allow it.
7256     *
7257     * @see #isSaveFromParentEnabled()
7258     * @see #setId(int)
7259     * @see #onSaveInstanceState()
7260     */
7261    public void setSaveFromParentEnabled(boolean enabled) {
7262        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7263    }
7264
7265
7266    /**
7267     * Returns whether this View is able to take focus.
7268     *
7269     * @return True if this view can take focus, or false otherwise.
7270     * @attr ref android.R.styleable#View_focusable
7271     */
7272    @ViewDebug.ExportedProperty(category = "focus")
7273    public final boolean isFocusable() {
7274        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7275    }
7276
7277    /**
7278     * When a view is focusable, it may not want to take focus when in touch mode.
7279     * For example, a button would like focus when the user is navigating via a D-pad
7280     * so that the user can click on it, but once the user starts touching the screen,
7281     * the button shouldn't take focus
7282     * @return Whether the view is focusable in touch mode.
7283     * @attr ref android.R.styleable#View_focusableInTouchMode
7284     */
7285    @ViewDebug.ExportedProperty
7286    public final boolean isFocusableInTouchMode() {
7287        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7288    }
7289
7290    /**
7291     * Find the nearest view in the specified direction that can take focus.
7292     * This does not actually give focus to that view.
7293     *
7294     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7295     *
7296     * @return The nearest focusable in the specified direction, or null if none
7297     *         can be found.
7298     */
7299    public View focusSearch(@FocusRealDirection int direction) {
7300        if (mParent != null) {
7301            return mParent.focusSearch(this, direction);
7302        } else {
7303            return null;
7304        }
7305    }
7306
7307    /**
7308     * This method is the last chance for the focused view and its ancestors to
7309     * respond to an arrow key. This is called when the focused view did not
7310     * consume the key internally, nor could the view system find a new view in
7311     * the requested direction to give focus to.
7312     *
7313     * @param focused The currently focused view.
7314     * @param direction The direction focus wants to move. One of FOCUS_UP,
7315     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7316     * @return True if the this view consumed this unhandled move.
7317     */
7318    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7319        return false;
7320    }
7321
7322    /**
7323     * If a user manually specified the next view id for a particular direction,
7324     * use the root to look up the view.
7325     * @param root The root view of the hierarchy containing this view.
7326     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7327     * or FOCUS_BACKWARD.
7328     * @return The user specified next view, or null if there is none.
7329     */
7330    View findUserSetNextFocus(View root, @FocusDirection int direction) {
7331        switch (direction) {
7332            case FOCUS_LEFT:
7333                if (mNextFocusLeftId == View.NO_ID) return null;
7334                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7335            case FOCUS_RIGHT:
7336                if (mNextFocusRightId == View.NO_ID) return null;
7337                return findViewInsideOutShouldExist(root, mNextFocusRightId);
7338            case FOCUS_UP:
7339                if (mNextFocusUpId == View.NO_ID) return null;
7340                return findViewInsideOutShouldExist(root, mNextFocusUpId);
7341            case FOCUS_DOWN:
7342                if (mNextFocusDownId == View.NO_ID) return null;
7343                return findViewInsideOutShouldExist(root, mNextFocusDownId);
7344            case FOCUS_FORWARD:
7345                if (mNextFocusForwardId == View.NO_ID) return null;
7346                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7347            case FOCUS_BACKWARD: {
7348                if (mID == View.NO_ID) return null;
7349                final int id = mID;
7350                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7351                    @Override
7352                    public boolean apply(View t) {
7353                        return t.mNextFocusForwardId == id;
7354                    }
7355                });
7356            }
7357        }
7358        return null;
7359    }
7360
7361    private View findViewInsideOutShouldExist(View root, int id) {
7362        if (mMatchIdPredicate == null) {
7363            mMatchIdPredicate = new MatchIdPredicate();
7364        }
7365        mMatchIdPredicate.mId = id;
7366        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7367        if (result == null) {
7368            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7369        }
7370        return result;
7371    }
7372
7373    /**
7374     * Find and return all focusable views that are descendants of this view,
7375     * possibly including this view if it is focusable itself.
7376     *
7377     * @param direction The direction of the focus
7378     * @return A list of focusable views
7379     */
7380    public ArrayList<View> getFocusables(@FocusDirection int direction) {
7381        ArrayList<View> result = new ArrayList<View>(24);
7382        addFocusables(result, direction);
7383        return result;
7384    }
7385
7386    /**
7387     * Add any focusable views that are descendants of this view (possibly
7388     * including this view if it is focusable itself) to views.  If we are in touch mode,
7389     * only add views that are also focusable in touch mode.
7390     *
7391     * @param views Focusable views found so far
7392     * @param direction The direction of the focus
7393     */
7394    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7395        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7396    }
7397
7398    /**
7399     * Adds any focusable views that are descendants of this view (possibly
7400     * including this view if it is focusable itself) to views. This method
7401     * adds all focusable views regardless if we are in touch mode or
7402     * only views focusable in touch mode if we are in touch mode or
7403     * only views that can take accessibility focus if accessibility is enabled
7404     * depending on the focusable mode parameter.
7405     *
7406     * @param views Focusable views found so far or null if all we are interested is
7407     *        the number of focusables.
7408     * @param direction The direction of the focus.
7409     * @param focusableMode The type of focusables to be added.
7410     *
7411     * @see #FOCUSABLES_ALL
7412     * @see #FOCUSABLES_TOUCH_MODE
7413     */
7414    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7415            @FocusableMode int focusableMode) {
7416        if (views == null) {
7417            return;
7418        }
7419        if (!isFocusable()) {
7420            return;
7421        }
7422        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7423                && isInTouchMode() && !isFocusableInTouchMode()) {
7424            return;
7425        }
7426        views.add(this);
7427    }
7428
7429    /**
7430     * Finds the Views that contain given text. The containment is case insensitive.
7431     * The search is performed by either the text that the View renders or the content
7432     * description that describes the view for accessibility purposes and the view does
7433     * not render or both. Clients can specify how the search is to be performed via
7434     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7435     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7436     *
7437     * @param outViews The output list of matching Views.
7438     * @param searched The text to match against.
7439     *
7440     * @see #FIND_VIEWS_WITH_TEXT
7441     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7442     * @see #setContentDescription(CharSequence)
7443     */
7444    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7445            @FindViewFlags int flags) {
7446        if (getAccessibilityNodeProvider() != null) {
7447            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7448                outViews.add(this);
7449            }
7450        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7451                && (searched != null && searched.length() > 0)
7452                && (mContentDescription != null && mContentDescription.length() > 0)) {
7453            String searchedLowerCase = searched.toString().toLowerCase();
7454            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7455            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7456                outViews.add(this);
7457            }
7458        }
7459    }
7460
7461    /**
7462     * Find and return all touchable views that are descendants of this view,
7463     * possibly including this view if it is touchable itself.
7464     *
7465     * @return A list of touchable views
7466     */
7467    public ArrayList<View> getTouchables() {
7468        ArrayList<View> result = new ArrayList<View>();
7469        addTouchables(result);
7470        return result;
7471    }
7472
7473    /**
7474     * Add any touchable views that are descendants of this view (possibly
7475     * including this view if it is touchable itself) to views.
7476     *
7477     * @param views Touchable views found so far
7478     */
7479    public void addTouchables(ArrayList<View> views) {
7480        final int viewFlags = mViewFlags;
7481
7482        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7483                && (viewFlags & ENABLED_MASK) == ENABLED) {
7484            views.add(this);
7485        }
7486    }
7487
7488    /**
7489     * Returns whether this View is accessibility focused.
7490     *
7491     * @return True if this View is accessibility focused.
7492     */
7493    public boolean isAccessibilityFocused() {
7494        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7495    }
7496
7497    /**
7498     * Call this to try to give accessibility focus to this view.
7499     *
7500     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7501     * returns false or the view is no visible or the view already has accessibility
7502     * focus.
7503     *
7504     * See also {@link #focusSearch(int)}, which is what you call to say that you
7505     * have focus, and you want your parent to look for the next one.
7506     *
7507     * @return Whether this view actually took accessibility focus.
7508     *
7509     * @hide
7510     */
7511    public boolean requestAccessibilityFocus() {
7512        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7513        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7514            return false;
7515        }
7516        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7517            return false;
7518        }
7519        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7520            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7521            ViewRootImpl viewRootImpl = getViewRootImpl();
7522            if (viewRootImpl != null) {
7523                viewRootImpl.setAccessibilityFocus(this, null);
7524            }
7525            invalidate();
7526            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7527            return true;
7528        }
7529        return false;
7530    }
7531
7532    /**
7533     * Call this to try to clear accessibility focus of this view.
7534     *
7535     * See also {@link #focusSearch(int)}, which is what you call to say that you
7536     * have focus, and you want your parent to look for the next one.
7537     *
7538     * @hide
7539     */
7540    public void clearAccessibilityFocus() {
7541        clearAccessibilityFocusNoCallbacks();
7542        // Clear the global reference of accessibility focus if this
7543        // view or any of its descendants had accessibility focus.
7544        ViewRootImpl viewRootImpl = getViewRootImpl();
7545        if (viewRootImpl != null) {
7546            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7547            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7548                viewRootImpl.setAccessibilityFocus(null, null);
7549            }
7550        }
7551    }
7552
7553    private void sendAccessibilityHoverEvent(int eventType) {
7554        // Since we are not delivering to a client accessibility events from not
7555        // important views (unless the clinet request that) we need to fire the
7556        // event from the deepest view exposed to the client. As a consequence if
7557        // the user crosses a not exposed view the client will see enter and exit
7558        // of the exposed predecessor followed by and enter and exit of that same
7559        // predecessor when entering and exiting the not exposed descendant. This
7560        // is fine since the client has a clear idea which view is hovered at the
7561        // price of a couple more events being sent. This is a simple and
7562        // working solution.
7563        View source = this;
7564        while (true) {
7565            if (source.includeForAccessibility()) {
7566                source.sendAccessibilityEvent(eventType);
7567                return;
7568            }
7569            ViewParent parent = source.getParent();
7570            if (parent instanceof View) {
7571                source = (View) parent;
7572            } else {
7573                return;
7574            }
7575        }
7576    }
7577
7578    /**
7579     * Clears accessibility focus without calling any callback methods
7580     * normally invoked in {@link #clearAccessibilityFocus()}. This method
7581     * is used for clearing accessibility focus when giving this focus to
7582     * another view.
7583     */
7584    void clearAccessibilityFocusNoCallbacks() {
7585        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7586            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7587            invalidate();
7588            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7589        }
7590    }
7591
7592    /**
7593     * Call this to try to give focus to a specific view or to one of its
7594     * descendants.
7595     *
7596     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7597     * false), or if it is focusable and it is not focusable in touch mode
7598     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7599     *
7600     * See also {@link #focusSearch(int)}, which is what you call to say that you
7601     * have focus, and you want your parent to look for the next one.
7602     *
7603     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7604     * {@link #FOCUS_DOWN} and <code>null</code>.
7605     *
7606     * @return Whether this view or one of its descendants actually took focus.
7607     */
7608    public final boolean requestFocus() {
7609        return requestFocus(View.FOCUS_DOWN);
7610    }
7611
7612    /**
7613     * Call this to try to give focus to a specific view or to one of its
7614     * descendants and give it a hint about what direction focus is heading.
7615     *
7616     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7617     * false), or if it is focusable and it is not focusable in touch mode
7618     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7619     *
7620     * See also {@link #focusSearch(int)}, which is what you call to say that you
7621     * have focus, and you want your parent to look for the next one.
7622     *
7623     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7624     * <code>null</code> set for the previously focused rectangle.
7625     *
7626     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7627     * @return Whether this view or one of its descendants actually took focus.
7628     */
7629    public final boolean requestFocus(int direction) {
7630        return requestFocus(direction, null);
7631    }
7632
7633    /**
7634     * Call this to try to give focus to a specific view or to one of its descendants
7635     * and give it hints about the direction and a specific rectangle that the focus
7636     * is coming from.  The rectangle can help give larger views a finer grained hint
7637     * about where focus is coming from, and therefore, where to show selection, or
7638     * forward focus change internally.
7639     *
7640     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7641     * false), or if it is focusable and it is not focusable in touch mode
7642     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7643     *
7644     * A View will not take focus if it is not visible.
7645     *
7646     * A View will not take focus if one of its parents has
7647     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7648     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7649     *
7650     * See also {@link #focusSearch(int)}, which is what you call to say that you
7651     * have focus, and you want your parent to look for the next one.
7652     *
7653     * You may wish to override this method if your custom {@link View} has an internal
7654     * {@link View} that it wishes to forward the request to.
7655     *
7656     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7657     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7658     *        to give a finer grained hint about where focus is coming from.  May be null
7659     *        if there is no hint.
7660     * @return Whether this view or one of its descendants actually took focus.
7661     */
7662    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7663        return requestFocusNoSearch(direction, previouslyFocusedRect);
7664    }
7665
7666    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7667        // need to be focusable
7668        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7669                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7670            return false;
7671        }
7672
7673        // need to be focusable in touch mode if in touch mode
7674        if (isInTouchMode() &&
7675            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7676               return false;
7677        }
7678
7679        // need to not have any parents blocking us
7680        if (hasAncestorThatBlocksDescendantFocus()) {
7681            return false;
7682        }
7683
7684        handleFocusGainInternal(direction, previouslyFocusedRect);
7685        return true;
7686    }
7687
7688    /**
7689     * Call this to try to give focus to a specific view or to one of its descendants. This is a
7690     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
7691     * touch mode to request focus when they are touched.
7692     *
7693     * @return Whether this view or one of its descendants actually took focus.
7694     *
7695     * @see #isInTouchMode()
7696     *
7697     */
7698    public final boolean requestFocusFromTouch() {
7699        // Leave touch mode if we need to
7700        if (isInTouchMode()) {
7701            ViewRootImpl viewRoot = getViewRootImpl();
7702            if (viewRoot != null) {
7703                viewRoot.ensureTouchMode(false);
7704            }
7705        }
7706        return requestFocus(View.FOCUS_DOWN);
7707    }
7708
7709    /**
7710     * @return Whether any ancestor of this view blocks descendant focus.
7711     */
7712    private boolean hasAncestorThatBlocksDescendantFocus() {
7713        final boolean focusableInTouchMode = isFocusableInTouchMode();
7714        ViewParent ancestor = mParent;
7715        while (ancestor instanceof ViewGroup) {
7716            final ViewGroup vgAncestor = (ViewGroup) ancestor;
7717            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7718                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
7719                return true;
7720            } else {
7721                ancestor = vgAncestor.getParent();
7722            }
7723        }
7724        return false;
7725    }
7726
7727    /**
7728     * Gets the mode for determining whether this View is important for accessibility
7729     * which is if it fires accessibility events and if it is reported to
7730     * accessibility services that query the screen.
7731     *
7732     * @return The mode for determining whether a View is important for accessibility.
7733     *
7734     * @attr ref android.R.styleable#View_importantForAccessibility
7735     *
7736     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7737     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7738     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7739     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7740     */
7741    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7742            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7743            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7744            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7745            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7746                    to = "noHideDescendants")
7747        })
7748    public int getImportantForAccessibility() {
7749        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7750                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7751    }
7752
7753    /**
7754     * Sets the live region mode for this view. This indicates to accessibility
7755     * services whether they should automatically notify the user about changes
7756     * to the view's content description or text, or to the content descriptions
7757     * or text of the view's children (where applicable).
7758     * <p>
7759     * For example, in a login screen with a TextView that displays an "incorrect
7760     * password" notification, that view should be marked as a live region with
7761     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7762     * <p>
7763     * To disable change notifications for this view, use
7764     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7765     * mode for most views.
7766     * <p>
7767     * To indicate that the user should be notified of changes, use
7768     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7769     * <p>
7770     * If the view's changes should interrupt ongoing speech and notify the user
7771     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7772     *
7773     * @param mode The live region mode for this view, one of:
7774     *        <ul>
7775     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7776     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7777     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7778     *        </ul>
7779     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7780     */
7781    public void setAccessibilityLiveRegion(int mode) {
7782        if (mode != getAccessibilityLiveRegion()) {
7783            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7784            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7785                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7786            notifyViewAccessibilityStateChangedIfNeeded(
7787                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7788        }
7789    }
7790
7791    /**
7792     * Gets the live region mode for this View.
7793     *
7794     * @return The live region mode for the view.
7795     *
7796     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7797     *
7798     * @see #setAccessibilityLiveRegion(int)
7799     */
7800    public int getAccessibilityLiveRegion() {
7801        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7802                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7803    }
7804
7805    /**
7806     * Sets how to determine whether this view is important for accessibility
7807     * which is if it fires accessibility events and if it is reported to
7808     * accessibility services that query the screen.
7809     *
7810     * @param mode How to determine whether this view is important for accessibility.
7811     *
7812     * @attr ref android.R.styleable#View_importantForAccessibility
7813     *
7814     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7815     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7816     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7817     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7818     */
7819    public void setImportantForAccessibility(int mode) {
7820        final int oldMode = getImportantForAccessibility();
7821        if (mode != oldMode) {
7822            // If we're moving between AUTO and another state, we might not need
7823            // to send a subtree changed notification. We'll store the computed
7824            // importance, since we'll need to check it later to make sure.
7825            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7826                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7827            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7828            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7829            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7830                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7831            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7832                notifySubtreeAccessibilityStateChangedIfNeeded();
7833            } else {
7834                notifyViewAccessibilityStateChangedIfNeeded(
7835                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7836            }
7837        }
7838    }
7839
7840    /**
7841     * Computes whether this view should be exposed for accessibility. In
7842     * general, views that are interactive or provide information are exposed
7843     * while views that serve only as containers are hidden.
7844     * <p>
7845     * If an ancestor of this view has importance
7846     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7847     * returns <code>false</code>.
7848     * <p>
7849     * Otherwise, the value is computed according to the view's
7850     * {@link #getImportantForAccessibility()} value:
7851     * <ol>
7852     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7853     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7854     * </code>
7855     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7856     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7857     * view satisfies any of the following:
7858     * <ul>
7859     * <li>Is actionable, e.g. {@link #isClickable()},
7860     * {@link #isLongClickable()}, or {@link #isFocusable()}
7861     * <li>Has an {@link AccessibilityDelegate}
7862     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7863     * {@link OnKeyListener}, etc.
7864     * <li>Is an accessibility live region, e.g.
7865     * {@link #getAccessibilityLiveRegion()} is not
7866     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7867     * </ul>
7868     * </ol>
7869     *
7870     * @return Whether the view is exposed for accessibility.
7871     * @see #setImportantForAccessibility(int)
7872     * @see #getImportantForAccessibility()
7873     */
7874    public boolean isImportantForAccessibility() {
7875        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7876                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7877        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7878                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7879            return false;
7880        }
7881
7882        // Check parent mode to ensure we're not hidden.
7883        ViewParent parent = mParent;
7884        while (parent instanceof View) {
7885            if (((View) parent).getImportantForAccessibility()
7886                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7887                return false;
7888            }
7889            parent = parent.getParent();
7890        }
7891
7892        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7893                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7894                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7895    }
7896
7897    /**
7898     * Gets the parent for accessibility purposes. Note that the parent for
7899     * accessibility is not necessary the immediate parent. It is the first
7900     * predecessor that is important for accessibility.
7901     *
7902     * @return The parent for accessibility purposes.
7903     */
7904    public ViewParent getParentForAccessibility() {
7905        if (mParent instanceof View) {
7906            View parentView = (View) mParent;
7907            if (parentView.includeForAccessibility()) {
7908                return mParent;
7909            } else {
7910                return mParent.getParentForAccessibility();
7911            }
7912        }
7913        return null;
7914    }
7915
7916    /**
7917     * Adds the children of a given View for accessibility. Since some Views are
7918     * not important for accessibility the children for accessibility are not
7919     * necessarily direct children of the view, rather they are the first level of
7920     * descendants important for accessibility.
7921     *
7922     * @param children The list of children for accessibility.
7923     */
7924    public void addChildrenForAccessibility(ArrayList<View> children) {
7925
7926    }
7927
7928    /**
7929     * Whether to regard this view for accessibility. A view is regarded for
7930     * accessibility if it is important for accessibility or the querying
7931     * accessibility service has explicitly requested that view not
7932     * important for accessibility are regarded.
7933     *
7934     * @return Whether to regard the view for accessibility.
7935     *
7936     * @hide
7937     */
7938    public boolean includeForAccessibility() {
7939        if (mAttachInfo != null) {
7940            return (mAttachInfo.mAccessibilityFetchFlags
7941                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7942                    || isImportantForAccessibility();
7943        }
7944        return false;
7945    }
7946
7947    /**
7948     * Returns whether the View is considered actionable from
7949     * accessibility perspective. Such view are important for
7950     * accessibility.
7951     *
7952     * @return True if the view is actionable for accessibility.
7953     *
7954     * @hide
7955     */
7956    public boolean isActionableForAccessibility() {
7957        return (isClickable() || isLongClickable() || isFocusable());
7958    }
7959
7960    /**
7961     * Returns whether the View has registered callbacks which makes it
7962     * important for accessibility.
7963     *
7964     * @return True if the view is actionable for accessibility.
7965     */
7966    private boolean hasListenersForAccessibility() {
7967        ListenerInfo info = getListenerInfo();
7968        return mTouchDelegate != null || info.mOnKeyListener != null
7969                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7970                || info.mOnHoverListener != null || info.mOnDragListener != null;
7971    }
7972
7973    /**
7974     * Notifies that the accessibility state of this view changed. The change
7975     * is local to this view and does not represent structural changes such
7976     * as children and parent. For example, the view became focusable. The
7977     * notification is at at most once every
7978     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7979     * to avoid unnecessary load to the system. Also once a view has a pending
7980     * notification this method is a NOP until the notification has been sent.
7981     *
7982     * @hide
7983     */
7984    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7985        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7986            return;
7987        }
7988        if (mSendViewStateChangedAccessibilityEvent == null) {
7989            mSendViewStateChangedAccessibilityEvent =
7990                    new SendViewStateChangedAccessibilityEvent();
7991        }
7992        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7993    }
7994
7995    /**
7996     * Notifies that the accessibility state of this view changed. The change
7997     * is *not* local to this view and does represent structural changes such
7998     * as children and parent. For example, the view size changed. The
7999     * notification is at at most once every
8000     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8001     * to avoid unnecessary load to the system. Also once a view has a pending
8002     * notification this method is a NOP until the notification has been sent.
8003     *
8004     * @hide
8005     */
8006    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8007        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8008            return;
8009        }
8010        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8011            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8012            if (mParent != null) {
8013                try {
8014                    mParent.notifySubtreeAccessibilityStateChanged(
8015                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8016                } catch (AbstractMethodError e) {
8017                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8018                            " does not fully implement ViewParent", e);
8019                }
8020            }
8021        }
8022    }
8023
8024    /**
8025     * Reset the flag indicating the accessibility state of the subtree rooted
8026     * at this view changed.
8027     */
8028    void resetSubtreeAccessibilityStateChanged() {
8029        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8030    }
8031
8032    /**
8033     * Report an accessibility action to this view's parents for delegated processing.
8034     *
8035     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8036     * call this method to delegate an accessibility action to a supporting parent. If the parent
8037     * returns true from its
8038     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8039     * method this method will return true to signify that the action was consumed.</p>
8040     *
8041     * <p>This method is useful for implementing nested scrolling child views. If
8042     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8043     * a custom view implementation may invoke this method to allow a parent to consume the
8044     * scroll first. If this method returns true the custom view should skip its own scrolling
8045     * behavior.</p>
8046     *
8047     * @param action Accessibility action to delegate
8048     * @param arguments Optional action arguments
8049     * @return true if the action was consumed by a parent
8050     */
8051    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8052        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8053            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8054                return true;
8055            }
8056        }
8057        return false;
8058    }
8059
8060    /**
8061     * Performs the specified accessibility action on the view. For
8062     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8063     * <p>
8064     * If an {@link AccessibilityDelegate} has been specified via calling
8065     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8066     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8067     * is responsible for handling this call.
8068     * </p>
8069     *
8070     * <p>The default implementation will delegate
8071     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8072     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8073     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8074     *
8075     * @param action The action to perform.
8076     * @param arguments Optional action arguments.
8077     * @return Whether the action was performed.
8078     */
8079    public boolean performAccessibilityAction(int action, Bundle arguments) {
8080      if (mAccessibilityDelegate != null) {
8081          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8082      } else {
8083          return performAccessibilityActionInternal(action, arguments);
8084      }
8085    }
8086
8087   /**
8088    * @see #performAccessibilityAction(int, Bundle)
8089    *
8090    * Note: Called from the default {@link AccessibilityDelegate}.
8091    *
8092    * @hide
8093    */
8094    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8095        if (isNestedScrollingEnabled()
8096                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8097                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
8098            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8099                return true;
8100            }
8101        }
8102
8103        switch (action) {
8104            case AccessibilityNodeInfo.ACTION_CLICK: {
8105                if (isClickable()) {
8106                    performClick();
8107                    return true;
8108                }
8109            } break;
8110            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8111                if (isLongClickable()) {
8112                    performLongClick();
8113                    return true;
8114                }
8115            } break;
8116            case AccessibilityNodeInfo.ACTION_FOCUS: {
8117                if (!hasFocus()) {
8118                    // Get out of touch mode since accessibility
8119                    // wants to move focus around.
8120                    getViewRootImpl().ensureTouchMode(false);
8121                    return requestFocus();
8122                }
8123            } break;
8124            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8125                if (hasFocus()) {
8126                    clearFocus();
8127                    return !isFocused();
8128                }
8129            } break;
8130            case AccessibilityNodeInfo.ACTION_SELECT: {
8131                if (!isSelected()) {
8132                    setSelected(true);
8133                    return isSelected();
8134                }
8135            } break;
8136            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8137                if (isSelected()) {
8138                    setSelected(false);
8139                    return !isSelected();
8140                }
8141            } break;
8142            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8143                if (!isAccessibilityFocused()) {
8144                    return requestAccessibilityFocus();
8145                }
8146            } break;
8147            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8148                if (isAccessibilityFocused()) {
8149                    clearAccessibilityFocus();
8150                    return true;
8151                }
8152            } break;
8153            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8154                if (arguments != null) {
8155                    final int granularity = arguments.getInt(
8156                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8157                    final boolean extendSelection = arguments.getBoolean(
8158                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8159                    return traverseAtGranularity(granularity, true, extendSelection);
8160                }
8161            } break;
8162            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8163                if (arguments != null) {
8164                    final int granularity = arguments.getInt(
8165                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8166                    final boolean extendSelection = arguments.getBoolean(
8167                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8168                    return traverseAtGranularity(granularity, false, extendSelection);
8169                }
8170            } break;
8171            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8172                CharSequence text = getIterableTextForAccessibility();
8173                if (text == null) {
8174                    return false;
8175                }
8176                final int start = (arguments != null) ? arguments.getInt(
8177                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8178                final int end = (arguments != null) ? arguments.getInt(
8179                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8180                // Only cursor position can be specified (selection length == 0)
8181                if ((getAccessibilitySelectionStart() != start
8182                        || getAccessibilitySelectionEnd() != end)
8183                        && (start == end)) {
8184                    setAccessibilitySelection(start, end);
8185                    notifyViewAccessibilityStateChangedIfNeeded(
8186                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8187                    return true;
8188                }
8189            } break;
8190        }
8191        return false;
8192    }
8193
8194    private boolean traverseAtGranularity(int granularity, boolean forward,
8195            boolean extendSelection) {
8196        CharSequence text = getIterableTextForAccessibility();
8197        if (text == null || text.length() == 0) {
8198            return false;
8199        }
8200        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8201        if (iterator == null) {
8202            return false;
8203        }
8204        int current = getAccessibilitySelectionEnd();
8205        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8206            current = forward ? 0 : text.length();
8207        }
8208        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8209        if (range == null) {
8210            return false;
8211        }
8212        final int segmentStart = range[0];
8213        final int segmentEnd = range[1];
8214        int selectionStart;
8215        int selectionEnd;
8216        if (extendSelection && isAccessibilitySelectionExtendable()) {
8217            selectionStart = getAccessibilitySelectionStart();
8218            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8219                selectionStart = forward ? segmentStart : segmentEnd;
8220            }
8221            selectionEnd = forward ? segmentEnd : segmentStart;
8222        } else {
8223            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8224        }
8225        setAccessibilitySelection(selectionStart, selectionEnd);
8226        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8227                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8228        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8229        return true;
8230    }
8231
8232    /**
8233     * Gets the text reported for accessibility purposes.
8234     *
8235     * @return The accessibility text.
8236     *
8237     * @hide
8238     */
8239    public CharSequence getIterableTextForAccessibility() {
8240        return getContentDescription();
8241    }
8242
8243    /**
8244     * Gets whether accessibility selection can be extended.
8245     *
8246     * @return If selection is extensible.
8247     *
8248     * @hide
8249     */
8250    public boolean isAccessibilitySelectionExtendable() {
8251        return false;
8252    }
8253
8254    /**
8255     * @hide
8256     */
8257    public int getAccessibilitySelectionStart() {
8258        return mAccessibilityCursorPosition;
8259    }
8260
8261    /**
8262     * @hide
8263     */
8264    public int getAccessibilitySelectionEnd() {
8265        return getAccessibilitySelectionStart();
8266    }
8267
8268    /**
8269     * @hide
8270     */
8271    public void setAccessibilitySelection(int start, int end) {
8272        if (start ==  end && end == mAccessibilityCursorPosition) {
8273            return;
8274        }
8275        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8276            mAccessibilityCursorPosition = start;
8277        } else {
8278            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8279        }
8280        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8281    }
8282
8283    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8284            int fromIndex, int toIndex) {
8285        if (mParent == null) {
8286            return;
8287        }
8288        AccessibilityEvent event = AccessibilityEvent.obtain(
8289                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8290        onInitializeAccessibilityEvent(event);
8291        onPopulateAccessibilityEvent(event);
8292        event.setFromIndex(fromIndex);
8293        event.setToIndex(toIndex);
8294        event.setAction(action);
8295        event.setMovementGranularity(granularity);
8296        mParent.requestSendAccessibilityEvent(this, event);
8297    }
8298
8299    /**
8300     * @hide
8301     */
8302    public TextSegmentIterator getIteratorForGranularity(int granularity) {
8303        switch (granularity) {
8304            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8305                CharSequence text = getIterableTextForAccessibility();
8306                if (text != null && text.length() > 0) {
8307                    CharacterTextSegmentIterator iterator =
8308                        CharacterTextSegmentIterator.getInstance(
8309                                mContext.getResources().getConfiguration().locale);
8310                    iterator.initialize(text.toString());
8311                    return iterator;
8312                }
8313            } break;
8314            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8315                CharSequence text = getIterableTextForAccessibility();
8316                if (text != null && text.length() > 0) {
8317                    WordTextSegmentIterator iterator =
8318                        WordTextSegmentIterator.getInstance(
8319                                mContext.getResources().getConfiguration().locale);
8320                    iterator.initialize(text.toString());
8321                    return iterator;
8322                }
8323            } break;
8324            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8325                CharSequence text = getIterableTextForAccessibility();
8326                if (text != null && text.length() > 0) {
8327                    ParagraphTextSegmentIterator iterator =
8328                        ParagraphTextSegmentIterator.getInstance();
8329                    iterator.initialize(text.toString());
8330                    return iterator;
8331                }
8332            } break;
8333        }
8334        return null;
8335    }
8336
8337    /**
8338     * @hide
8339     */
8340    public void dispatchStartTemporaryDetach() {
8341        onStartTemporaryDetach();
8342    }
8343
8344    /**
8345     * This is called when a container is going to temporarily detach a child, with
8346     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8347     * It will either be followed by {@link #onFinishTemporaryDetach()} or
8348     * {@link #onDetachedFromWindow()} when the container is done.
8349     */
8350    public void onStartTemporaryDetach() {
8351        removeUnsetPressCallback();
8352        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8353    }
8354
8355    /**
8356     * @hide
8357     */
8358    public void dispatchFinishTemporaryDetach() {
8359        onFinishTemporaryDetach();
8360    }
8361
8362    /**
8363     * Called after {@link #onStartTemporaryDetach} when the container is done
8364     * changing the view.
8365     */
8366    public void onFinishTemporaryDetach() {
8367    }
8368
8369    /**
8370     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8371     * for this view's window.  Returns null if the view is not currently attached
8372     * to the window.  Normally you will not need to use this directly, but
8373     * just use the standard high-level event callbacks like
8374     * {@link #onKeyDown(int, KeyEvent)}.
8375     */
8376    public KeyEvent.DispatcherState getKeyDispatcherState() {
8377        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8378    }
8379
8380    /**
8381     * Dispatch a key event before it is processed by any input method
8382     * associated with the view hierarchy.  This can be used to intercept
8383     * key events in special situations before the IME consumes them; a
8384     * typical example would be handling the BACK key to update the application's
8385     * UI instead of allowing the IME to see it and close itself.
8386     *
8387     * @param event The key event to be dispatched.
8388     * @return True if the event was handled, false otherwise.
8389     */
8390    public boolean dispatchKeyEventPreIme(KeyEvent event) {
8391        return onKeyPreIme(event.getKeyCode(), event);
8392    }
8393
8394    /**
8395     * Dispatch a key event to the next view on the focus path. This path runs
8396     * from the top of the view tree down to the currently focused view. If this
8397     * view has focus, it will dispatch to itself. Otherwise it will dispatch
8398     * the next node down the focus path. This method also fires any key
8399     * listeners.
8400     *
8401     * @param event The key event to be dispatched.
8402     * @return True if the event was handled, false otherwise.
8403     */
8404    public boolean dispatchKeyEvent(KeyEvent event) {
8405        if (mInputEventConsistencyVerifier != null) {
8406            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8407        }
8408
8409        // Give any attached key listener a first crack at the event.
8410        //noinspection SimplifiableIfStatement
8411        ListenerInfo li = mListenerInfo;
8412        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8413                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8414            return true;
8415        }
8416
8417        if (event.dispatch(this, mAttachInfo != null
8418                ? mAttachInfo.mKeyDispatchState : null, this)) {
8419            return true;
8420        }
8421
8422        if (mInputEventConsistencyVerifier != null) {
8423            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8424        }
8425        return false;
8426    }
8427
8428    /**
8429     * Dispatches a key shortcut event.
8430     *
8431     * @param event The key event to be dispatched.
8432     * @return True if the event was handled by the view, false otherwise.
8433     */
8434    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8435        return onKeyShortcut(event.getKeyCode(), event);
8436    }
8437
8438    /**
8439     * Pass the touch screen motion event down to the target view, or this
8440     * view if it is the target.
8441     *
8442     * @param event The motion event to be dispatched.
8443     * @return True if the event was handled by the view, false otherwise.
8444     */
8445    public boolean dispatchTouchEvent(MotionEvent event) {
8446        // If the event should be handled by accessibility focus first.
8447        if (event.isTargetAccessibilityFocus()) {
8448            // We don't have focus or no virtual descendant has it, do not handle the event.
8449            if (!isAccessibilityFocusedViewOrHost()) {
8450                return false;
8451            }
8452            // We have focus and got the event, then use normal event dispatch.
8453            event.setTargetAccessibilityFocus(false);
8454        }
8455
8456        boolean result = false;
8457
8458        if (mInputEventConsistencyVerifier != null) {
8459            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8460        }
8461
8462        final int actionMasked = event.getActionMasked();
8463        if (actionMasked == MotionEvent.ACTION_DOWN) {
8464            // Defensive cleanup for new gesture
8465            stopNestedScroll();
8466        }
8467
8468        if (onFilterTouchEventForSecurity(event)) {
8469            //noinspection SimplifiableIfStatement
8470            ListenerInfo li = mListenerInfo;
8471            if (li != null && li.mOnTouchListener != null
8472                    && (mViewFlags & ENABLED_MASK) == ENABLED
8473                    && li.mOnTouchListener.onTouch(this, event)) {
8474                result = true;
8475            }
8476
8477            if (!result && onTouchEvent(event)) {
8478                result = true;
8479            }
8480        }
8481
8482        if (!result && mInputEventConsistencyVerifier != null) {
8483            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8484        }
8485
8486        // Clean up after nested scrolls if this is the end of a gesture;
8487        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8488        // of the gesture.
8489        if (actionMasked == MotionEvent.ACTION_UP ||
8490                actionMasked == MotionEvent.ACTION_CANCEL ||
8491                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8492            stopNestedScroll();
8493        }
8494
8495        return result;
8496    }
8497
8498    boolean isAccessibilityFocusedViewOrHost() {
8499        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
8500                .getAccessibilityFocusedHost() == this);
8501    }
8502
8503    /**
8504     * Filter the touch event to apply security policies.
8505     *
8506     * @param event The motion event to be filtered.
8507     * @return True if the event should be dispatched, false if the event should be dropped.
8508     *
8509     * @see #getFilterTouchesWhenObscured
8510     */
8511    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8512        //noinspection RedundantIfStatement
8513        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8514                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8515            // Window is obscured, drop this touch.
8516            return false;
8517        }
8518        return true;
8519    }
8520
8521    /**
8522     * Pass a trackball motion event down to the focused view.
8523     *
8524     * @param event The motion event to be dispatched.
8525     * @return True if the event was handled by the view, false otherwise.
8526     */
8527    public boolean dispatchTrackballEvent(MotionEvent event) {
8528        if (mInputEventConsistencyVerifier != null) {
8529            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8530        }
8531
8532        return onTrackballEvent(event);
8533    }
8534
8535    /**
8536     * Dispatch a generic motion event.
8537     * <p>
8538     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8539     * are delivered to the view under the pointer.  All other generic motion events are
8540     * delivered to the focused view.  Hover events are handled specially and are delivered
8541     * to {@link #onHoverEvent(MotionEvent)}.
8542     * </p>
8543     *
8544     * @param event The motion event to be dispatched.
8545     * @return True if the event was handled by the view, false otherwise.
8546     */
8547    public boolean dispatchGenericMotionEvent(MotionEvent event) {
8548        if (mInputEventConsistencyVerifier != null) {
8549            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8550        }
8551
8552        final int source = event.getSource();
8553        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8554            final int action = event.getAction();
8555            if (action == MotionEvent.ACTION_HOVER_ENTER
8556                    || action == MotionEvent.ACTION_HOVER_MOVE
8557                    || action == MotionEvent.ACTION_HOVER_EXIT) {
8558                if (dispatchHoverEvent(event)) {
8559                    return true;
8560                }
8561            } else if (dispatchGenericPointerEvent(event)) {
8562                return true;
8563            }
8564        } else if (dispatchGenericFocusedEvent(event)) {
8565            return true;
8566        }
8567
8568        if (dispatchGenericMotionEventInternal(event)) {
8569            return true;
8570        }
8571
8572        if (mInputEventConsistencyVerifier != null) {
8573            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8574        }
8575        return false;
8576    }
8577
8578    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8579        //noinspection SimplifiableIfStatement
8580        ListenerInfo li = mListenerInfo;
8581        if (li != null && li.mOnGenericMotionListener != null
8582                && (mViewFlags & ENABLED_MASK) == ENABLED
8583                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8584            return true;
8585        }
8586
8587        if (onGenericMotionEvent(event)) {
8588            return true;
8589        }
8590
8591        if (mInputEventConsistencyVerifier != null) {
8592            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8593        }
8594        return false;
8595    }
8596
8597    /**
8598     * Dispatch a hover event.
8599     * <p>
8600     * Do not call this method directly.
8601     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8602     * </p>
8603     *
8604     * @param event The motion event to be dispatched.
8605     * @return True if the event was handled by the view, false otherwise.
8606     */
8607    protected boolean dispatchHoverEvent(MotionEvent event) {
8608        ListenerInfo li = mListenerInfo;
8609        //noinspection SimplifiableIfStatement
8610        if (li != null && li.mOnHoverListener != null
8611                && (mViewFlags & ENABLED_MASK) == ENABLED
8612                && li.mOnHoverListener.onHover(this, event)) {
8613            return true;
8614        }
8615
8616        return onHoverEvent(event);
8617    }
8618
8619    /**
8620     * Returns true if the view has a child to which it has recently sent
8621     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8622     * it does not have a hovered child, then it must be the innermost hovered view.
8623     * @hide
8624     */
8625    protected boolean hasHoveredChild() {
8626        return false;
8627    }
8628
8629    /**
8630     * Dispatch a generic motion event to the view under the first pointer.
8631     * <p>
8632     * Do not call this method directly.
8633     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8634     * </p>
8635     *
8636     * @param event The motion event to be dispatched.
8637     * @return True if the event was handled by the view, false otherwise.
8638     */
8639    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8640        return false;
8641    }
8642
8643    /**
8644     * Dispatch a generic motion event to the currently focused view.
8645     * <p>
8646     * Do not call this method directly.
8647     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8648     * </p>
8649     *
8650     * @param event The motion event to be dispatched.
8651     * @return True if the event was handled by the view, false otherwise.
8652     */
8653    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8654        return false;
8655    }
8656
8657    /**
8658     * Dispatch a pointer event.
8659     * <p>
8660     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8661     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
8662     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8663     * and should not be expected to handle other pointing device features.
8664     * </p>
8665     *
8666     * @param event The motion event to be dispatched.
8667     * @return True if the event was handled by the view, false otherwise.
8668     * @hide
8669     */
8670    public final boolean dispatchPointerEvent(MotionEvent event) {
8671        if (event.isTouchEvent()) {
8672            return dispatchTouchEvent(event);
8673        } else {
8674            return dispatchGenericMotionEvent(event);
8675        }
8676    }
8677
8678    /**
8679     * Called when the window containing this view gains or loses window focus.
8680     * ViewGroups should override to route to their children.
8681     *
8682     * @param hasFocus True if the window containing this view now has focus,
8683     *        false otherwise.
8684     */
8685    public void dispatchWindowFocusChanged(boolean hasFocus) {
8686        onWindowFocusChanged(hasFocus);
8687    }
8688
8689    /**
8690     * Called when the window containing this view gains or loses focus.  Note
8691     * that this is separate from view focus: to receive key events, both
8692     * your view and its window must have focus.  If a window is displayed
8693     * on top of yours that takes input focus, then your own window will lose
8694     * focus but the view focus will remain unchanged.
8695     *
8696     * @param hasWindowFocus True if the window containing this view now has
8697     *        focus, false otherwise.
8698     */
8699    public void onWindowFocusChanged(boolean hasWindowFocus) {
8700        InputMethodManager imm = InputMethodManager.peekInstance();
8701        if (!hasWindowFocus) {
8702            if (isPressed()) {
8703                setPressed(false);
8704            }
8705            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8706                imm.focusOut(this);
8707            }
8708            removeLongPressCallback();
8709            removeTapCallback();
8710            onFocusLost();
8711        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8712            imm.focusIn(this);
8713        }
8714        refreshDrawableState();
8715    }
8716
8717    /**
8718     * Returns true if this view is in a window that currently has window focus.
8719     * Note that this is not the same as the view itself having focus.
8720     *
8721     * @return True if this view is in a window that currently has window focus.
8722     */
8723    public boolean hasWindowFocus() {
8724        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8725    }
8726
8727    /**
8728     * Dispatch a view visibility change down the view hierarchy.
8729     * ViewGroups should override to route to their children.
8730     * @param changedView The view whose visibility changed. Could be 'this' or
8731     * an ancestor view.
8732     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8733     * {@link #INVISIBLE} or {@link #GONE}.
8734     */
8735    protected void dispatchVisibilityChanged(@NonNull View changedView,
8736            @Visibility int visibility) {
8737        onVisibilityChanged(changedView, visibility);
8738    }
8739
8740    /**
8741     * Called when the visibility of the view or an ancestor of the view has
8742     * changed.
8743     *
8744     * @param changedView The view whose visibility changed. May be
8745     *                    {@code this} or an ancestor view.
8746     * @param visibility The new visibility, one of {@link #VISIBLE},
8747     *                   {@link #INVISIBLE} or {@link #GONE}.
8748     */
8749    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8750        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
8751        if (visible) {
8752            if (mAttachInfo != null) {
8753                initialAwakenScrollBars();
8754            } else {
8755                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8756            }
8757        }
8758
8759        final Drawable dr = mBackground;
8760        if (dr != null && visible != dr.isVisible()) {
8761            dr.setVisible(visible, false);
8762        }
8763    }
8764
8765    /**
8766     * Dispatch a hint about whether this view is displayed. For instance, when
8767     * a View moves out of the screen, it might receives a display hint indicating
8768     * the view is not displayed. Applications should not <em>rely</em> on this hint
8769     * as there is no guarantee that they will receive one.
8770     *
8771     * @param hint A hint about whether or not this view is displayed:
8772     * {@link #VISIBLE} or {@link #INVISIBLE}.
8773     */
8774    public void dispatchDisplayHint(@Visibility int hint) {
8775        onDisplayHint(hint);
8776    }
8777
8778    /**
8779     * Gives this view a hint about whether is displayed or not. For instance, when
8780     * a View moves out of the screen, it might receives a display hint indicating
8781     * the view is not displayed. Applications should not <em>rely</em> on this hint
8782     * as there is no guarantee that they will receive one.
8783     *
8784     * @param hint A hint about whether or not this view is displayed:
8785     * {@link #VISIBLE} or {@link #INVISIBLE}.
8786     */
8787    protected void onDisplayHint(@Visibility int hint) {
8788    }
8789
8790    /**
8791     * Dispatch a window visibility change down the view hierarchy.
8792     * ViewGroups should override to route to their children.
8793     *
8794     * @param visibility The new visibility of the window.
8795     *
8796     * @see #onWindowVisibilityChanged(int)
8797     */
8798    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8799        onWindowVisibilityChanged(visibility);
8800    }
8801
8802    /**
8803     * Called when the window containing has change its visibility
8804     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
8805     * that this tells you whether or not your window is being made visible
8806     * to the window manager; this does <em>not</em> tell you whether or not
8807     * your window is obscured by other windows on the screen, even if it
8808     * is itself visible.
8809     *
8810     * @param visibility The new visibility of the window.
8811     */
8812    protected void onWindowVisibilityChanged(@Visibility int visibility) {
8813        if (visibility == VISIBLE) {
8814            initialAwakenScrollBars();
8815        }
8816    }
8817
8818    /**
8819     * Returns the current visibility of the window this view is attached to
8820     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8821     *
8822     * @return Returns the current visibility of the view's window.
8823     */
8824    @Visibility
8825    public int getWindowVisibility() {
8826        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8827    }
8828
8829    /**
8830     * Retrieve the overall visible display size in which the window this view is
8831     * attached to has been positioned in.  This takes into account screen
8832     * decorations above the window, for both cases where the window itself
8833     * is being position inside of them or the window is being placed under
8834     * then and covered insets are used for the window to position its content
8835     * inside.  In effect, this tells you the available area where content can
8836     * be placed and remain visible to users.
8837     *
8838     * <p>This function requires an IPC back to the window manager to retrieve
8839     * the requested information, so should not be used in performance critical
8840     * code like drawing.
8841     *
8842     * @param outRect Filled in with the visible display frame.  If the view
8843     * is not attached to a window, this is simply the raw display size.
8844     */
8845    public void getWindowVisibleDisplayFrame(Rect outRect) {
8846        if (mAttachInfo != null) {
8847            try {
8848                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8849            } catch (RemoteException e) {
8850                return;
8851            }
8852            // XXX This is really broken, and probably all needs to be done
8853            // in the window manager, and we need to know more about whether
8854            // we want the area behind or in front of the IME.
8855            final Rect insets = mAttachInfo.mVisibleInsets;
8856            outRect.left += insets.left;
8857            outRect.top += insets.top;
8858            outRect.right -= insets.right;
8859            outRect.bottom -= insets.bottom;
8860            return;
8861        }
8862        // The view is not attached to a display so we don't have a context.
8863        // Make a best guess about the display size.
8864        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8865        d.getRectSize(outRect);
8866    }
8867
8868    /**
8869     * Dispatch a notification about a resource configuration change down
8870     * the view hierarchy.
8871     * ViewGroups should override to route to their children.
8872     *
8873     * @param newConfig The new resource configuration.
8874     *
8875     * @see #onConfigurationChanged(android.content.res.Configuration)
8876     */
8877    public void dispatchConfigurationChanged(Configuration newConfig) {
8878        onConfigurationChanged(newConfig);
8879    }
8880
8881    /**
8882     * Called when the current configuration of the resources being used
8883     * by the application have changed.  You can use this to decide when
8884     * to reload resources that can changed based on orientation and other
8885     * configuration characteristics.  You only need to use this if you are
8886     * not relying on the normal {@link android.app.Activity} mechanism of
8887     * recreating the activity instance upon a configuration change.
8888     *
8889     * @param newConfig The new resource configuration.
8890     */
8891    protected void onConfigurationChanged(Configuration newConfig) {
8892    }
8893
8894    /**
8895     * Private function to aggregate all per-view attributes in to the view
8896     * root.
8897     */
8898    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8899        performCollectViewAttributes(attachInfo, visibility);
8900    }
8901
8902    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8903        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8904            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8905                attachInfo.mKeepScreenOn = true;
8906            }
8907            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8908            ListenerInfo li = mListenerInfo;
8909            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8910                attachInfo.mHasSystemUiListeners = true;
8911            }
8912        }
8913    }
8914
8915    void needGlobalAttributesUpdate(boolean force) {
8916        final AttachInfo ai = mAttachInfo;
8917        if (ai != null && !ai.mRecomputeGlobalAttributes) {
8918            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8919                    || ai.mHasSystemUiListeners) {
8920                ai.mRecomputeGlobalAttributes = true;
8921            }
8922        }
8923    }
8924
8925    /**
8926     * Returns whether the device is currently in touch mode.  Touch mode is entered
8927     * once the user begins interacting with the device by touch, and affects various
8928     * things like whether focus is always visible to the user.
8929     *
8930     * @return Whether the device is in touch mode.
8931     */
8932    @ViewDebug.ExportedProperty
8933    public boolean isInTouchMode() {
8934        if (mAttachInfo != null) {
8935            return mAttachInfo.mInTouchMode;
8936        } else {
8937            return ViewRootImpl.isInTouchMode();
8938        }
8939    }
8940
8941    /**
8942     * Returns the context the view is running in, through which it can
8943     * access the current theme, resources, etc.
8944     *
8945     * @return The view's Context.
8946     */
8947    @ViewDebug.CapturedViewProperty
8948    public final Context getContext() {
8949        return mContext;
8950    }
8951
8952    /**
8953     * Handle a key event before it is processed by any input method
8954     * associated with the view hierarchy.  This can be used to intercept
8955     * key events in special situations before the IME consumes them; a
8956     * typical example would be handling the BACK key to update the application's
8957     * UI instead of allowing the IME to see it and close itself.
8958     *
8959     * @param keyCode The value in event.getKeyCode().
8960     * @param event Description of the key event.
8961     * @return If you handled the event, return true. If you want to allow the
8962     *         event to be handled by the next receiver, return false.
8963     */
8964    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8965        return false;
8966    }
8967
8968    /**
8969     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8970     * KeyEvent.Callback.onKeyDown()}: perform press of the view
8971     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8972     * is released, if the view is enabled and clickable.
8973     *
8974     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8975     * although some may elect to do so in some situations. Do not rely on this to
8976     * catch software key presses.
8977     *
8978     * @param keyCode A key code that represents the button pressed, from
8979     *                {@link android.view.KeyEvent}.
8980     * @param event   The KeyEvent object that defines the button action.
8981     */
8982    public boolean onKeyDown(int keyCode, KeyEvent event) {
8983        boolean result = false;
8984
8985        if (KeyEvent.isConfirmKey(keyCode)) {
8986            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8987                return true;
8988            }
8989            // Long clickable items don't necessarily have to be clickable
8990            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8991                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8992                    (event.getRepeatCount() == 0)) {
8993                setPressed(true);
8994                checkForLongClick(0);
8995                return true;
8996            }
8997        }
8998        return result;
8999    }
9000
9001    /**
9002     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9003     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9004     * the event).
9005     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9006     * although some may elect to do so in some situations. Do not rely on this to
9007     * catch software key presses.
9008     */
9009    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9010        return false;
9011    }
9012
9013    /**
9014     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9015     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9016     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9017     * {@link KeyEvent#KEYCODE_ENTER} is released.
9018     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9019     * although some may elect to do so in some situations. Do not rely on this to
9020     * catch software key presses.
9021     *
9022     * @param keyCode A key code that represents the button pressed, from
9023     *                {@link android.view.KeyEvent}.
9024     * @param event   The KeyEvent object that defines the button action.
9025     */
9026    public boolean onKeyUp(int keyCode, KeyEvent event) {
9027        if (KeyEvent.isConfirmKey(keyCode)) {
9028            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9029                return true;
9030            }
9031            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9032                setPressed(false);
9033
9034                if (!mHasPerformedLongPress) {
9035                    // This is a tap, so remove the longpress check
9036                    removeLongPressCallback();
9037                    return performClick();
9038                }
9039            }
9040        }
9041        return false;
9042    }
9043
9044    /**
9045     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9046     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9047     * the event).
9048     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9049     * although some may elect to do so in some situations. Do not rely on this to
9050     * catch software key presses.
9051     *
9052     * @param keyCode     A key code that represents the button pressed, from
9053     *                    {@link android.view.KeyEvent}.
9054     * @param repeatCount The number of times the action was made.
9055     * @param event       The KeyEvent object that defines the button action.
9056     */
9057    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9058        return false;
9059    }
9060
9061    /**
9062     * Called on the focused view when a key shortcut event is not handled.
9063     * Override this method to implement local key shortcuts for the View.
9064     * Key shortcuts can also be implemented by setting the
9065     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9066     *
9067     * @param keyCode The value in event.getKeyCode().
9068     * @param event Description of the key event.
9069     * @return If you handled the event, return true. If you want to allow the
9070     *         event to be handled by the next receiver, return false.
9071     */
9072    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9073        return false;
9074    }
9075
9076    /**
9077     * Check whether the called view is a text editor, in which case it
9078     * would make sense to automatically display a soft input window for
9079     * it.  Subclasses should override this if they implement
9080     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9081     * a call on that method would return a non-null InputConnection, and
9082     * they are really a first-class editor that the user would normally
9083     * start typing on when the go into a window containing your view.
9084     *
9085     * <p>The default implementation always returns false.  This does
9086     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9087     * will not be called or the user can not otherwise perform edits on your
9088     * view; it is just a hint to the system that this is not the primary
9089     * purpose of this view.
9090     *
9091     * @return Returns true if this view is a text editor, else false.
9092     */
9093    public boolean onCheckIsTextEditor() {
9094        return false;
9095    }
9096
9097    /**
9098     * Create a new InputConnection for an InputMethod to interact
9099     * with the view.  The default implementation returns null, since it doesn't
9100     * support input methods.  You can override this to implement such support.
9101     * This is only needed for views that take focus and text input.
9102     *
9103     * <p>When implementing this, you probably also want to implement
9104     * {@link #onCheckIsTextEditor()} to indicate you will return a
9105     * non-null InputConnection.</p>
9106     *
9107     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9108     * object correctly and in its entirety, so that the connected IME can rely
9109     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9110     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9111     * must be filled in with the correct cursor position for IMEs to work correctly
9112     * with your application.</p>
9113     *
9114     * @param outAttrs Fill in with attribute information about the connection.
9115     */
9116    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9117        return null;
9118    }
9119
9120    /**
9121     * Called by the {@link android.view.inputmethod.InputMethodManager}
9122     * when a view who is not the current
9123     * input connection target is trying to make a call on the manager.  The
9124     * default implementation returns false; you can override this to return
9125     * true for certain views if you are performing InputConnection proxying
9126     * to them.
9127     * @param view The View that is making the InputMethodManager call.
9128     * @return Return true to allow the call, false to reject.
9129     */
9130    public boolean checkInputConnectionProxy(View view) {
9131        return false;
9132    }
9133
9134    /**
9135     * Show the context menu for this view. It is not safe to hold on to the
9136     * menu after returning from this method.
9137     *
9138     * You should normally not overload this method. Overload
9139     * {@link #onCreateContextMenu(ContextMenu)} or define an
9140     * {@link OnCreateContextMenuListener} to add items to the context menu.
9141     *
9142     * @param menu The context menu to populate
9143     */
9144    public void createContextMenu(ContextMenu menu) {
9145        ContextMenuInfo menuInfo = getContextMenuInfo();
9146
9147        // Sets the current menu info so all items added to menu will have
9148        // my extra info set.
9149        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9150
9151        onCreateContextMenu(menu);
9152        ListenerInfo li = mListenerInfo;
9153        if (li != null && li.mOnCreateContextMenuListener != null) {
9154            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9155        }
9156
9157        // Clear the extra information so subsequent items that aren't mine don't
9158        // have my extra info.
9159        ((MenuBuilder)menu).setCurrentMenuInfo(null);
9160
9161        if (mParent != null) {
9162            mParent.createContextMenu(menu);
9163        }
9164    }
9165
9166    /**
9167     * Views should implement this if they have extra information to associate
9168     * with the context menu. The return result is supplied as a parameter to
9169     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9170     * callback.
9171     *
9172     * @return Extra information about the item for which the context menu
9173     *         should be shown. This information will vary across different
9174     *         subclasses of View.
9175     */
9176    protected ContextMenuInfo getContextMenuInfo() {
9177        return null;
9178    }
9179
9180    /**
9181     * Views should implement this if the view itself is going to add items to
9182     * the context menu.
9183     *
9184     * @param menu the context menu to populate
9185     */
9186    protected void onCreateContextMenu(ContextMenu menu) {
9187    }
9188
9189    /**
9190     * Implement this method to handle trackball motion events.  The
9191     * <em>relative</em> movement of the trackball since the last event
9192     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9193     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
9194     * that a movement of 1 corresponds to the user pressing one DPAD key (so
9195     * they will often be fractional values, representing the more fine-grained
9196     * movement information available from a trackball).
9197     *
9198     * @param event The motion event.
9199     * @return True if the event was handled, false otherwise.
9200     */
9201    public boolean onTrackballEvent(MotionEvent event) {
9202        return false;
9203    }
9204
9205    /**
9206     * Implement this method to handle generic motion events.
9207     * <p>
9208     * Generic motion events describe joystick movements, mouse hovers, track pad
9209     * touches, scroll wheel movements and other input events.  The
9210     * {@link MotionEvent#getSource() source} of the motion event specifies
9211     * the class of input that was received.  Implementations of this method
9212     * must examine the bits in the source before processing the event.
9213     * The following code example shows how this is done.
9214     * </p><p>
9215     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9216     * are delivered to the view under the pointer.  All other generic motion events are
9217     * delivered to the focused view.
9218     * </p>
9219     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9220     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9221     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
9222     *             // process the joystick movement...
9223     *             return true;
9224     *         }
9225     *     }
9226     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9227     *         switch (event.getAction()) {
9228     *             case MotionEvent.ACTION_HOVER_MOVE:
9229     *                 // process the mouse hover movement...
9230     *                 return true;
9231     *             case MotionEvent.ACTION_SCROLL:
9232     *                 // process the scroll wheel movement...
9233     *                 return true;
9234     *         }
9235     *     }
9236     *     return super.onGenericMotionEvent(event);
9237     * }</pre>
9238     *
9239     * @param event The generic motion event being processed.
9240     * @return True if the event was handled, false otherwise.
9241     */
9242    public boolean onGenericMotionEvent(MotionEvent event) {
9243        return false;
9244    }
9245
9246    /**
9247     * Implement this method to handle hover events.
9248     * <p>
9249     * This method is called whenever a pointer is hovering into, over, or out of the
9250     * bounds of a view and the view is not currently being touched.
9251     * Hover events are represented as pointer events with action
9252     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9253     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9254     * </p>
9255     * <ul>
9256     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9257     * when the pointer enters the bounds of the view.</li>
9258     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9259     * when the pointer has already entered the bounds of the view and has moved.</li>
9260     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9261     * when the pointer has exited the bounds of the view or when the pointer is
9262     * about to go down due to a button click, tap, or similar user action that
9263     * causes the view to be touched.</li>
9264     * </ul>
9265     * <p>
9266     * The view should implement this method to return true to indicate that it is
9267     * handling the hover event, such as by changing its drawable state.
9268     * </p><p>
9269     * The default implementation calls {@link #setHovered} to update the hovered state
9270     * of the view when a hover enter or hover exit event is received, if the view
9271     * is enabled and is clickable.  The default implementation also sends hover
9272     * accessibility events.
9273     * </p>
9274     *
9275     * @param event The motion event that describes the hover.
9276     * @return True if the view handled the hover event.
9277     *
9278     * @see #isHovered
9279     * @see #setHovered
9280     * @see #onHoverChanged
9281     */
9282    public boolean onHoverEvent(MotionEvent event) {
9283        // The root view may receive hover (or touch) events that are outside the bounds of
9284        // the window.  This code ensures that we only send accessibility events for
9285        // hovers that are actually within the bounds of the root view.
9286        final int action = event.getActionMasked();
9287        if (!mSendingHoverAccessibilityEvents) {
9288            if ((action == MotionEvent.ACTION_HOVER_ENTER
9289                    || action == MotionEvent.ACTION_HOVER_MOVE)
9290                    && !hasHoveredChild()
9291                    && pointInView(event.getX(), event.getY())) {
9292                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9293                mSendingHoverAccessibilityEvents = true;
9294            }
9295        } else {
9296            if (action == MotionEvent.ACTION_HOVER_EXIT
9297                    || (action == MotionEvent.ACTION_MOVE
9298                            && !pointInView(event.getX(), event.getY()))) {
9299                mSendingHoverAccessibilityEvents = false;
9300                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9301            }
9302        }
9303
9304        if (isHoverable()) {
9305            switch (action) {
9306                case MotionEvent.ACTION_HOVER_ENTER:
9307                    setHovered(true);
9308                    break;
9309                case MotionEvent.ACTION_HOVER_EXIT:
9310                    setHovered(false);
9311                    break;
9312            }
9313
9314            // Dispatch the event to onGenericMotionEvent before returning true.
9315            // This is to provide compatibility with existing applications that
9316            // handled HOVER_MOVE events in onGenericMotionEvent and that would
9317            // break because of the new default handling for hoverable views
9318            // in onHoverEvent.
9319            // Note that onGenericMotionEvent will be called by default when
9320            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9321            dispatchGenericMotionEventInternal(event);
9322            // The event was already handled by calling setHovered(), so always
9323            // return true.
9324            return true;
9325        }
9326
9327        return false;
9328    }
9329
9330    /**
9331     * Returns true if the view should handle {@link #onHoverEvent}
9332     * by calling {@link #setHovered} to change its hovered state.
9333     *
9334     * @return True if the view is hoverable.
9335     */
9336    private boolean isHoverable() {
9337        final int viewFlags = mViewFlags;
9338        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9339            return false;
9340        }
9341
9342        return (viewFlags & CLICKABLE) == CLICKABLE
9343                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9344    }
9345
9346    /**
9347     * Returns true if the view is currently hovered.
9348     *
9349     * @return True if the view is currently hovered.
9350     *
9351     * @see #setHovered
9352     * @see #onHoverChanged
9353     */
9354    @ViewDebug.ExportedProperty
9355    public boolean isHovered() {
9356        return (mPrivateFlags & PFLAG_HOVERED) != 0;
9357    }
9358
9359    /**
9360     * Sets whether the view is currently hovered.
9361     * <p>
9362     * Calling this method also changes the drawable state of the view.  This
9363     * enables the view to react to hover by using different drawable resources
9364     * to change its appearance.
9365     * </p><p>
9366     * The {@link #onHoverChanged} method is called when the hovered state changes.
9367     * </p>
9368     *
9369     * @param hovered True if the view is hovered.
9370     *
9371     * @see #isHovered
9372     * @see #onHoverChanged
9373     */
9374    public void setHovered(boolean hovered) {
9375        if (hovered) {
9376            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9377                mPrivateFlags |= PFLAG_HOVERED;
9378                refreshDrawableState();
9379                onHoverChanged(true);
9380            }
9381        } else {
9382            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9383                mPrivateFlags &= ~PFLAG_HOVERED;
9384                refreshDrawableState();
9385                onHoverChanged(false);
9386            }
9387        }
9388    }
9389
9390    /**
9391     * Implement this method to handle hover state changes.
9392     * <p>
9393     * This method is called whenever the hover state changes as a result of a
9394     * call to {@link #setHovered}.
9395     * </p>
9396     *
9397     * @param hovered The current hover state, as returned by {@link #isHovered}.
9398     *
9399     * @see #isHovered
9400     * @see #setHovered
9401     */
9402    public void onHoverChanged(boolean hovered) {
9403    }
9404
9405    /**
9406     * Implement this method to handle touch screen motion events.
9407     * <p>
9408     * If this method is used to detect click actions, it is recommended that
9409     * the actions be performed by implementing and calling
9410     * {@link #performClick()}. This will ensure consistent system behavior,
9411     * including:
9412     * <ul>
9413     * <li>obeying click sound preferences
9414     * <li>dispatching OnClickListener calls
9415     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9416     * accessibility features are enabled
9417     * </ul>
9418     *
9419     * @param event The motion event.
9420     * @return True if the event was handled, false otherwise.
9421     */
9422    public boolean onTouchEvent(MotionEvent event) {
9423        final float x = event.getX();
9424        final float y = event.getY();
9425        final int viewFlags = mViewFlags;
9426
9427        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9428            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9429                setPressed(false);
9430            }
9431            // A disabled view that is clickable still consumes the touch
9432            // events, it just doesn't respond to them.
9433            return (((viewFlags & CLICKABLE) == CLICKABLE ||
9434                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9435        }
9436
9437        if (mTouchDelegate != null) {
9438            if (mTouchDelegate.onTouchEvent(event)) {
9439                return true;
9440            }
9441        }
9442
9443        if (((viewFlags & CLICKABLE) == CLICKABLE ||
9444                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9445            switch (event.getAction()) {
9446                case MotionEvent.ACTION_UP:
9447                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9448                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9449                        // take focus if we don't have it already and we should in
9450                        // touch mode.
9451                        boolean focusTaken = false;
9452                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9453                            focusTaken = requestFocus();
9454                        }
9455
9456                        if (prepressed) {
9457                            // The button is being released before we actually
9458                            // showed it as pressed.  Make it show the pressed
9459                            // state now (before scheduling the click) to ensure
9460                            // the user sees it.
9461                            setPressed(true, x, y);
9462                       }
9463
9464                        if (!mHasPerformedLongPress) {
9465                            // This is a tap, so remove the longpress check
9466                            removeLongPressCallback();
9467
9468                            // Only perform take click actions if we were in the pressed state
9469                            if (!focusTaken) {
9470                                // Use a Runnable and post this rather than calling
9471                                // performClick directly. This lets other visual state
9472                                // of the view update before click actions start.
9473                                if (mPerformClick == null) {
9474                                    mPerformClick = new PerformClick();
9475                                }
9476                                if (!post(mPerformClick)) {
9477                                    performClick();
9478                                }
9479                            }
9480                        }
9481
9482                        if (mUnsetPressedState == null) {
9483                            mUnsetPressedState = new UnsetPressedState();
9484                        }
9485
9486                        if (prepressed) {
9487                            postDelayed(mUnsetPressedState,
9488                                    ViewConfiguration.getPressedStateDuration());
9489                        } else if (!post(mUnsetPressedState)) {
9490                            // If the post failed, unpress right now
9491                            mUnsetPressedState.run();
9492                        }
9493
9494                        removeTapCallback();
9495                    }
9496                    break;
9497
9498                case MotionEvent.ACTION_DOWN:
9499                    mHasPerformedLongPress = false;
9500
9501                    if (performButtonActionOnTouchDown(event)) {
9502                        break;
9503                    }
9504
9505                    // Walk up the hierarchy to determine if we're inside a scrolling container.
9506                    boolean isInScrollingContainer = isInScrollingContainer();
9507
9508                    // For views inside a scrolling container, delay the pressed feedback for
9509                    // a short period in case this is a scroll.
9510                    if (isInScrollingContainer) {
9511                        mPrivateFlags |= PFLAG_PREPRESSED;
9512                        if (mPendingCheckForTap == null) {
9513                            mPendingCheckForTap = new CheckForTap();
9514                        }
9515                        mPendingCheckForTap.x = event.getX();
9516                        mPendingCheckForTap.y = event.getY();
9517                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9518                    } else {
9519                        // Not inside a scrolling container, so show the feedback right away
9520                        setPressed(true, x, y);
9521                        checkForLongClick(0);
9522                    }
9523                    break;
9524
9525                case MotionEvent.ACTION_CANCEL:
9526                    setPressed(false);
9527                    removeTapCallback();
9528                    removeLongPressCallback();
9529                    break;
9530
9531                case MotionEvent.ACTION_MOVE:
9532                    drawableHotspotChanged(x, y);
9533
9534                    // Be lenient about moving outside of buttons
9535                    if (!pointInView(x, y, mTouchSlop)) {
9536                        // Outside button
9537                        removeTapCallback();
9538                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9539                            // Remove any future long press/tap checks
9540                            removeLongPressCallback();
9541
9542                            setPressed(false);
9543                        }
9544                    }
9545                    break;
9546            }
9547
9548            return true;
9549        }
9550
9551        return false;
9552    }
9553
9554    /**
9555     * @hide
9556     */
9557    public boolean isInScrollingContainer() {
9558        ViewParent p = getParent();
9559        while (p != null && p instanceof ViewGroup) {
9560            if (((ViewGroup) p).shouldDelayChildPressedState()) {
9561                return true;
9562            }
9563            p = p.getParent();
9564        }
9565        return false;
9566    }
9567
9568    /**
9569     * Remove the longpress detection timer.
9570     */
9571    private void removeLongPressCallback() {
9572        if (mPendingCheckForLongPress != null) {
9573          removeCallbacks(mPendingCheckForLongPress);
9574        }
9575    }
9576
9577    /**
9578     * Remove the pending click action
9579     */
9580    private void removePerformClickCallback() {
9581        if (mPerformClick != null) {
9582            removeCallbacks(mPerformClick);
9583        }
9584    }
9585
9586    /**
9587     * Remove the prepress detection timer.
9588     */
9589    private void removeUnsetPressCallback() {
9590        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9591            setPressed(false);
9592            removeCallbacks(mUnsetPressedState);
9593        }
9594    }
9595
9596    /**
9597     * Remove the tap detection timer.
9598     */
9599    private void removeTapCallback() {
9600        if (mPendingCheckForTap != null) {
9601            mPrivateFlags &= ~PFLAG_PREPRESSED;
9602            removeCallbacks(mPendingCheckForTap);
9603        }
9604    }
9605
9606    /**
9607     * Cancels a pending long press.  Your subclass can use this if you
9608     * want the context menu to come up if the user presses and holds
9609     * at the same place, but you don't want it to come up if they press
9610     * and then move around enough to cause scrolling.
9611     */
9612    public void cancelLongPress() {
9613        removeLongPressCallback();
9614
9615        /*
9616         * The prepressed state handled by the tap callback is a display
9617         * construct, but the tap callback will post a long press callback
9618         * less its own timeout. Remove it here.
9619         */
9620        removeTapCallback();
9621    }
9622
9623    /**
9624     * Remove the pending callback for sending a
9625     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9626     */
9627    private void removeSendViewScrolledAccessibilityEventCallback() {
9628        if (mSendViewScrolledAccessibilityEvent != null) {
9629            removeCallbacks(mSendViewScrolledAccessibilityEvent);
9630            mSendViewScrolledAccessibilityEvent.mIsPending = false;
9631        }
9632    }
9633
9634    /**
9635     * Sets the TouchDelegate for this View.
9636     */
9637    public void setTouchDelegate(TouchDelegate delegate) {
9638        mTouchDelegate = delegate;
9639    }
9640
9641    /**
9642     * Gets the TouchDelegate for this View.
9643     */
9644    public TouchDelegate getTouchDelegate() {
9645        return mTouchDelegate;
9646    }
9647
9648    /**
9649     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9650     *
9651     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9652     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9653     * available. This method should only be called for touch events.
9654     *
9655     * <p class="note">This api is not intended for most applications. Buffered dispatch
9656     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9657     * streams will not improve your input latency. Side effects include: increased latency,
9658     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9659     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9660     * you.</p>
9661     */
9662    public final void requestUnbufferedDispatch(MotionEvent event) {
9663        final int action = event.getAction();
9664        if (mAttachInfo == null
9665                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9666                || !event.isTouchEvent()) {
9667            return;
9668        }
9669        mAttachInfo.mUnbufferedDispatchRequested = true;
9670    }
9671
9672    /**
9673     * Set flags controlling behavior of this view.
9674     *
9675     * @param flags Constant indicating the value which should be set
9676     * @param mask Constant indicating the bit range that should be changed
9677     */
9678    void setFlags(int flags, int mask) {
9679        final boolean accessibilityEnabled =
9680                AccessibilityManager.getInstance(mContext).isEnabled();
9681        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9682
9683        int old = mViewFlags;
9684        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9685
9686        int changed = mViewFlags ^ old;
9687        if (changed == 0) {
9688            return;
9689        }
9690        int privateFlags = mPrivateFlags;
9691
9692        /* Check if the FOCUSABLE bit has changed */
9693        if (((changed & FOCUSABLE_MASK) != 0) &&
9694                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9695            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9696                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9697                /* Give up focus if we are no longer focusable */
9698                clearFocus();
9699            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9700                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9701                /*
9702                 * Tell the view system that we are now available to take focus
9703                 * if no one else already has it.
9704                 */
9705                if (mParent != null) mParent.focusableViewAvailable(this);
9706            }
9707        }
9708
9709        final int newVisibility = flags & VISIBILITY_MASK;
9710        if (newVisibility == VISIBLE) {
9711            if ((changed & VISIBILITY_MASK) != 0) {
9712                /*
9713                 * If this view is becoming visible, invalidate it in case it changed while
9714                 * it was not visible. Marking it drawn ensures that the invalidation will
9715                 * go through.
9716                 */
9717                mPrivateFlags |= PFLAG_DRAWN;
9718                invalidate(true);
9719
9720                needGlobalAttributesUpdate(true);
9721
9722                // a view becoming visible is worth notifying the parent
9723                // about in case nothing has focus.  even if this specific view
9724                // isn't focusable, it may contain something that is, so let
9725                // the root view try to give this focus if nothing else does.
9726                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9727                    mParent.focusableViewAvailable(this);
9728                }
9729            }
9730        }
9731
9732        /* Check if the GONE bit has changed */
9733        if ((changed & GONE) != 0) {
9734            needGlobalAttributesUpdate(false);
9735            requestLayout();
9736
9737            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9738                if (hasFocus()) clearFocus();
9739                clearAccessibilityFocus();
9740                destroyDrawingCache();
9741                if (mParent instanceof View) {
9742                    // GONE views noop invalidation, so invalidate the parent
9743                    ((View) mParent).invalidate(true);
9744                }
9745                // Mark the view drawn to ensure that it gets invalidated properly the next
9746                // time it is visible and gets invalidated
9747                mPrivateFlags |= PFLAG_DRAWN;
9748            }
9749            if (mAttachInfo != null) {
9750                mAttachInfo.mViewVisibilityChanged = true;
9751            }
9752        }
9753
9754        /* Check if the VISIBLE bit has changed */
9755        if ((changed & INVISIBLE) != 0) {
9756            needGlobalAttributesUpdate(false);
9757            /*
9758             * If this view is becoming invisible, set the DRAWN flag so that
9759             * the next invalidate() will not be skipped.
9760             */
9761            mPrivateFlags |= PFLAG_DRAWN;
9762
9763            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9764                // root view becoming invisible shouldn't clear focus and accessibility focus
9765                if (getRootView() != this) {
9766                    if (hasFocus()) clearFocus();
9767                    clearAccessibilityFocus();
9768                }
9769            }
9770            if (mAttachInfo != null) {
9771                mAttachInfo.mViewVisibilityChanged = true;
9772            }
9773        }
9774
9775        if ((changed & VISIBILITY_MASK) != 0) {
9776            // If the view is invisible, cleanup its display list to free up resources
9777            if (newVisibility != VISIBLE && mAttachInfo != null) {
9778                cleanupDraw();
9779            }
9780
9781            if (mParent instanceof ViewGroup) {
9782                ((ViewGroup) mParent).onChildVisibilityChanged(this,
9783                        (changed & VISIBILITY_MASK), newVisibility);
9784                ((View) mParent).invalidate(true);
9785            } else if (mParent != null) {
9786                mParent.invalidateChild(this, null);
9787            }
9788            dispatchVisibilityChanged(this, newVisibility);
9789
9790            notifySubtreeAccessibilityStateChangedIfNeeded();
9791        }
9792
9793        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9794            destroyDrawingCache();
9795        }
9796
9797        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9798            destroyDrawingCache();
9799            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9800            invalidateParentCaches();
9801        }
9802
9803        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9804            destroyDrawingCache();
9805            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9806        }
9807
9808        if ((changed & DRAW_MASK) != 0) {
9809            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9810                if (mBackground != null) {
9811                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9812                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9813                } else {
9814                    mPrivateFlags |= PFLAG_SKIP_DRAW;
9815                }
9816            } else {
9817                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9818            }
9819            requestLayout();
9820            invalidate(true);
9821        }
9822
9823        if ((changed & KEEP_SCREEN_ON) != 0) {
9824            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9825                mParent.recomputeViewAttributes(this);
9826            }
9827        }
9828
9829        if (accessibilityEnabled) {
9830            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9831                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9832                if (oldIncludeForAccessibility != includeForAccessibility()) {
9833                    notifySubtreeAccessibilityStateChangedIfNeeded();
9834                } else {
9835                    notifyViewAccessibilityStateChangedIfNeeded(
9836                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9837                }
9838            } else if ((changed & ENABLED_MASK) != 0) {
9839                notifyViewAccessibilityStateChangedIfNeeded(
9840                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9841            }
9842        }
9843    }
9844
9845    /**
9846     * Change the view's z order in the tree, so it's on top of other sibling
9847     * views. This ordering change may affect layout, if the parent container
9848     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9849     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9850     * method should be followed by calls to {@link #requestLayout()} and
9851     * {@link View#invalidate()} on the view's parent to force the parent to redraw
9852     * with the new child ordering.
9853     *
9854     * @see ViewGroup#bringChildToFront(View)
9855     */
9856    public void bringToFront() {
9857        if (mParent != null) {
9858            mParent.bringChildToFront(this);
9859        }
9860    }
9861
9862    /**
9863     * This is called in response to an internal scroll in this view (i.e., the
9864     * view scrolled its own contents). This is typically as a result of
9865     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9866     * called.
9867     *
9868     * @param l Current horizontal scroll origin.
9869     * @param t Current vertical scroll origin.
9870     * @param oldl Previous horizontal scroll origin.
9871     * @param oldt Previous vertical scroll origin.
9872     */
9873    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9874        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9875            postSendViewScrolledAccessibilityEventCallback();
9876        }
9877
9878        mBackgroundSizeChanged = true;
9879
9880        final AttachInfo ai = mAttachInfo;
9881        if (ai != null) {
9882            ai.mViewScrollChanged = true;
9883        }
9884
9885        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
9886            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
9887        }
9888    }
9889
9890    /**
9891     * Interface definition for a callback to be invoked when the scroll
9892     * X or Y positions of a view change.
9893     * <p>
9894     * <b>Note:</b> Some views handle scrolling independently from View and may
9895     * have their own separate listeners for scroll-type events. For example,
9896     * {@link android.widget.ListView ListView} allows clients to register an
9897     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
9898     * to listen for changes in list scroll position.
9899     *
9900     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
9901     */
9902    public interface OnScrollChangeListener {
9903        /**
9904         * Called when the scroll position of a view changes.
9905         *
9906         * @param v The view whose scroll position has changed.
9907         * @param scrollX Current horizontal scroll origin.
9908         * @param scrollY Current vertical scroll origin.
9909         * @param oldScrollX Previous horizontal scroll origin.
9910         * @param oldScrollY Previous vertical scroll origin.
9911         */
9912        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
9913    }
9914
9915    /**
9916     * Interface definition for a callback to be invoked when the layout bounds of a view
9917     * changes due to layout processing.
9918     */
9919    public interface OnLayoutChangeListener {
9920        /**
9921         * Called when the layout bounds of a view changes due to layout processing.
9922         *
9923         * @param v The view whose bounds have changed.
9924         * @param left The new value of the view's left property.
9925         * @param top The new value of the view's top property.
9926         * @param right The new value of the view's right property.
9927         * @param bottom The new value of the view's bottom property.
9928         * @param oldLeft The previous value of the view's left property.
9929         * @param oldTop The previous value of the view's top property.
9930         * @param oldRight The previous value of the view's right property.
9931         * @param oldBottom The previous value of the view's bottom property.
9932         */
9933        void onLayoutChange(View v, int left, int top, int right, int bottom,
9934            int oldLeft, int oldTop, int oldRight, int oldBottom);
9935    }
9936
9937    /**
9938     * This is called during layout when the size of this view has changed. If
9939     * you were just added to the view hierarchy, you're called with the old
9940     * values of 0.
9941     *
9942     * @param w Current width of this view.
9943     * @param h Current height of this view.
9944     * @param oldw Old width of this view.
9945     * @param oldh Old height of this view.
9946     */
9947    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9948    }
9949
9950    /**
9951     * Called by draw to draw the child views. This may be overridden
9952     * by derived classes to gain control just before its children are drawn
9953     * (but after its own view has been drawn).
9954     * @param canvas the canvas on which to draw the view
9955     */
9956    protected void dispatchDraw(Canvas canvas) {
9957
9958    }
9959
9960    /**
9961     * Gets the parent of this view. Note that the parent is a
9962     * ViewParent and not necessarily a View.
9963     *
9964     * @return Parent of this view.
9965     */
9966    public final ViewParent getParent() {
9967        return mParent;
9968    }
9969
9970    /**
9971     * Set the horizontal scrolled position of your view. This will cause a call to
9972     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9973     * invalidated.
9974     * @param value the x position to scroll to
9975     */
9976    public void setScrollX(int value) {
9977        scrollTo(value, mScrollY);
9978    }
9979
9980    /**
9981     * Set the vertical scrolled position of your view. This will cause a call to
9982     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9983     * invalidated.
9984     * @param value the y position to scroll to
9985     */
9986    public void setScrollY(int value) {
9987        scrollTo(mScrollX, value);
9988    }
9989
9990    /**
9991     * Return the scrolled left position of this view. This is the left edge of
9992     * the displayed part of your view. You do not need to draw any pixels
9993     * farther left, since those are outside of the frame of your view on
9994     * screen.
9995     *
9996     * @return The left edge of the displayed part of your view, in pixels.
9997     */
9998    public final int getScrollX() {
9999        return mScrollX;
10000    }
10001
10002    /**
10003     * Return the scrolled top position of this view. This is the top edge of
10004     * the displayed part of your view. You do not need to draw any pixels above
10005     * it, since those are outside of the frame of your view on screen.
10006     *
10007     * @return The top edge of the displayed part of your view, in pixels.
10008     */
10009    public final int getScrollY() {
10010        return mScrollY;
10011    }
10012
10013    /**
10014     * Return the width of the your view.
10015     *
10016     * @return The width of your view, in pixels.
10017     */
10018    @ViewDebug.ExportedProperty(category = "layout")
10019    public final int getWidth() {
10020        return mRight - mLeft;
10021    }
10022
10023    /**
10024     * Return the height of your view.
10025     *
10026     * @return The height of your view, in pixels.
10027     */
10028    @ViewDebug.ExportedProperty(category = "layout")
10029    public final int getHeight() {
10030        return mBottom - mTop;
10031    }
10032
10033    /**
10034     * Return the visible drawing bounds of your view. Fills in the output
10035     * rectangle with the values from getScrollX(), getScrollY(),
10036     * getWidth(), and getHeight(). These bounds do not account for any
10037     * transformation properties currently set on the view, such as
10038     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10039     *
10040     * @param outRect The (scrolled) drawing bounds of the view.
10041     */
10042    public void getDrawingRect(Rect outRect) {
10043        outRect.left = mScrollX;
10044        outRect.top = mScrollY;
10045        outRect.right = mScrollX + (mRight - mLeft);
10046        outRect.bottom = mScrollY + (mBottom - mTop);
10047    }
10048
10049    /**
10050     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10051     * raw width component (that is the result is masked by
10052     * {@link #MEASURED_SIZE_MASK}).
10053     *
10054     * @return The raw measured width of this view.
10055     */
10056    public final int getMeasuredWidth() {
10057        return mMeasuredWidth & MEASURED_SIZE_MASK;
10058    }
10059
10060    /**
10061     * Return the full width measurement information for this view as computed
10062     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10063     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10064     * This should be used during measurement and layout calculations only. Use
10065     * {@link #getWidth()} to see how wide a view is after layout.
10066     *
10067     * @return The measured width of this view as a bit mask.
10068     */
10069    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10070            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10071                    name = "MEASURED_STATE_TOO_SMALL"),
10072    })
10073    public final int getMeasuredWidthAndState() {
10074        return mMeasuredWidth;
10075    }
10076
10077    /**
10078     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10079     * raw width component (that is the result is masked by
10080     * {@link #MEASURED_SIZE_MASK}).
10081     *
10082     * @return The raw measured height of this view.
10083     */
10084    public final int getMeasuredHeight() {
10085        return mMeasuredHeight & MEASURED_SIZE_MASK;
10086    }
10087
10088    /**
10089     * Return the full height measurement information for this view as computed
10090     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10091     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10092     * This should be used during measurement and layout calculations only. Use
10093     * {@link #getHeight()} to see how wide a view is after layout.
10094     *
10095     * @return The measured width of this view as a bit mask.
10096     */
10097    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10098            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10099                    name = "MEASURED_STATE_TOO_SMALL"),
10100    })
10101    public final int getMeasuredHeightAndState() {
10102        return mMeasuredHeight;
10103    }
10104
10105    /**
10106     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10107     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10108     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10109     * and the height component is at the shifted bits
10110     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10111     */
10112    public final int getMeasuredState() {
10113        return (mMeasuredWidth&MEASURED_STATE_MASK)
10114                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10115                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10116    }
10117
10118    /**
10119     * The transform matrix of this view, which is calculated based on the current
10120     * rotation, scale, and pivot properties.
10121     *
10122     * @see #getRotation()
10123     * @see #getScaleX()
10124     * @see #getScaleY()
10125     * @see #getPivotX()
10126     * @see #getPivotY()
10127     * @return The current transform matrix for the view
10128     */
10129    public Matrix getMatrix() {
10130        ensureTransformationInfo();
10131        final Matrix matrix = mTransformationInfo.mMatrix;
10132        mRenderNode.getMatrix(matrix);
10133        return matrix;
10134    }
10135
10136    /**
10137     * Returns true if the transform matrix is the identity matrix.
10138     * Recomputes the matrix if necessary.
10139     *
10140     * @return True if the transform matrix is the identity matrix, false otherwise.
10141     */
10142    final boolean hasIdentityMatrix() {
10143        return mRenderNode.hasIdentityMatrix();
10144    }
10145
10146    void ensureTransformationInfo() {
10147        if (mTransformationInfo == null) {
10148            mTransformationInfo = new TransformationInfo();
10149        }
10150    }
10151
10152   /**
10153     * Utility method to retrieve the inverse of the current mMatrix property.
10154     * We cache the matrix to avoid recalculating it when transform properties
10155     * have not changed.
10156     *
10157     * @return The inverse of the current matrix of this view.
10158     * @hide
10159     */
10160    public final Matrix getInverseMatrix() {
10161        ensureTransformationInfo();
10162        if (mTransformationInfo.mInverseMatrix == null) {
10163            mTransformationInfo.mInverseMatrix = new Matrix();
10164        }
10165        final Matrix matrix = mTransformationInfo.mInverseMatrix;
10166        mRenderNode.getInverseMatrix(matrix);
10167        return matrix;
10168    }
10169
10170    /**
10171     * Gets the distance along the Z axis from the camera to this view.
10172     *
10173     * @see #setCameraDistance(float)
10174     *
10175     * @return The distance along the Z axis.
10176     */
10177    public float getCameraDistance() {
10178        final float dpi = mResources.getDisplayMetrics().densityDpi;
10179        return -(mRenderNode.getCameraDistance() * dpi);
10180    }
10181
10182    /**
10183     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10184     * views are drawn) from the camera to this view. The camera's distance
10185     * affects 3D transformations, for instance rotations around the X and Y
10186     * axis. If the rotationX or rotationY properties are changed and this view is
10187     * large (more than half the size of the screen), it is recommended to always
10188     * use a camera distance that's greater than the height (X axis rotation) or
10189     * the width (Y axis rotation) of this view.</p>
10190     *
10191     * <p>The distance of the camera from the view plane can have an affect on the
10192     * perspective distortion of the view when it is rotated around the x or y axis.
10193     * For example, a large distance will result in a large viewing angle, and there
10194     * will not be much perspective distortion of the view as it rotates. A short
10195     * distance may cause much more perspective distortion upon rotation, and can
10196     * also result in some drawing artifacts if the rotated view ends up partially
10197     * behind the camera (which is why the recommendation is to use a distance at
10198     * least as far as the size of the view, if the view is to be rotated.)</p>
10199     *
10200     * <p>The distance is expressed in "depth pixels." The default distance depends
10201     * on the screen density. For instance, on a medium density display, the
10202     * default distance is 1280. On a high density display, the default distance
10203     * is 1920.</p>
10204     *
10205     * <p>If you want to specify a distance that leads to visually consistent
10206     * results across various densities, use the following formula:</p>
10207     * <pre>
10208     * float scale = context.getResources().getDisplayMetrics().density;
10209     * view.setCameraDistance(distance * scale);
10210     * </pre>
10211     *
10212     * <p>The density scale factor of a high density display is 1.5,
10213     * and 1920 = 1280 * 1.5.</p>
10214     *
10215     * @param distance The distance in "depth pixels", if negative the opposite
10216     *        value is used
10217     *
10218     * @see #setRotationX(float)
10219     * @see #setRotationY(float)
10220     */
10221    public void setCameraDistance(float distance) {
10222        final float dpi = mResources.getDisplayMetrics().densityDpi;
10223
10224        invalidateViewProperty(true, false);
10225        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10226        invalidateViewProperty(false, false);
10227
10228        invalidateParentIfNeededAndWasQuickRejected();
10229    }
10230
10231    /**
10232     * The degrees that the view is rotated around the pivot point.
10233     *
10234     * @see #setRotation(float)
10235     * @see #getPivotX()
10236     * @see #getPivotY()
10237     *
10238     * @return The degrees of rotation.
10239     */
10240    @ViewDebug.ExportedProperty(category = "drawing")
10241    public float getRotation() {
10242        return mRenderNode.getRotation();
10243    }
10244
10245    /**
10246     * Sets the degrees that the view is rotated around the pivot point. Increasing values
10247     * result in clockwise rotation.
10248     *
10249     * @param rotation The degrees of rotation.
10250     *
10251     * @see #getRotation()
10252     * @see #getPivotX()
10253     * @see #getPivotY()
10254     * @see #setRotationX(float)
10255     * @see #setRotationY(float)
10256     *
10257     * @attr ref android.R.styleable#View_rotation
10258     */
10259    public void setRotation(float rotation) {
10260        if (rotation != getRotation()) {
10261            // Double-invalidation is necessary to capture view's old and new areas
10262            invalidateViewProperty(true, false);
10263            mRenderNode.setRotation(rotation);
10264            invalidateViewProperty(false, true);
10265
10266            invalidateParentIfNeededAndWasQuickRejected();
10267            notifySubtreeAccessibilityStateChangedIfNeeded();
10268        }
10269    }
10270
10271    /**
10272     * The degrees that the view is rotated around the vertical axis through the pivot point.
10273     *
10274     * @see #getPivotX()
10275     * @see #getPivotY()
10276     * @see #setRotationY(float)
10277     *
10278     * @return The degrees of Y rotation.
10279     */
10280    @ViewDebug.ExportedProperty(category = "drawing")
10281    public float getRotationY() {
10282        return mRenderNode.getRotationY();
10283    }
10284
10285    /**
10286     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10287     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10288     * down the y axis.
10289     *
10290     * When rotating large views, it is recommended to adjust the camera distance
10291     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10292     *
10293     * @param rotationY The degrees of Y rotation.
10294     *
10295     * @see #getRotationY()
10296     * @see #getPivotX()
10297     * @see #getPivotY()
10298     * @see #setRotation(float)
10299     * @see #setRotationX(float)
10300     * @see #setCameraDistance(float)
10301     *
10302     * @attr ref android.R.styleable#View_rotationY
10303     */
10304    public void setRotationY(float rotationY) {
10305        if (rotationY != getRotationY()) {
10306            invalidateViewProperty(true, false);
10307            mRenderNode.setRotationY(rotationY);
10308            invalidateViewProperty(false, true);
10309
10310            invalidateParentIfNeededAndWasQuickRejected();
10311            notifySubtreeAccessibilityStateChangedIfNeeded();
10312        }
10313    }
10314
10315    /**
10316     * The degrees that the view is rotated around the horizontal axis through the pivot point.
10317     *
10318     * @see #getPivotX()
10319     * @see #getPivotY()
10320     * @see #setRotationX(float)
10321     *
10322     * @return The degrees of X rotation.
10323     */
10324    @ViewDebug.ExportedProperty(category = "drawing")
10325    public float getRotationX() {
10326        return mRenderNode.getRotationX();
10327    }
10328
10329    /**
10330     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10331     * Increasing values result in clockwise rotation from the viewpoint of looking down the
10332     * x axis.
10333     *
10334     * When rotating large views, it is recommended to adjust the camera distance
10335     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10336     *
10337     * @param rotationX The degrees of X rotation.
10338     *
10339     * @see #getRotationX()
10340     * @see #getPivotX()
10341     * @see #getPivotY()
10342     * @see #setRotation(float)
10343     * @see #setRotationY(float)
10344     * @see #setCameraDistance(float)
10345     *
10346     * @attr ref android.R.styleable#View_rotationX
10347     */
10348    public void setRotationX(float rotationX) {
10349        if (rotationX != getRotationX()) {
10350            invalidateViewProperty(true, false);
10351            mRenderNode.setRotationX(rotationX);
10352            invalidateViewProperty(false, true);
10353
10354            invalidateParentIfNeededAndWasQuickRejected();
10355            notifySubtreeAccessibilityStateChangedIfNeeded();
10356        }
10357    }
10358
10359    /**
10360     * The amount that the view is scaled in x around the pivot point, as a proportion of
10361     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10362     *
10363     * <p>By default, this is 1.0f.
10364     *
10365     * @see #getPivotX()
10366     * @see #getPivotY()
10367     * @return The scaling factor.
10368     */
10369    @ViewDebug.ExportedProperty(category = "drawing")
10370    public float getScaleX() {
10371        return mRenderNode.getScaleX();
10372    }
10373
10374    /**
10375     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10376     * the view's unscaled width. A value of 1 means that no scaling is applied.
10377     *
10378     * @param scaleX The scaling factor.
10379     * @see #getPivotX()
10380     * @see #getPivotY()
10381     *
10382     * @attr ref android.R.styleable#View_scaleX
10383     */
10384    public void setScaleX(float scaleX) {
10385        if (scaleX != getScaleX()) {
10386            invalidateViewProperty(true, false);
10387            mRenderNode.setScaleX(scaleX);
10388            invalidateViewProperty(false, true);
10389
10390            invalidateParentIfNeededAndWasQuickRejected();
10391            notifySubtreeAccessibilityStateChangedIfNeeded();
10392        }
10393    }
10394
10395    /**
10396     * The amount that the view is scaled in y around the pivot point, as a proportion of
10397     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10398     *
10399     * <p>By default, this is 1.0f.
10400     *
10401     * @see #getPivotX()
10402     * @see #getPivotY()
10403     * @return The scaling factor.
10404     */
10405    @ViewDebug.ExportedProperty(category = "drawing")
10406    public float getScaleY() {
10407        return mRenderNode.getScaleY();
10408    }
10409
10410    /**
10411     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10412     * the view's unscaled width. A value of 1 means that no scaling is applied.
10413     *
10414     * @param scaleY The scaling factor.
10415     * @see #getPivotX()
10416     * @see #getPivotY()
10417     *
10418     * @attr ref android.R.styleable#View_scaleY
10419     */
10420    public void setScaleY(float scaleY) {
10421        if (scaleY != getScaleY()) {
10422            invalidateViewProperty(true, false);
10423            mRenderNode.setScaleY(scaleY);
10424            invalidateViewProperty(false, true);
10425
10426            invalidateParentIfNeededAndWasQuickRejected();
10427            notifySubtreeAccessibilityStateChangedIfNeeded();
10428        }
10429    }
10430
10431    /**
10432     * The x location of the point around which the view is {@link #setRotation(float) rotated}
10433     * and {@link #setScaleX(float) scaled}.
10434     *
10435     * @see #getRotation()
10436     * @see #getScaleX()
10437     * @see #getScaleY()
10438     * @see #getPivotY()
10439     * @return The x location of the pivot point.
10440     *
10441     * @attr ref android.R.styleable#View_transformPivotX
10442     */
10443    @ViewDebug.ExportedProperty(category = "drawing")
10444    public float getPivotX() {
10445        return mRenderNode.getPivotX();
10446    }
10447
10448    /**
10449     * Sets the x location of the point around which the view is
10450     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10451     * By default, the pivot point is centered on the object.
10452     * Setting this property disables this behavior and causes the view to use only the
10453     * explicitly set pivotX and pivotY values.
10454     *
10455     * @param pivotX The x location of the pivot point.
10456     * @see #getRotation()
10457     * @see #getScaleX()
10458     * @see #getScaleY()
10459     * @see #getPivotY()
10460     *
10461     * @attr ref android.R.styleable#View_transformPivotX
10462     */
10463    public void setPivotX(float pivotX) {
10464        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10465            invalidateViewProperty(true, false);
10466            mRenderNode.setPivotX(pivotX);
10467            invalidateViewProperty(false, true);
10468
10469            invalidateParentIfNeededAndWasQuickRejected();
10470        }
10471    }
10472
10473    /**
10474     * The y location of the point around which the view is {@link #setRotation(float) rotated}
10475     * and {@link #setScaleY(float) scaled}.
10476     *
10477     * @see #getRotation()
10478     * @see #getScaleX()
10479     * @see #getScaleY()
10480     * @see #getPivotY()
10481     * @return The y location of the pivot point.
10482     *
10483     * @attr ref android.R.styleable#View_transformPivotY
10484     */
10485    @ViewDebug.ExportedProperty(category = "drawing")
10486    public float getPivotY() {
10487        return mRenderNode.getPivotY();
10488    }
10489
10490    /**
10491     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10492     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10493     * Setting this property disables this behavior and causes the view to use only the
10494     * explicitly set pivotX and pivotY values.
10495     *
10496     * @param pivotY The y location of the pivot point.
10497     * @see #getRotation()
10498     * @see #getScaleX()
10499     * @see #getScaleY()
10500     * @see #getPivotY()
10501     *
10502     * @attr ref android.R.styleable#View_transformPivotY
10503     */
10504    public void setPivotY(float pivotY) {
10505        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10506            invalidateViewProperty(true, false);
10507            mRenderNode.setPivotY(pivotY);
10508            invalidateViewProperty(false, true);
10509
10510            invalidateParentIfNeededAndWasQuickRejected();
10511        }
10512    }
10513
10514    /**
10515     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10516     * completely transparent and 1 means the view is completely opaque.
10517     *
10518     * <p>By default this is 1.0f.
10519     * @return The opacity of the view.
10520     */
10521    @ViewDebug.ExportedProperty(category = "drawing")
10522    public float getAlpha() {
10523        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10524    }
10525
10526    /**
10527     * Returns whether this View has content which overlaps.
10528     *
10529     * <p>This function, intended to be overridden by specific View types, is an optimization when
10530     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10531     * an offscreen buffer and then composited into place, which can be expensive. If the view has
10532     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10533     * directly. An example of overlapping rendering is a TextView with a background image, such as
10534     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10535     * ImageView with only the foreground image. The default implementation returns true; subclasses
10536     * should override if they have cases which can be optimized.</p>
10537     *
10538     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10539     * necessitates that a View return true if it uses the methods internally without passing the
10540     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10541     *
10542     * @return true if the content in this view might overlap, false otherwise.
10543     */
10544    @ViewDebug.ExportedProperty(category = "drawing")
10545    public boolean hasOverlappingRendering() {
10546        return true;
10547    }
10548
10549    /**
10550     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10551     * completely transparent and 1 means the view is completely opaque.</p>
10552     *
10553     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10554     * performance implications, especially for large views. It is best to use the alpha property
10555     * sparingly and transiently, as in the case of fading animations.</p>
10556     *
10557     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10558     * strongly recommended for performance reasons to either override
10559     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10560     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10561     *
10562     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10563     * responsible for applying the opacity itself.</p>
10564     *
10565     * <p>Note that if the view is backed by a
10566     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10567     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10568     * 1.0 will supersede the alpha of the layer paint.</p>
10569     *
10570     * @param alpha The opacity of the view.
10571     *
10572     * @see #hasOverlappingRendering()
10573     * @see #setLayerType(int, android.graphics.Paint)
10574     *
10575     * @attr ref android.R.styleable#View_alpha
10576     */
10577    public void setAlpha(float alpha) {
10578        ensureTransformationInfo();
10579        if (mTransformationInfo.mAlpha != alpha) {
10580            mTransformationInfo.mAlpha = alpha;
10581            if (onSetAlpha((int) (alpha * 255))) {
10582                mPrivateFlags |= PFLAG_ALPHA_SET;
10583                // subclass is handling alpha - don't optimize rendering cache invalidation
10584                invalidateParentCaches();
10585                invalidate(true);
10586            } else {
10587                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10588                invalidateViewProperty(true, false);
10589                mRenderNode.setAlpha(getFinalAlpha());
10590                notifyViewAccessibilityStateChangedIfNeeded(
10591                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10592            }
10593        }
10594    }
10595
10596    /**
10597     * Faster version of setAlpha() which performs the same steps except there are
10598     * no calls to invalidate(). The caller of this function should perform proper invalidation
10599     * on the parent and this object. The return value indicates whether the subclass handles
10600     * alpha (the return value for onSetAlpha()).
10601     *
10602     * @param alpha The new value for the alpha property
10603     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10604     *         the new value for the alpha property is different from the old value
10605     */
10606    boolean setAlphaNoInvalidation(float alpha) {
10607        ensureTransformationInfo();
10608        if (mTransformationInfo.mAlpha != alpha) {
10609            mTransformationInfo.mAlpha = alpha;
10610            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10611            if (subclassHandlesAlpha) {
10612                mPrivateFlags |= PFLAG_ALPHA_SET;
10613                return true;
10614            } else {
10615                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10616                mRenderNode.setAlpha(getFinalAlpha());
10617            }
10618        }
10619        return false;
10620    }
10621
10622    /**
10623     * This property is hidden and intended only for use by the Fade transition, which
10624     * animates it to produce a visual translucency that does not side-effect (or get
10625     * affected by) the real alpha property. This value is composited with the other
10626     * alpha value (and the AlphaAnimation value, when that is present) to produce
10627     * a final visual translucency result, which is what is passed into the DisplayList.
10628     *
10629     * @hide
10630     */
10631    public void setTransitionAlpha(float alpha) {
10632        ensureTransformationInfo();
10633        if (mTransformationInfo.mTransitionAlpha != alpha) {
10634            mTransformationInfo.mTransitionAlpha = alpha;
10635            mPrivateFlags &= ~PFLAG_ALPHA_SET;
10636            invalidateViewProperty(true, false);
10637            mRenderNode.setAlpha(getFinalAlpha());
10638        }
10639    }
10640
10641    /**
10642     * Calculates the visual alpha of this view, which is a combination of the actual
10643     * alpha value and the transitionAlpha value (if set).
10644     */
10645    private float getFinalAlpha() {
10646        if (mTransformationInfo != null) {
10647            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10648        }
10649        return 1;
10650    }
10651
10652    /**
10653     * This property is hidden and intended only for use by the Fade transition, which
10654     * animates it to produce a visual translucency that does not side-effect (or get
10655     * affected by) the real alpha property. This value is composited with the other
10656     * alpha value (and the AlphaAnimation value, when that is present) to produce
10657     * a final visual translucency result, which is what is passed into the DisplayList.
10658     *
10659     * @hide
10660     */
10661    @ViewDebug.ExportedProperty(category = "drawing")
10662    public float getTransitionAlpha() {
10663        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10664    }
10665
10666    /**
10667     * Top position of this view relative to its parent.
10668     *
10669     * @return The top of this view, in pixels.
10670     */
10671    @ViewDebug.CapturedViewProperty
10672    public final int getTop() {
10673        return mTop;
10674    }
10675
10676    /**
10677     * Sets the top position of this view relative to its parent. This method is meant to be called
10678     * by the layout system and should not generally be called otherwise, because the property
10679     * may be changed at any time by the layout.
10680     *
10681     * @param top The top of this view, in pixels.
10682     */
10683    public final void setTop(int top) {
10684        if (top != mTop) {
10685            final boolean matrixIsIdentity = hasIdentityMatrix();
10686            if (matrixIsIdentity) {
10687                if (mAttachInfo != null) {
10688                    int minTop;
10689                    int yLoc;
10690                    if (top < mTop) {
10691                        minTop = top;
10692                        yLoc = top - mTop;
10693                    } else {
10694                        minTop = mTop;
10695                        yLoc = 0;
10696                    }
10697                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10698                }
10699            } else {
10700                // Double-invalidation is necessary to capture view's old and new areas
10701                invalidate(true);
10702            }
10703
10704            int width = mRight - mLeft;
10705            int oldHeight = mBottom - mTop;
10706
10707            mTop = top;
10708            mRenderNode.setTop(mTop);
10709
10710            sizeChange(width, mBottom - mTop, width, oldHeight);
10711
10712            if (!matrixIsIdentity) {
10713                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10714                invalidate(true);
10715            }
10716            mBackgroundSizeChanged = true;
10717            invalidateParentIfNeeded();
10718            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10719                // View was rejected last time it was drawn by its parent; this may have changed
10720                invalidateParentIfNeeded();
10721            }
10722        }
10723    }
10724
10725    /**
10726     * Bottom position of this view relative to its parent.
10727     *
10728     * @return The bottom of this view, in pixels.
10729     */
10730    @ViewDebug.CapturedViewProperty
10731    public final int getBottom() {
10732        return mBottom;
10733    }
10734
10735    /**
10736     * True if this view has changed since the last time being drawn.
10737     *
10738     * @return The dirty state of this view.
10739     */
10740    public boolean isDirty() {
10741        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10742    }
10743
10744    /**
10745     * Sets the bottom position of this view relative to its parent. This method is meant to be
10746     * called by the layout system and should not generally be called otherwise, because the
10747     * property may be changed at any time by the layout.
10748     *
10749     * @param bottom The bottom of this view, in pixels.
10750     */
10751    public final void setBottom(int bottom) {
10752        if (bottom != mBottom) {
10753            final boolean matrixIsIdentity = hasIdentityMatrix();
10754            if (matrixIsIdentity) {
10755                if (mAttachInfo != null) {
10756                    int maxBottom;
10757                    if (bottom < mBottom) {
10758                        maxBottom = mBottom;
10759                    } else {
10760                        maxBottom = bottom;
10761                    }
10762                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10763                }
10764            } else {
10765                // Double-invalidation is necessary to capture view's old and new areas
10766                invalidate(true);
10767            }
10768
10769            int width = mRight - mLeft;
10770            int oldHeight = mBottom - mTop;
10771
10772            mBottom = bottom;
10773            mRenderNode.setBottom(mBottom);
10774
10775            sizeChange(width, mBottom - mTop, width, oldHeight);
10776
10777            if (!matrixIsIdentity) {
10778                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10779                invalidate(true);
10780            }
10781            mBackgroundSizeChanged = true;
10782            invalidateParentIfNeeded();
10783            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10784                // View was rejected last time it was drawn by its parent; this may have changed
10785                invalidateParentIfNeeded();
10786            }
10787        }
10788    }
10789
10790    /**
10791     * Left position of this view relative to its parent.
10792     *
10793     * @return The left edge of this view, in pixels.
10794     */
10795    @ViewDebug.CapturedViewProperty
10796    public final int getLeft() {
10797        return mLeft;
10798    }
10799
10800    /**
10801     * Sets the left position of this view relative to its parent. This method is meant to be called
10802     * by the layout system and should not generally be called otherwise, because the property
10803     * may be changed at any time by the layout.
10804     *
10805     * @param left The left of this view, in pixels.
10806     */
10807    public final void setLeft(int left) {
10808        if (left != mLeft) {
10809            final boolean matrixIsIdentity = hasIdentityMatrix();
10810            if (matrixIsIdentity) {
10811                if (mAttachInfo != null) {
10812                    int minLeft;
10813                    int xLoc;
10814                    if (left < mLeft) {
10815                        minLeft = left;
10816                        xLoc = left - mLeft;
10817                    } else {
10818                        minLeft = mLeft;
10819                        xLoc = 0;
10820                    }
10821                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10822                }
10823            } else {
10824                // Double-invalidation is necessary to capture view's old and new areas
10825                invalidate(true);
10826            }
10827
10828            int oldWidth = mRight - mLeft;
10829            int height = mBottom - mTop;
10830
10831            mLeft = left;
10832            mRenderNode.setLeft(left);
10833
10834            sizeChange(mRight - mLeft, height, oldWidth, height);
10835
10836            if (!matrixIsIdentity) {
10837                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10838                invalidate(true);
10839            }
10840            mBackgroundSizeChanged = true;
10841            invalidateParentIfNeeded();
10842            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10843                // View was rejected last time it was drawn by its parent; this may have changed
10844                invalidateParentIfNeeded();
10845            }
10846        }
10847    }
10848
10849    /**
10850     * Right position of this view relative to its parent.
10851     *
10852     * @return The right edge of this view, in pixels.
10853     */
10854    @ViewDebug.CapturedViewProperty
10855    public final int getRight() {
10856        return mRight;
10857    }
10858
10859    /**
10860     * Sets the right position of this view relative to its parent. This method is meant to be called
10861     * by the layout system and should not generally be called otherwise, because the property
10862     * may be changed at any time by the layout.
10863     *
10864     * @param right The right of this view, in pixels.
10865     */
10866    public final void setRight(int right) {
10867        if (right != mRight) {
10868            final boolean matrixIsIdentity = hasIdentityMatrix();
10869            if (matrixIsIdentity) {
10870                if (mAttachInfo != null) {
10871                    int maxRight;
10872                    if (right < mRight) {
10873                        maxRight = mRight;
10874                    } else {
10875                        maxRight = right;
10876                    }
10877                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10878                }
10879            } else {
10880                // Double-invalidation is necessary to capture view's old and new areas
10881                invalidate(true);
10882            }
10883
10884            int oldWidth = mRight - mLeft;
10885            int height = mBottom - mTop;
10886
10887            mRight = right;
10888            mRenderNode.setRight(mRight);
10889
10890            sizeChange(mRight - mLeft, height, oldWidth, height);
10891
10892            if (!matrixIsIdentity) {
10893                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10894                invalidate(true);
10895            }
10896            mBackgroundSizeChanged = true;
10897            invalidateParentIfNeeded();
10898            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10899                // View was rejected last time it was drawn by its parent; this may have changed
10900                invalidateParentIfNeeded();
10901            }
10902        }
10903    }
10904
10905    /**
10906     * The visual x position of this view, in pixels. This is equivalent to the
10907     * {@link #setTranslationX(float) translationX} property plus the current
10908     * {@link #getLeft() left} property.
10909     *
10910     * @return The visual x position of this view, in pixels.
10911     */
10912    @ViewDebug.ExportedProperty(category = "drawing")
10913    public float getX() {
10914        return mLeft + getTranslationX();
10915    }
10916
10917    /**
10918     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10919     * {@link #setTranslationX(float) translationX} property to be the difference between
10920     * the x value passed in and the current {@link #getLeft() left} property.
10921     *
10922     * @param x The visual x position of this view, in pixels.
10923     */
10924    public void setX(float x) {
10925        setTranslationX(x - mLeft);
10926    }
10927
10928    /**
10929     * The visual y position of this view, in pixels. This is equivalent to the
10930     * {@link #setTranslationY(float) translationY} property plus the current
10931     * {@link #getTop() top} property.
10932     *
10933     * @return The visual y position of this view, in pixels.
10934     */
10935    @ViewDebug.ExportedProperty(category = "drawing")
10936    public float getY() {
10937        return mTop + getTranslationY();
10938    }
10939
10940    /**
10941     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10942     * {@link #setTranslationY(float) translationY} property to be the difference between
10943     * the y value passed in and the current {@link #getTop() top} property.
10944     *
10945     * @param y The visual y position of this view, in pixels.
10946     */
10947    public void setY(float y) {
10948        setTranslationY(y - mTop);
10949    }
10950
10951    /**
10952     * The visual z position of this view, in pixels. This is equivalent to the
10953     * {@link #setTranslationZ(float) translationZ} property plus the current
10954     * {@link #getElevation() elevation} property.
10955     *
10956     * @return The visual z position of this view, in pixels.
10957     */
10958    @ViewDebug.ExportedProperty(category = "drawing")
10959    public float getZ() {
10960        return getElevation() + getTranslationZ();
10961    }
10962
10963    /**
10964     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
10965     * {@link #setTranslationZ(float) translationZ} property to be the difference between
10966     * the x value passed in and the current {@link #getElevation() elevation} property.
10967     *
10968     * @param z The visual z position of this view, in pixels.
10969     */
10970    public void setZ(float z) {
10971        setTranslationZ(z - getElevation());
10972    }
10973
10974    /**
10975     * The base elevation of this view relative to its parent, in pixels.
10976     *
10977     * @return The base depth position of the view, in pixels.
10978     */
10979    @ViewDebug.ExportedProperty(category = "drawing")
10980    public float getElevation() {
10981        return mRenderNode.getElevation();
10982    }
10983
10984    /**
10985     * Sets the base elevation of this view, in pixels.
10986     *
10987     * @attr ref android.R.styleable#View_elevation
10988     */
10989    public void setElevation(float elevation) {
10990        if (elevation != getElevation()) {
10991            invalidateViewProperty(true, false);
10992            mRenderNode.setElevation(elevation);
10993            invalidateViewProperty(false, true);
10994
10995            invalidateParentIfNeededAndWasQuickRejected();
10996        }
10997    }
10998
10999    /**
11000     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11001     * This position is post-layout, in addition to wherever the object's
11002     * layout placed it.
11003     *
11004     * @return The horizontal position of this view relative to its left position, in pixels.
11005     */
11006    @ViewDebug.ExportedProperty(category = "drawing")
11007    public float getTranslationX() {
11008        return mRenderNode.getTranslationX();
11009    }
11010
11011    /**
11012     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11013     * This effectively positions the object post-layout, in addition to wherever the object's
11014     * layout placed it.
11015     *
11016     * @param translationX The horizontal position of this view relative to its left position,
11017     * in pixels.
11018     *
11019     * @attr ref android.R.styleable#View_translationX
11020     */
11021    public void setTranslationX(float translationX) {
11022        if (translationX != getTranslationX()) {
11023            invalidateViewProperty(true, false);
11024            mRenderNode.setTranslationX(translationX);
11025            invalidateViewProperty(false, true);
11026
11027            invalidateParentIfNeededAndWasQuickRejected();
11028            notifySubtreeAccessibilityStateChangedIfNeeded();
11029        }
11030    }
11031
11032    /**
11033     * The vertical location of this view relative to its {@link #getTop() top} position.
11034     * This position is post-layout, in addition to wherever the object's
11035     * layout placed it.
11036     *
11037     * @return The vertical position of this view relative to its top position,
11038     * in pixels.
11039     */
11040    @ViewDebug.ExportedProperty(category = "drawing")
11041    public float getTranslationY() {
11042        return mRenderNode.getTranslationY();
11043    }
11044
11045    /**
11046     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11047     * This effectively positions the object post-layout, in addition to wherever the object's
11048     * layout placed it.
11049     *
11050     * @param translationY The vertical position of this view relative to its top position,
11051     * in pixels.
11052     *
11053     * @attr ref android.R.styleable#View_translationY
11054     */
11055    public void setTranslationY(float translationY) {
11056        if (translationY != getTranslationY()) {
11057            invalidateViewProperty(true, false);
11058            mRenderNode.setTranslationY(translationY);
11059            invalidateViewProperty(false, true);
11060
11061            invalidateParentIfNeededAndWasQuickRejected();
11062        }
11063    }
11064
11065    /**
11066     * The depth location of this view relative to its {@link #getElevation() elevation}.
11067     *
11068     * @return The depth of this view relative to its elevation.
11069     */
11070    @ViewDebug.ExportedProperty(category = "drawing")
11071    public float getTranslationZ() {
11072        return mRenderNode.getTranslationZ();
11073    }
11074
11075    /**
11076     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11077     *
11078     * @attr ref android.R.styleable#View_translationZ
11079     */
11080    public void setTranslationZ(float translationZ) {
11081        if (translationZ != getTranslationZ()) {
11082            invalidateViewProperty(true, false);
11083            mRenderNode.setTranslationZ(translationZ);
11084            invalidateViewProperty(false, true);
11085
11086            invalidateParentIfNeededAndWasQuickRejected();
11087        }
11088    }
11089
11090    /** @hide */
11091    public void setAnimationMatrix(Matrix matrix) {
11092        invalidateViewProperty(true, false);
11093        mRenderNode.setAnimationMatrix(matrix);
11094        invalidateViewProperty(false, true);
11095
11096        invalidateParentIfNeededAndWasQuickRejected();
11097    }
11098
11099    /**
11100     * Returns the current StateListAnimator if exists.
11101     *
11102     * @return StateListAnimator or null if it does not exists
11103     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11104     */
11105    public StateListAnimator getStateListAnimator() {
11106        return mStateListAnimator;
11107    }
11108
11109    /**
11110     * Attaches the provided StateListAnimator to this View.
11111     * <p>
11112     * Any previously attached StateListAnimator will be detached.
11113     *
11114     * @param stateListAnimator The StateListAnimator to update the view
11115     * @see {@link android.animation.StateListAnimator}
11116     */
11117    public void setStateListAnimator(StateListAnimator stateListAnimator) {
11118        if (mStateListAnimator == stateListAnimator) {
11119            return;
11120        }
11121        if (mStateListAnimator != null) {
11122            mStateListAnimator.setTarget(null);
11123        }
11124        mStateListAnimator = stateListAnimator;
11125        if (stateListAnimator != null) {
11126            stateListAnimator.setTarget(this);
11127            if (isAttachedToWindow()) {
11128                stateListAnimator.setState(getDrawableState());
11129            }
11130        }
11131    }
11132
11133    /**
11134     * Returns whether the Outline should be used to clip the contents of the View.
11135     * <p>
11136     * Note that this flag will only be respected if the View's Outline returns true from
11137     * {@link Outline#canClip()}.
11138     *
11139     * @see #setOutlineProvider(ViewOutlineProvider)
11140     * @see #setClipToOutline(boolean)
11141     */
11142    public final boolean getClipToOutline() {
11143        return mRenderNode.getClipToOutline();
11144    }
11145
11146    /**
11147     * Sets whether the View's Outline should be used to clip the contents of the View.
11148     * <p>
11149     * Only a single non-rectangular clip can be applied on a View at any time.
11150     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11151     * circular reveal} animation take priority over Outline clipping, and
11152     * child Outline clipping takes priority over Outline clipping done by a
11153     * parent.
11154     * <p>
11155     * Note that this flag will only be respected if the View's Outline returns true from
11156     * {@link Outline#canClip()}.
11157     *
11158     * @see #setOutlineProvider(ViewOutlineProvider)
11159     * @see #getClipToOutline()
11160     */
11161    public void setClipToOutline(boolean clipToOutline) {
11162        damageInParent();
11163        if (getClipToOutline() != clipToOutline) {
11164            mRenderNode.setClipToOutline(clipToOutline);
11165        }
11166    }
11167
11168    // correspond to the enum values of View_outlineProvider
11169    private static final int PROVIDER_BACKGROUND = 0;
11170    private static final int PROVIDER_NONE = 1;
11171    private static final int PROVIDER_BOUNDS = 2;
11172    private static final int PROVIDER_PADDED_BOUNDS = 3;
11173    private void setOutlineProviderFromAttribute(int providerInt) {
11174        switch (providerInt) {
11175            case PROVIDER_BACKGROUND:
11176                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11177                break;
11178            case PROVIDER_NONE:
11179                setOutlineProvider(null);
11180                break;
11181            case PROVIDER_BOUNDS:
11182                setOutlineProvider(ViewOutlineProvider.BOUNDS);
11183                break;
11184            case PROVIDER_PADDED_BOUNDS:
11185                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11186                break;
11187        }
11188    }
11189
11190    /**
11191     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11192     * the shape of the shadow it casts, and enables outline clipping.
11193     * <p>
11194     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11195     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11196     * outline provider with this method allows this behavior to be overridden.
11197     * <p>
11198     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11199     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11200     * <p>
11201     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11202     *
11203     * @see #setClipToOutline(boolean)
11204     * @see #getClipToOutline()
11205     * @see #getOutlineProvider()
11206     */
11207    public void setOutlineProvider(ViewOutlineProvider provider) {
11208        mOutlineProvider = provider;
11209        invalidateOutline();
11210    }
11211
11212    /**
11213     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11214     * that defines the shape of the shadow it casts, and enables outline clipping.
11215     *
11216     * @see #setOutlineProvider(ViewOutlineProvider)
11217     */
11218    public ViewOutlineProvider getOutlineProvider() {
11219        return mOutlineProvider;
11220    }
11221
11222    /**
11223     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11224     *
11225     * @see #setOutlineProvider(ViewOutlineProvider)
11226     */
11227    public void invalidateOutline() {
11228        rebuildOutline();
11229
11230        notifySubtreeAccessibilityStateChangedIfNeeded();
11231        invalidateViewProperty(false, false);
11232    }
11233
11234    /**
11235     * Internal version of {@link #invalidateOutline()} which invalidates the
11236     * outline without invalidating the view itself. This is intended to be called from
11237     * within methods in the View class itself which are the result of the view being
11238     * invalidated already. For example, when we are drawing the background of a View,
11239     * we invalidate the outline in case it changed in the meantime, but we do not
11240     * need to invalidate the view because we're already drawing the background as part
11241     * of drawing the view in response to an earlier invalidation of the view.
11242     */
11243    private void rebuildOutline() {
11244        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11245        if (mAttachInfo == null) return;
11246
11247        if (mOutlineProvider == null) {
11248            // no provider, remove outline
11249            mRenderNode.setOutline(null);
11250        } else {
11251            final Outline outline = mAttachInfo.mTmpOutline;
11252            outline.setEmpty();
11253            outline.setAlpha(1.0f);
11254
11255            mOutlineProvider.getOutline(this, outline);
11256            mRenderNode.setOutline(outline);
11257        }
11258    }
11259
11260    /**
11261     * HierarchyViewer only
11262     *
11263     * @hide
11264     */
11265    @ViewDebug.ExportedProperty(category = "drawing")
11266    public boolean hasShadow() {
11267        return mRenderNode.hasShadow();
11268    }
11269
11270
11271    /** @hide */
11272    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11273        mRenderNode.setRevealClip(shouldClip, x, y, radius);
11274        invalidateViewProperty(false, false);
11275    }
11276
11277    /**
11278     * Hit rectangle in parent's coordinates
11279     *
11280     * @param outRect The hit rectangle of the view.
11281     */
11282    public void getHitRect(Rect outRect) {
11283        if (hasIdentityMatrix() || mAttachInfo == null) {
11284            outRect.set(mLeft, mTop, mRight, mBottom);
11285        } else {
11286            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11287            tmpRect.set(0, 0, getWidth(), getHeight());
11288            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11289            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11290                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11291        }
11292    }
11293
11294    /**
11295     * Determines whether the given point, in local coordinates is inside the view.
11296     */
11297    /*package*/ final boolean pointInView(float localX, float localY) {
11298        return localX >= 0 && localX < (mRight - mLeft)
11299                && localY >= 0 && localY < (mBottom - mTop);
11300    }
11301
11302    /**
11303     * Utility method to determine whether the given point, in local coordinates,
11304     * is inside the view, where the area of the view is expanded by the slop factor.
11305     * This method is called while processing touch-move events to determine if the event
11306     * is still within the view.
11307     *
11308     * @hide
11309     */
11310    public boolean pointInView(float localX, float localY, float slop) {
11311        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11312                localY < ((mBottom - mTop) + slop);
11313    }
11314
11315    /**
11316     * When a view has focus and the user navigates away from it, the next view is searched for
11317     * starting from the rectangle filled in by this method.
11318     *
11319     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11320     * of the view.  However, if your view maintains some idea of internal selection,
11321     * such as a cursor, or a selected row or column, you should override this method and
11322     * fill in a more specific rectangle.
11323     *
11324     * @param r The rectangle to fill in, in this view's coordinates.
11325     */
11326    public void getFocusedRect(Rect r) {
11327        getDrawingRect(r);
11328    }
11329
11330    /**
11331     * If some part of this view is not clipped by any of its parents, then
11332     * return that area in r in global (root) coordinates. To convert r to local
11333     * coordinates (without taking possible View rotations into account), offset
11334     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11335     * If the view is completely clipped or translated out, return false.
11336     *
11337     * @param r If true is returned, r holds the global coordinates of the
11338     *        visible portion of this view.
11339     * @param globalOffset If true is returned, globalOffset holds the dx,dy
11340     *        between this view and its root. globalOffet may be null.
11341     * @return true if r is non-empty (i.e. part of the view is visible at the
11342     *         root level.
11343     */
11344    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11345        int width = mRight - mLeft;
11346        int height = mBottom - mTop;
11347        if (width > 0 && height > 0) {
11348            r.set(0, 0, width, height);
11349            if (globalOffset != null) {
11350                globalOffset.set(-mScrollX, -mScrollY);
11351            }
11352            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11353        }
11354        return false;
11355    }
11356
11357    public final boolean getGlobalVisibleRect(Rect r) {
11358        return getGlobalVisibleRect(r, null);
11359    }
11360
11361    public final boolean getLocalVisibleRect(Rect r) {
11362        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11363        if (getGlobalVisibleRect(r, offset)) {
11364            r.offset(-offset.x, -offset.y); // make r local
11365            return true;
11366        }
11367        return false;
11368    }
11369
11370    /**
11371     * Offset this view's vertical location by the specified number of pixels.
11372     *
11373     * @param offset the number of pixels to offset the view by
11374     */
11375    public void offsetTopAndBottom(int offset) {
11376        if (offset != 0) {
11377            final boolean matrixIsIdentity = hasIdentityMatrix();
11378            if (matrixIsIdentity) {
11379                if (isHardwareAccelerated()) {
11380                    invalidateViewProperty(false, false);
11381                } else {
11382                    final ViewParent p = mParent;
11383                    if (p != null && mAttachInfo != null) {
11384                        final Rect r = mAttachInfo.mTmpInvalRect;
11385                        int minTop;
11386                        int maxBottom;
11387                        int yLoc;
11388                        if (offset < 0) {
11389                            minTop = mTop + offset;
11390                            maxBottom = mBottom;
11391                            yLoc = offset;
11392                        } else {
11393                            minTop = mTop;
11394                            maxBottom = mBottom + offset;
11395                            yLoc = 0;
11396                        }
11397                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11398                        p.invalidateChild(this, r);
11399                    }
11400                }
11401            } else {
11402                invalidateViewProperty(false, false);
11403            }
11404
11405            mTop += offset;
11406            mBottom += offset;
11407            mRenderNode.offsetTopAndBottom(offset);
11408            if (isHardwareAccelerated()) {
11409                invalidateViewProperty(false, false);
11410            } else {
11411                if (!matrixIsIdentity) {
11412                    invalidateViewProperty(false, true);
11413                }
11414                invalidateParentIfNeeded();
11415            }
11416            notifySubtreeAccessibilityStateChangedIfNeeded();
11417        }
11418    }
11419
11420    /**
11421     * Offset this view's horizontal location by the specified amount of pixels.
11422     *
11423     * @param offset the number of pixels to offset the view by
11424     */
11425    public void offsetLeftAndRight(int offset) {
11426        if (offset != 0) {
11427            final boolean matrixIsIdentity = hasIdentityMatrix();
11428            if (matrixIsIdentity) {
11429                if (isHardwareAccelerated()) {
11430                    invalidateViewProperty(false, false);
11431                } else {
11432                    final ViewParent p = mParent;
11433                    if (p != null && mAttachInfo != null) {
11434                        final Rect r = mAttachInfo.mTmpInvalRect;
11435                        int minLeft;
11436                        int maxRight;
11437                        if (offset < 0) {
11438                            minLeft = mLeft + offset;
11439                            maxRight = mRight;
11440                        } else {
11441                            minLeft = mLeft;
11442                            maxRight = mRight + offset;
11443                        }
11444                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11445                        p.invalidateChild(this, r);
11446                    }
11447                }
11448            } else {
11449                invalidateViewProperty(false, false);
11450            }
11451
11452            mLeft += offset;
11453            mRight += offset;
11454            mRenderNode.offsetLeftAndRight(offset);
11455            if (isHardwareAccelerated()) {
11456                invalidateViewProperty(false, false);
11457            } else {
11458                if (!matrixIsIdentity) {
11459                    invalidateViewProperty(false, true);
11460                }
11461                invalidateParentIfNeeded();
11462            }
11463            notifySubtreeAccessibilityStateChangedIfNeeded();
11464        }
11465    }
11466
11467    /**
11468     * Get the LayoutParams associated with this view. All views should have
11469     * layout parameters. These supply parameters to the <i>parent</i> of this
11470     * view specifying how it should be arranged. There are many subclasses of
11471     * ViewGroup.LayoutParams, and these correspond to the different subclasses
11472     * of ViewGroup that are responsible for arranging their children.
11473     *
11474     * This method may return null if this View is not attached to a parent
11475     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11476     * was not invoked successfully. When a View is attached to a parent
11477     * ViewGroup, this method must not return null.
11478     *
11479     * @return The LayoutParams associated with this view, or null if no
11480     *         parameters have been set yet
11481     */
11482    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11483    public ViewGroup.LayoutParams getLayoutParams() {
11484        return mLayoutParams;
11485    }
11486
11487    /**
11488     * Set the layout parameters associated with this view. These supply
11489     * parameters to the <i>parent</i> of this view specifying how it should be
11490     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11491     * correspond to the different subclasses of ViewGroup that are responsible
11492     * for arranging their children.
11493     *
11494     * @param params The layout parameters for this view, cannot be null
11495     */
11496    public void setLayoutParams(ViewGroup.LayoutParams params) {
11497        if (params == null) {
11498            throw new NullPointerException("Layout parameters cannot be null");
11499        }
11500        mLayoutParams = params;
11501        resolveLayoutParams();
11502        if (mParent instanceof ViewGroup) {
11503            ((ViewGroup) mParent).onSetLayoutParams(this, params);
11504        }
11505        requestLayout();
11506    }
11507
11508    /**
11509     * Resolve the layout parameters depending on the resolved layout direction
11510     *
11511     * @hide
11512     */
11513    public void resolveLayoutParams() {
11514        if (mLayoutParams != null) {
11515            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11516        }
11517    }
11518
11519    /**
11520     * Set the scrolled position of your view. This will cause a call to
11521     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11522     * invalidated.
11523     * @param x the x position to scroll to
11524     * @param y the y position to scroll to
11525     */
11526    public void scrollTo(int x, int y) {
11527        if (mScrollX != x || mScrollY != y) {
11528            int oldX = mScrollX;
11529            int oldY = mScrollY;
11530            mScrollX = x;
11531            mScrollY = y;
11532            invalidateParentCaches();
11533            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11534            if (!awakenScrollBars()) {
11535                postInvalidateOnAnimation();
11536            }
11537        }
11538    }
11539
11540    /**
11541     * Move the scrolled position of your view. This will cause a call to
11542     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11543     * invalidated.
11544     * @param x the amount of pixels to scroll by horizontally
11545     * @param y the amount of pixels to scroll by vertically
11546     */
11547    public void scrollBy(int x, int y) {
11548        scrollTo(mScrollX + x, mScrollY + y);
11549    }
11550
11551    /**
11552     * <p>Trigger the scrollbars to draw. When invoked this method starts an
11553     * animation to fade the scrollbars out after a default delay. If a subclass
11554     * provides animated scrolling, the start delay should equal the duration
11555     * of the scrolling animation.</p>
11556     *
11557     * <p>The animation starts only if at least one of the scrollbars is
11558     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11559     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11560     * this method returns true, and false otherwise. If the animation is
11561     * started, this method calls {@link #invalidate()}; in that case the
11562     * caller should not call {@link #invalidate()}.</p>
11563     *
11564     * <p>This method should be invoked every time a subclass directly updates
11565     * the scroll parameters.</p>
11566     *
11567     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11568     * and {@link #scrollTo(int, int)}.</p>
11569     *
11570     * @return true if the animation is played, false otherwise
11571     *
11572     * @see #awakenScrollBars(int)
11573     * @see #scrollBy(int, int)
11574     * @see #scrollTo(int, int)
11575     * @see #isHorizontalScrollBarEnabled()
11576     * @see #isVerticalScrollBarEnabled()
11577     * @see #setHorizontalScrollBarEnabled(boolean)
11578     * @see #setVerticalScrollBarEnabled(boolean)
11579     */
11580    protected boolean awakenScrollBars() {
11581        return mScrollCache != null &&
11582                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11583    }
11584
11585    /**
11586     * Trigger the scrollbars to draw.
11587     * This method differs from awakenScrollBars() only in its default duration.
11588     * initialAwakenScrollBars() will show the scroll bars for longer than
11589     * usual to give the user more of a chance to notice them.
11590     *
11591     * @return true if the animation is played, false otherwise.
11592     */
11593    private boolean initialAwakenScrollBars() {
11594        return mScrollCache != null &&
11595                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11596    }
11597
11598    /**
11599     * <p>
11600     * Trigger the scrollbars to draw. When invoked this method starts an
11601     * animation to fade the scrollbars out after a fixed delay. If a subclass
11602     * provides animated scrolling, the start delay should equal the duration of
11603     * the scrolling animation.
11604     * </p>
11605     *
11606     * <p>
11607     * The animation starts only if at least one of the scrollbars is enabled,
11608     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11609     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11610     * this method returns true, and false otherwise. If the animation is
11611     * started, this method calls {@link #invalidate()}; in that case the caller
11612     * should not call {@link #invalidate()}.
11613     * </p>
11614     *
11615     * <p>
11616     * This method should be invoked every time a subclass directly updates the
11617     * scroll parameters.
11618     * </p>
11619     *
11620     * @param startDelay the delay, in milliseconds, after which the animation
11621     *        should start; when the delay is 0, the animation starts
11622     *        immediately
11623     * @return true if the animation is played, false otherwise
11624     *
11625     * @see #scrollBy(int, int)
11626     * @see #scrollTo(int, int)
11627     * @see #isHorizontalScrollBarEnabled()
11628     * @see #isVerticalScrollBarEnabled()
11629     * @see #setHorizontalScrollBarEnabled(boolean)
11630     * @see #setVerticalScrollBarEnabled(boolean)
11631     */
11632    protected boolean awakenScrollBars(int startDelay) {
11633        return awakenScrollBars(startDelay, true);
11634    }
11635
11636    /**
11637     * <p>
11638     * Trigger the scrollbars to draw. When invoked this method starts an
11639     * animation to fade the scrollbars out after a fixed delay. If a subclass
11640     * provides animated scrolling, the start delay should equal the duration of
11641     * the scrolling animation.
11642     * </p>
11643     *
11644     * <p>
11645     * The animation starts only if at least one of the scrollbars is enabled,
11646     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11647     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11648     * this method returns true, and false otherwise. If the animation is
11649     * started, this method calls {@link #invalidate()} if the invalidate parameter
11650     * is set to true; in that case the caller
11651     * should not call {@link #invalidate()}.
11652     * </p>
11653     *
11654     * <p>
11655     * This method should be invoked every time a subclass directly updates the
11656     * scroll parameters.
11657     * </p>
11658     *
11659     * @param startDelay the delay, in milliseconds, after which the animation
11660     *        should start; when the delay is 0, the animation starts
11661     *        immediately
11662     *
11663     * @param invalidate Whether this method should call invalidate
11664     *
11665     * @return true if the animation is played, false otherwise
11666     *
11667     * @see #scrollBy(int, int)
11668     * @see #scrollTo(int, int)
11669     * @see #isHorizontalScrollBarEnabled()
11670     * @see #isVerticalScrollBarEnabled()
11671     * @see #setHorizontalScrollBarEnabled(boolean)
11672     * @see #setVerticalScrollBarEnabled(boolean)
11673     */
11674    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11675        final ScrollabilityCache scrollCache = mScrollCache;
11676
11677        if (scrollCache == null || !scrollCache.fadeScrollBars) {
11678            return false;
11679        }
11680
11681        if (scrollCache.scrollBar == null) {
11682            scrollCache.scrollBar = new ScrollBarDrawable();
11683            scrollCache.scrollBar.setCallback(this);
11684            scrollCache.scrollBar.setState(getDrawableState());
11685        }
11686
11687        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11688
11689            if (invalidate) {
11690                // Invalidate to show the scrollbars
11691                postInvalidateOnAnimation();
11692            }
11693
11694            if (scrollCache.state == ScrollabilityCache.OFF) {
11695                // FIXME: this is copied from WindowManagerService.
11696                // We should get this value from the system when it
11697                // is possible to do so.
11698                final int KEY_REPEAT_FIRST_DELAY = 750;
11699                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11700            }
11701
11702            // Tell mScrollCache when we should start fading. This may
11703            // extend the fade start time if one was already scheduled
11704            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11705            scrollCache.fadeStartTime = fadeStartTime;
11706            scrollCache.state = ScrollabilityCache.ON;
11707
11708            // Schedule our fader to run, unscheduling any old ones first
11709            if (mAttachInfo != null) {
11710                mAttachInfo.mHandler.removeCallbacks(scrollCache);
11711                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11712            }
11713
11714            return true;
11715        }
11716
11717        return false;
11718    }
11719
11720    /**
11721     * Do not invalidate views which are not visible and which are not running an animation. They
11722     * will not get drawn and they should not set dirty flags as if they will be drawn
11723     */
11724    private boolean skipInvalidate() {
11725        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11726                (!(mParent instanceof ViewGroup) ||
11727                        !((ViewGroup) mParent).isViewTransitioning(this));
11728    }
11729
11730    /**
11731     * Mark the area defined by dirty as needing to be drawn. If the view is
11732     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11733     * point in the future.
11734     * <p>
11735     * This must be called from a UI thread. To call from a non-UI thread, call
11736     * {@link #postInvalidate()}.
11737     * <p>
11738     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11739     * {@code dirty}.
11740     *
11741     * @param dirty the rectangle representing the bounds of the dirty region
11742     */
11743    public void invalidate(Rect dirty) {
11744        final int scrollX = mScrollX;
11745        final int scrollY = mScrollY;
11746        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11747                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11748    }
11749
11750    /**
11751     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11752     * coordinates of the dirty rect are relative to the view. If the view is
11753     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11754     * point in the future.
11755     * <p>
11756     * This must be called from a UI thread. To call from a non-UI thread, call
11757     * {@link #postInvalidate()}.
11758     *
11759     * @param l the left position of the dirty region
11760     * @param t the top position of the dirty region
11761     * @param r the right position of the dirty region
11762     * @param b the bottom position of the dirty region
11763     */
11764    public void invalidate(int l, int t, int r, int b) {
11765        final int scrollX = mScrollX;
11766        final int scrollY = mScrollY;
11767        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11768    }
11769
11770    /**
11771     * Invalidate the whole view. If the view is visible,
11772     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11773     * the future.
11774     * <p>
11775     * This must be called from a UI thread. To call from a non-UI thread, call
11776     * {@link #postInvalidate()}.
11777     */
11778    public void invalidate() {
11779        invalidate(true);
11780    }
11781
11782    /**
11783     * This is where the invalidate() work actually happens. A full invalidate()
11784     * causes the drawing cache to be invalidated, but this function can be
11785     * called with invalidateCache set to false to skip that invalidation step
11786     * for cases that do not need it (for example, a component that remains at
11787     * the same dimensions with the same content).
11788     *
11789     * @param invalidateCache Whether the drawing cache for this view should be
11790     *            invalidated as well. This is usually true for a full
11791     *            invalidate, but may be set to false if the View's contents or
11792     *            dimensions have not changed.
11793     */
11794    void invalidate(boolean invalidateCache) {
11795        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11796    }
11797
11798    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11799            boolean fullInvalidate) {
11800        if (mGhostView != null) {
11801            mGhostView.invalidate(true);
11802            return;
11803        }
11804
11805        if (skipInvalidate()) {
11806            return;
11807        }
11808
11809        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11810                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11811                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11812                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11813            if (fullInvalidate) {
11814                mLastIsOpaque = isOpaque();
11815                mPrivateFlags &= ~PFLAG_DRAWN;
11816            }
11817
11818            mPrivateFlags |= PFLAG_DIRTY;
11819
11820            if (invalidateCache) {
11821                mPrivateFlags |= PFLAG_INVALIDATED;
11822                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11823            }
11824
11825            // Propagate the damage rectangle to the parent view.
11826            final AttachInfo ai = mAttachInfo;
11827            final ViewParent p = mParent;
11828            if (p != null && ai != null && l < r && t < b) {
11829                final Rect damage = ai.mTmpInvalRect;
11830                damage.set(l, t, r, b);
11831                p.invalidateChild(this, damage);
11832            }
11833
11834            // Damage the entire projection receiver, if necessary.
11835            if (mBackground != null && mBackground.isProjected()) {
11836                final View receiver = getProjectionReceiver();
11837                if (receiver != null) {
11838                    receiver.damageInParent();
11839                }
11840            }
11841
11842            // Damage the entire IsolatedZVolume receiving this view's shadow.
11843            if (isHardwareAccelerated() && getZ() != 0) {
11844                damageShadowReceiver();
11845            }
11846        }
11847    }
11848
11849    /**
11850     * @return this view's projection receiver, or {@code null} if none exists
11851     */
11852    private View getProjectionReceiver() {
11853        ViewParent p = getParent();
11854        while (p != null && p instanceof View) {
11855            final View v = (View) p;
11856            if (v.isProjectionReceiver()) {
11857                return v;
11858            }
11859            p = p.getParent();
11860        }
11861
11862        return null;
11863    }
11864
11865    /**
11866     * @return whether the view is a projection receiver
11867     */
11868    private boolean isProjectionReceiver() {
11869        return mBackground != null;
11870    }
11871
11872    /**
11873     * Damage area of the screen that can be covered by this View's shadow.
11874     *
11875     * This method will guarantee that any changes to shadows cast by a View
11876     * are damaged on the screen for future redraw.
11877     */
11878    private void damageShadowReceiver() {
11879        final AttachInfo ai = mAttachInfo;
11880        if (ai != null) {
11881            ViewParent p = getParent();
11882            if (p != null && p instanceof ViewGroup) {
11883                final ViewGroup vg = (ViewGroup) p;
11884                vg.damageInParent();
11885            }
11886        }
11887    }
11888
11889    /**
11890     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11891     * set any flags or handle all of the cases handled by the default invalidation methods.
11892     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11893     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11894     * walk up the hierarchy, transforming the dirty rect as necessary.
11895     *
11896     * The method also handles normal invalidation logic if display list properties are not
11897     * being used in this view. The invalidateParent and forceRedraw flags are used by that
11898     * backup approach, to handle these cases used in the various property-setting methods.
11899     *
11900     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11901     * are not being used in this view
11902     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11903     * list properties are not being used in this view
11904     */
11905    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11906        if (!isHardwareAccelerated()
11907                || !mRenderNode.isValid()
11908                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11909            if (invalidateParent) {
11910                invalidateParentCaches();
11911            }
11912            if (forceRedraw) {
11913                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11914            }
11915            invalidate(false);
11916        } else {
11917            damageInParent();
11918        }
11919        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
11920            damageShadowReceiver();
11921        }
11922    }
11923
11924    /**
11925     * Tells the parent view to damage this view's bounds.
11926     *
11927     * @hide
11928     */
11929    protected void damageInParent() {
11930        final AttachInfo ai = mAttachInfo;
11931        final ViewParent p = mParent;
11932        if (p != null && ai != null) {
11933            final Rect r = ai.mTmpInvalRect;
11934            r.set(0, 0, mRight - mLeft, mBottom - mTop);
11935            if (mParent instanceof ViewGroup) {
11936                ((ViewGroup) mParent).damageChild(this, r);
11937            } else {
11938                mParent.invalidateChild(this, r);
11939            }
11940        }
11941    }
11942
11943    /**
11944     * Utility method to transform a given Rect by the current matrix of this view.
11945     */
11946    void transformRect(final Rect rect) {
11947        if (!getMatrix().isIdentity()) {
11948            RectF boundingRect = mAttachInfo.mTmpTransformRect;
11949            boundingRect.set(rect);
11950            getMatrix().mapRect(boundingRect);
11951            rect.set((int) Math.floor(boundingRect.left),
11952                    (int) Math.floor(boundingRect.top),
11953                    (int) Math.ceil(boundingRect.right),
11954                    (int) Math.ceil(boundingRect.bottom));
11955        }
11956    }
11957
11958    /**
11959     * Used to indicate that the parent of this view should clear its caches. This functionality
11960     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11961     * which is necessary when various parent-managed properties of the view change, such as
11962     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11963     * clears the parent caches and does not causes an invalidate event.
11964     *
11965     * @hide
11966     */
11967    protected void invalidateParentCaches() {
11968        if (mParent instanceof View) {
11969            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11970        }
11971    }
11972
11973    /**
11974     * Used to indicate that the parent of this view should be invalidated. This functionality
11975     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11976     * which is necessary when various parent-managed properties of the view change, such as
11977     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11978     * an invalidation event to the parent.
11979     *
11980     * @hide
11981     */
11982    protected void invalidateParentIfNeeded() {
11983        if (isHardwareAccelerated() && mParent instanceof View) {
11984            ((View) mParent).invalidate(true);
11985        }
11986    }
11987
11988    /**
11989     * @hide
11990     */
11991    protected void invalidateParentIfNeededAndWasQuickRejected() {
11992        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11993            // View was rejected last time it was drawn by its parent; this may have changed
11994            invalidateParentIfNeeded();
11995        }
11996    }
11997
11998    /**
11999     * Indicates whether this View is opaque. An opaque View guarantees that it will
12000     * draw all the pixels overlapping its bounds using a fully opaque color.
12001     *
12002     * Subclasses of View should override this method whenever possible to indicate
12003     * whether an instance is opaque. Opaque Views are treated in a special way by
12004     * the View hierarchy, possibly allowing it to perform optimizations during
12005     * invalidate/draw passes.
12006     *
12007     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12008     */
12009    @ViewDebug.ExportedProperty(category = "drawing")
12010    public boolean isOpaque() {
12011        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12012                getFinalAlpha() >= 1.0f;
12013    }
12014
12015    /**
12016     * @hide
12017     */
12018    protected void computeOpaqueFlags() {
12019        // Opaque if:
12020        //   - Has a background
12021        //   - Background is opaque
12022        //   - Doesn't have scrollbars or scrollbars overlay
12023
12024        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12025            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12026        } else {
12027            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12028        }
12029
12030        final int flags = mViewFlags;
12031        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12032                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12033                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12034            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12035        } else {
12036            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12037        }
12038    }
12039
12040    /**
12041     * @hide
12042     */
12043    protected boolean hasOpaqueScrollbars() {
12044        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12045    }
12046
12047    /**
12048     * @return A handler associated with the thread running the View. This
12049     * handler can be used to pump events in the UI events queue.
12050     */
12051    public Handler getHandler() {
12052        final AttachInfo attachInfo = mAttachInfo;
12053        if (attachInfo != null) {
12054            return attachInfo.mHandler;
12055        }
12056        return null;
12057    }
12058
12059    /**
12060     * Gets the view root associated with the View.
12061     * @return The view root, or null if none.
12062     * @hide
12063     */
12064    public ViewRootImpl getViewRootImpl() {
12065        if (mAttachInfo != null) {
12066            return mAttachInfo.mViewRootImpl;
12067        }
12068        return null;
12069    }
12070
12071    /**
12072     * @hide
12073     */
12074    public HardwareRenderer getHardwareRenderer() {
12075        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12076    }
12077
12078    /**
12079     * <p>Causes the Runnable to be added to the message queue.
12080     * The runnable will be run on the user interface thread.</p>
12081     *
12082     * @param action The Runnable that will be executed.
12083     *
12084     * @return Returns true if the Runnable was successfully placed in to the
12085     *         message queue.  Returns false on failure, usually because the
12086     *         looper processing the message queue is exiting.
12087     *
12088     * @see #postDelayed
12089     * @see #removeCallbacks
12090     */
12091    public boolean post(Runnable action) {
12092        final AttachInfo attachInfo = mAttachInfo;
12093        if (attachInfo != null) {
12094            return attachInfo.mHandler.post(action);
12095        }
12096        // Assume that post will succeed later
12097        ViewRootImpl.getRunQueue().post(action);
12098        return true;
12099    }
12100
12101    /**
12102     * <p>Causes the Runnable to be added to the message queue, to be run
12103     * after the specified amount of time elapses.
12104     * The runnable will be run on the user interface thread.</p>
12105     *
12106     * @param action The Runnable that will be executed.
12107     * @param delayMillis The delay (in milliseconds) until the Runnable
12108     *        will be executed.
12109     *
12110     * @return true if the Runnable was successfully placed in to the
12111     *         message queue.  Returns false on failure, usually because the
12112     *         looper processing the message queue is exiting.  Note that a
12113     *         result of true does not mean the Runnable will be processed --
12114     *         if the looper is quit before the delivery time of the message
12115     *         occurs then the message will be dropped.
12116     *
12117     * @see #post
12118     * @see #removeCallbacks
12119     */
12120    public boolean postDelayed(Runnable action, long delayMillis) {
12121        final AttachInfo attachInfo = mAttachInfo;
12122        if (attachInfo != null) {
12123            return attachInfo.mHandler.postDelayed(action, delayMillis);
12124        }
12125        // Assume that post will succeed later
12126        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12127        return true;
12128    }
12129
12130    /**
12131     * <p>Causes the Runnable to execute on the next animation time step.
12132     * The runnable will be run on the user interface thread.</p>
12133     *
12134     * @param action The Runnable that will be executed.
12135     *
12136     * @see #postOnAnimationDelayed
12137     * @see #removeCallbacks
12138     */
12139    public void postOnAnimation(Runnable action) {
12140        final AttachInfo attachInfo = mAttachInfo;
12141        if (attachInfo != null) {
12142            attachInfo.mViewRootImpl.mChoreographer.postCallback(
12143                    Choreographer.CALLBACK_ANIMATION, action, null);
12144        } else {
12145            // Assume that post will succeed later
12146            ViewRootImpl.getRunQueue().post(action);
12147        }
12148    }
12149
12150    /**
12151     * <p>Causes the Runnable to execute on the next animation time step,
12152     * after the specified amount of time elapses.
12153     * The runnable will be run on the user interface thread.</p>
12154     *
12155     * @param action The Runnable that will be executed.
12156     * @param delayMillis The delay (in milliseconds) until the Runnable
12157     *        will be executed.
12158     *
12159     * @see #postOnAnimation
12160     * @see #removeCallbacks
12161     */
12162    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12163        final AttachInfo attachInfo = mAttachInfo;
12164        if (attachInfo != null) {
12165            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12166                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12167        } else {
12168            // Assume that post will succeed later
12169            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12170        }
12171    }
12172
12173    /**
12174     * <p>Removes the specified Runnable from the message queue.</p>
12175     *
12176     * @param action The Runnable to remove from the message handling queue
12177     *
12178     * @return true if this view could ask the Handler to remove the Runnable,
12179     *         false otherwise. When the returned value is true, the Runnable
12180     *         may or may not have been actually removed from the message queue
12181     *         (for instance, if the Runnable was not in the queue already.)
12182     *
12183     * @see #post
12184     * @see #postDelayed
12185     * @see #postOnAnimation
12186     * @see #postOnAnimationDelayed
12187     */
12188    public boolean removeCallbacks(Runnable action) {
12189        if (action != null) {
12190            final AttachInfo attachInfo = mAttachInfo;
12191            if (attachInfo != null) {
12192                attachInfo.mHandler.removeCallbacks(action);
12193                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12194                        Choreographer.CALLBACK_ANIMATION, action, null);
12195            }
12196            // Assume that post will succeed later
12197            ViewRootImpl.getRunQueue().removeCallbacks(action);
12198        }
12199        return true;
12200    }
12201
12202    /**
12203     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12204     * Use this to invalidate the View from a non-UI thread.</p>
12205     *
12206     * <p>This method can be invoked from outside of the UI thread
12207     * only when this View is attached to a window.</p>
12208     *
12209     * @see #invalidate()
12210     * @see #postInvalidateDelayed(long)
12211     */
12212    public void postInvalidate() {
12213        postInvalidateDelayed(0);
12214    }
12215
12216    /**
12217     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12218     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12219     *
12220     * <p>This method can be invoked from outside of the UI thread
12221     * only when this View is attached to a window.</p>
12222     *
12223     * @param left The left coordinate of the rectangle to invalidate.
12224     * @param top The top coordinate of the rectangle to invalidate.
12225     * @param right The right coordinate of the rectangle to invalidate.
12226     * @param bottom The bottom coordinate of the rectangle to invalidate.
12227     *
12228     * @see #invalidate(int, int, int, int)
12229     * @see #invalidate(Rect)
12230     * @see #postInvalidateDelayed(long, int, int, int, int)
12231     */
12232    public void postInvalidate(int left, int top, int right, int bottom) {
12233        postInvalidateDelayed(0, left, top, right, bottom);
12234    }
12235
12236    /**
12237     * <p>Cause an invalidate to happen on a subsequent cycle through the event
12238     * loop. Waits for the specified amount of time.</p>
12239     *
12240     * <p>This method can be invoked from outside of the UI thread
12241     * only when this View is attached to a window.</p>
12242     *
12243     * @param delayMilliseconds the duration in milliseconds to delay the
12244     *         invalidation by
12245     *
12246     * @see #invalidate()
12247     * @see #postInvalidate()
12248     */
12249    public void postInvalidateDelayed(long delayMilliseconds) {
12250        // We try only with the AttachInfo because there's no point in invalidating
12251        // if we are not attached to our window
12252        final AttachInfo attachInfo = mAttachInfo;
12253        if (attachInfo != null) {
12254            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12255        }
12256    }
12257
12258    /**
12259     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12260     * through the event loop. Waits for the specified amount of time.</p>
12261     *
12262     * <p>This method can be invoked from outside of the UI thread
12263     * only when this View is attached to a window.</p>
12264     *
12265     * @param delayMilliseconds the duration in milliseconds to delay the
12266     *         invalidation by
12267     * @param left The left coordinate of the rectangle to invalidate.
12268     * @param top The top coordinate of the rectangle to invalidate.
12269     * @param right The right coordinate of the rectangle to invalidate.
12270     * @param bottom The bottom coordinate of the rectangle to invalidate.
12271     *
12272     * @see #invalidate(int, int, int, int)
12273     * @see #invalidate(Rect)
12274     * @see #postInvalidate(int, int, int, int)
12275     */
12276    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12277            int right, int bottom) {
12278
12279        // We try only with the AttachInfo because there's no point in invalidating
12280        // if we are not attached to our window
12281        final AttachInfo attachInfo = mAttachInfo;
12282        if (attachInfo != null) {
12283            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12284            info.target = this;
12285            info.left = left;
12286            info.top = top;
12287            info.right = right;
12288            info.bottom = bottom;
12289
12290            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12291        }
12292    }
12293
12294    /**
12295     * <p>Cause an invalidate to happen on the next animation time step, typically the
12296     * next display frame.</p>
12297     *
12298     * <p>This method can be invoked from outside of the UI thread
12299     * only when this View is attached to a window.</p>
12300     *
12301     * @see #invalidate()
12302     */
12303    public void postInvalidateOnAnimation() {
12304        // We try only with the AttachInfo because there's no point in invalidating
12305        // if we are not attached to our window
12306        final AttachInfo attachInfo = mAttachInfo;
12307        if (attachInfo != null) {
12308            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12309        }
12310    }
12311
12312    /**
12313     * <p>Cause an invalidate of the specified area to happen on the next animation
12314     * time step, typically the next display frame.</p>
12315     *
12316     * <p>This method can be invoked from outside of the UI thread
12317     * only when this View is attached to a window.</p>
12318     *
12319     * @param left The left coordinate of the rectangle to invalidate.
12320     * @param top The top coordinate of the rectangle to invalidate.
12321     * @param right The right coordinate of the rectangle to invalidate.
12322     * @param bottom The bottom coordinate of the rectangle to invalidate.
12323     *
12324     * @see #invalidate(int, int, int, int)
12325     * @see #invalidate(Rect)
12326     */
12327    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12328        // We try only with the AttachInfo because there's no point in invalidating
12329        // if we are not attached to our window
12330        final AttachInfo attachInfo = mAttachInfo;
12331        if (attachInfo != null) {
12332            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12333            info.target = this;
12334            info.left = left;
12335            info.top = top;
12336            info.right = right;
12337            info.bottom = bottom;
12338
12339            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12340        }
12341    }
12342
12343    /**
12344     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12345     * This event is sent at most once every
12346     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12347     */
12348    private void postSendViewScrolledAccessibilityEventCallback() {
12349        if (mSendViewScrolledAccessibilityEvent == null) {
12350            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12351        }
12352        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12353            mSendViewScrolledAccessibilityEvent.mIsPending = true;
12354            postDelayed(mSendViewScrolledAccessibilityEvent,
12355                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12356        }
12357    }
12358
12359    /**
12360     * Called by a parent to request that a child update its values for mScrollX
12361     * and mScrollY if necessary. This will typically be done if the child is
12362     * animating a scroll using a {@link android.widget.Scroller Scroller}
12363     * object.
12364     */
12365    public void computeScroll() {
12366    }
12367
12368    /**
12369     * <p>Indicate whether the horizontal edges are faded when the view is
12370     * scrolled horizontally.</p>
12371     *
12372     * @return true if the horizontal edges should are faded on scroll, false
12373     *         otherwise
12374     *
12375     * @see #setHorizontalFadingEdgeEnabled(boolean)
12376     *
12377     * @attr ref android.R.styleable#View_requiresFadingEdge
12378     */
12379    public boolean isHorizontalFadingEdgeEnabled() {
12380        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12381    }
12382
12383    /**
12384     * <p>Define whether the horizontal edges should be faded when this view
12385     * is scrolled horizontally.</p>
12386     *
12387     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12388     *                                    be faded when the view is scrolled
12389     *                                    horizontally
12390     *
12391     * @see #isHorizontalFadingEdgeEnabled()
12392     *
12393     * @attr ref android.R.styleable#View_requiresFadingEdge
12394     */
12395    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12396        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12397            if (horizontalFadingEdgeEnabled) {
12398                initScrollCache();
12399            }
12400
12401            mViewFlags ^= FADING_EDGE_HORIZONTAL;
12402        }
12403    }
12404
12405    /**
12406     * <p>Indicate whether the vertical edges are faded when the view is
12407     * scrolled horizontally.</p>
12408     *
12409     * @return true if the vertical edges should are faded on scroll, false
12410     *         otherwise
12411     *
12412     * @see #setVerticalFadingEdgeEnabled(boolean)
12413     *
12414     * @attr ref android.R.styleable#View_requiresFadingEdge
12415     */
12416    public boolean isVerticalFadingEdgeEnabled() {
12417        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12418    }
12419
12420    /**
12421     * <p>Define whether the vertical edges should be faded when this view
12422     * is scrolled vertically.</p>
12423     *
12424     * @param verticalFadingEdgeEnabled true if the vertical edges should
12425     *                                  be faded when the view is scrolled
12426     *                                  vertically
12427     *
12428     * @see #isVerticalFadingEdgeEnabled()
12429     *
12430     * @attr ref android.R.styleable#View_requiresFadingEdge
12431     */
12432    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12433        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12434            if (verticalFadingEdgeEnabled) {
12435                initScrollCache();
12436            }
12437
12438            mViewFlags ^= FADING_EDGE_VERTICAL;
12439        }
12440    }
12441
12442    /**
12443     * Returns the strength, or intensity, of the top faded edge. The strength is
12444     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12445     * returns 0.0 or 1.0 but no value in between.
12446     *
12447     * Subclasses should override this method to provide a smoother fade transition
12448     * when scrolling occurs.
12449     *
12450     * @return the intensity of the top fade as a float between 0.0f and 1.0f
12451     */
12452    protected float getTopFadingEdgeStrength() {
12453        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12454    }
12455
12456    /**
12457     * Returns the strength, or intensity, of the bottom faded edge. The strength is
12458     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12459     * returns 0.0 or 1.0 but no value in between.
12460     *
12461     * Subclasses should override this method to provide a smoother fade transition
12462     * when scrolling occurs.
12463     *
12464     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12465     */
12466    protected float getBottomFadingEdgeStrength() {
12467        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12468                computeVerticalScrollRange() ? 1.0f : 0.0f;
12469    }
12470
12471    /**
12472     * Returns the strength, or intensity, of the left faded edge. The strength is
12473     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12474     * returns 0.0 or 1.0 but no value in between.
12475     *
12476     * Subclasses should override this method to provide a smoother fade transition
12477     * when scrolling occurs.
12478     *
12479     * @return the intensity of the left fade as a float between 0.0f and 1.0f
12480     */
12481    protected float getLeftFadingEdgeStrength() {
12482        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12483    }
12484
12485    /**
12486     * Returns the strength, or intensity, of the right faded edge. The strength is
12487     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12488     * returns 0.0 or 1.0 but no value in between.
12489     *
12490     * Subclasses should override this method to provide a smoother fade transition
12491     * when scrolling occurs.
12492     *
12493     * @return the intensity of the right fade as a float between 0.0f and 1.0f
12494     */
12495    protected float getRightFadingEdgeStrength() {
12496        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12497                computeHorizontalScrollRange() ? 1.0f : 0.0f;
12498    }
12499
12500    /**
12501     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12502     * scrollbar is not drawn by default.</p>
12503     *
12504     * @return true if the horizontal scrollbar should be painted, false
12505     *         otherwise
12506     *
12507     * @see #setHorizontalScrollBarEnabled(boolean)
12508     */
12509    public boolean isHorizontalScrollBarEnabled() {
12510        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12511    }
12512
12513    /**
12514     * <p>Define whether the horizontal scrollbar should be drawn or not. The
12515     * scrollbar is not drawn by default.</p>
12516     *
12517     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12518     *                                   be painted
12519     *
12520     * @see #isHorizontalScrollBarEnabled()
12521     */
12522    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12523        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12524            mViewFlags ^= SCROLLBARS_HORIZONTAL;
12525            computeOpaqueFlags();
12526            resolvePadding();
12527        }
12528    }
12529
12530    /**
12531     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12532     * scrollbar is not drawn by default.</p>
12533     *
12534     * @return true if the vertical scrollbar should be painted, false
12535     *         otherwise
12536     *
12537     * @see #setVerticalScrollBarEnabled(boolean)
12538     */
12539    public boolean isVerticalScrollBarEnabled() {
12540        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12541    }
12542
12543    /**
12544     * <p>Define whether the vertical scrollbar should be drawn or not. The
12545     * scrollbar is not drawn by default.</p>
12546     *
12547     * @param verticalScrollBarEnabled true if the vertical scrollbar should
12548     *                                 be painted
12549     *
12550     * @see #isVerticalScrollBarEnabled()
12551     */
12552    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12553        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12554            mViewFlags ^= SCROLLBARS_VERTICAL;
12555            computeOpaqueFlags();
12556            resolvePadding();
12557        }
12558    }
12559
12560    /**
12561     * @hide
12562     */
12563    protected void recomputePadding() {
12564        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12565    }
12566
12567    /**
12568     * Define whether scrollbars will fade when the view is not scrolling.
12569     *
12570     * @param fadeScrollbars whether to enable fading
12571     *
12572     * @attr ref android.R.styleable#View_fadeScrollbars
12573     */
12574    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12575        initScrollCache();
12576        final ScrollabilityCache scrollabilityCache = mScrollCache;
12577        scrollabilityCache.fadeScrollBars = fadeScrollbars;
12578        if (fadeScrollbars) {
12579            scrollabilityCache.state = ScrollabilityCache.OFF;
12580        } else {
12581            scrollabilityCache.state = ScrollabilityCache.ON;
12582        }
12583    }
12584
12585    /**
12586     *
12587     * Returns true if scrollbars will fade when this view is not scrolling
12588     *
12589     * @return true if scrollbar fading is enabled
12590     *
12591     * @attr ref android.R.styleable#View_fadeScrollbars
12592     */
12593    public boolean isScrollbarFadingEnabled() {
12594        return mScrollCache != null && mScrollCache.fadeScrollBars;
12595    }
12596
12597    /**
12598     *
12599     * Returns the delay before scrollbars fade.
12600     *
12601     * @return the delay before scrollbars fade
12602     *
12603     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12604     */
12605    public int getScrollBarDefaultDelayBeforeFade() {
12606        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12607                mScrollCache.scrollBarDefaultDelayBeforeFade;
12608    }
12609
12610    /**
12611     * Define the delay before scrollbars fade.
12612     *
12613     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12614     *
12615     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12616     */
12617    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12618        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12619    }
12620
12621    /**
12622     *
12623     * Returns the scrollbar fade duration.
12624     *
12625     * @return the scrollbar fade duration
12626     *
12627     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12628     */
12629    public int getScrollBarFadeDuration() {
12630        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12631                mScrollCache.scrollBarFadeDuration;
12632    }
12633
12634    /**
12635     * Define the scrollbar fade duration.
12636     *
12637     * @param scrollBarFadeDuration - the scrollbar fade duration
12638     *
12639     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12640     */
12641    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12642        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12643    }
12644
12645    /**
12646     *
12647     * Returns the scrollbar size.
12648     *
12649     * @return the scrollbar size
12650     *
12651     * @attr ref android.R.styleable#View_scrollbarSize
12652     */
12653    public int getScrollBarSize() {
12654        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12655                mScrollCache.scrollBarSize;
12656    }
12657
12658    /**
12659     * Define the scrollbar size.
12660     *
12661     * @param scrollBarSize - the scrollbar size
12662     *
12663     * @attr ref android.R.styleable#View_scrollbarSize
12664     */
12665    public void setScrollBarSize(int scrollBarSize) {
12666        getScrollCache().scrollBarSize = scrollBarSize;
12667    }
12668
12669    /**
12670     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12671     * inset. When inset, they add to the padding of the view. And the scrollbars
12672     * can be drawn inside the padding area or on the edge of the view. For example,
12673     * if a view has a background drawable and you want to draw the scrollbars
12674     * inside the padding specified by the drawable, you can use
12675     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12676     * appear at the edge of the view, ignoring the padding, then you can use
12677     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12678     * @param style the style of the scrollbars. Should be one of
12679     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12680     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12681     * @see #SCROLLBARS_INSIDE_OVERLAY
12682     * @see #SCROLLBARS_INSIDE_INSET
12683     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12684     * @see #SCROLLBARS_OUTSIDE_INSET
12685     *
12686     * @attr ref android.R.styleable#View_scrollbarStyle
12687     */
12688    public void setScrollBarStyle(@ScrollBarStyle int style) {
12689        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12690            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12691            computeOpaqueFlags();
12692            resolvePadding();
12693        }
12694    }
12695
12696    /**
12697     * <p>Returns the current scrollbar style.</p>
12698     * @return the current scrollbar style
12699     * @see #SCROLLBARS_INSIDE_OVERLAY
12700     * @see #SCROLLBARS_INSIDE_INSET
12701     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12702     * @see #SCROLLBARS_OUTSIDE_INSET
12703     *
12704     * @attr ref android.R.styleable#View_scrollbarStyle
12705     */
12706    @ViewDebug.ExportedProperty(mapping = {
12707            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12708            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12709            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12710            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12711    })
12712    @ScrollBarStyle
12713    public int getScrollBarStyle() {
12714        return mViewFlags & SCROLLBARS_STYLE_MASK;
12715    }
12716
12717    /**
12718     * <p>Compute the horizontal range that the horizontal scrollbar
12719     * represents.</p>
12720     *
12721     * <p>The range is expressed in arbitrary units that must be the same as the
12722     * units used by {@link #computeHorizontalScrollExtent()} and
12723     * {@link #computeHorizontalScrollOffset()}.</p>
12724     *
12725     * <p>The default range is the drawing width of this view.</p>
12726     *
12727     * @return the total horizontal range represented by the horizontal
12728     *         scrollbar
12729     *
12730     * @see #computeHorizontalScrollExtent()
12731     * @see #computeHorizontalScrollOffset()
12732     * @see android.widget.ScrollBarDrawable
12733     */
12734    protected int computeHorizontalScrollRange() {
12735        return getWidth();
12736    }
12737
12738    /**
12739     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12740     * within the horizontal range. This value is used to compute the position
12741     * of the thumb within the scrollbar's track.</p>
12742     *
12743     * <p>The range is expressed in arbitrary units that must be the same as the
12744     * units used by {@link #computeHorizontalScrollRange()} and
12745     * {@link #computeHorizontalScrollExtent()}.</p>
12746     *
12747     * <p>The default offset is the scroll offset of this view.</p>
12748     *
12749     * @return the horizontal offset of the scrollbar's thumb
12750     *
12751     * @see #computeHorizontalScrollRange()
12752     * @see #computeHorizontalScrollExtent()
12753     * @see android.widget.ScrollBarDrawable
12754     */
12755    protected int computeHorizontalScrollOffset() {
12756        return mScrollX;
12757    }
12758
12759    /**
12760     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12761     * within the horizontal range. This value is used to compute the length
12762     * of the thumb within the scrollbar's track.</p>
12763     *
12764     * <p>The range is expressed in arbitrary units that must be the same as the
12765     * units used by {@link #computeHorizontalScrollRange()} and
12766     * {@link #computeHorizontalScrollOffset()}.</p>
12767     *
12768     * <p>The default extent is the drawing width of this view.</p>
12769     *
12770     * @return the horizontal extent of the scrollbar's thumb
12771     *
12772     * @see #computeHorizontalScrollRange()
12773     * @see #computeHorizontalScrollOffset()
12774     * @see android.widget.ScrollBarDrawable
12775     */
12776    protected int computeHorizontalScrollExtent() {
12777        return getWidth();
12778    }
12779
12780    /**
12781     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12782     *
12783     * <p>The range is expressed in arbitrary units that must be the same as the
12784     * units used by {@link #computeVerticalScrollExtent()} and
12785     * {@link #computeVerticalScrollOffset()}.</p>
12786     *
12787     * @return the total vertical range represented by the vertical scrollbar
12788     *
12789     * <p>The default range is the drawing height of this view.</p>
12790     *
12791     * @see #computeVerticalScrollExtent()
12792     * @see #computeVerticalScrollOffset()
12793     * @see android.widget.ScrollBarDrawable
12794     */
12795    protected int computeVerticalScrollRange() {
12796        return getHeight();
12797    }
12798
12799    /**
12800     * <p>Compute the vertical offset of the vertical scrollbar's thumb
12801     * within the horizontal range. This value is used to compute the position
12802     * of the thumb within the scrollbar's track.</p>
12803     *
12804     * <p>The range is expressed in arbitrary units that must be the same as the
12805     * units used by {@link #computeVerticalScrollRange()} and
12806     * {@link #computeVerticalScrollExtent()}.</p>
12807     *
12808     * <p>The default offset is the scroll offset of this view.</p>
12809     *
12810     * @return the vertical offset of the scrollbar's thumb
12811     *
12812     * @see #computeVerticalScrollRange()
12813     * @see #computeVerticalScrollExtent()
12814     * @see android.widget.ScrollBarDrawable
12815     */
12816    protected int computeVerticalScrollOffset() {
12817        return mScrollY;
12818    }
12819
12820    /**
12821     * <p>Compute the vertical extent of the vertical scrollbar's thumb
12822     * within the vertical range. This value is used to compute the length
12823     * of the thumb within the scrollbar's track.</p>
12824     *
12825     * <p>The range is expressed in arbitrary units that must be the same as the
12826     * units used by {@link #computeVerticalScrollRange()} and
12827     * {@link #computeVerticalScrollOffset()}.</p>
12828     *
12829     * <p>The default extent is the drawing height of this view.</p>
12830     *
12831     * @return the vertical extent of the scrollbar's thumb
12832     *
12833     * @see #computeVerticalScrollRange()
12834     * @see #computeVerticalScrollOffset()
12835     * @see android.widget.ScrollBarDrawable
12836     */
12837    protected int computeVerticalScrollExtent() {
12838        return getHeight();
12839    }
12840
12841    /**
12842     * Check if this view can be scrolled horizontally in a certain direction.
12843     *
12844     * @param direction Negative to check scrolling left, positive to check scrolling right.
12845     * @return true if this view can be scrolled in the specified direction, false otherwise.
12846     */
12847    public boolean canScrollHorizontally(int direction) {
12848        final int offset = computeHorizontalScrollOffset();
12849        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12850        if (range == 0) return false;
12851        if (direction < 0) {
12852            return offset > 0;
12853        } else {
12854            return offset < range - 1;
12855        }
12856    }
12857
12858    /**
12859     * Check if this view can be scrolled vertically in a certain direction.
12860     *
12861     * @param direction Negative to check scrolling up, positive to check scrolling down.
12862     * @return true if this view can be scrolled in the specified direction, false otherwise.
12863     */
12864    public boolean canScrollVertically(int direction) {
12865        final int offset = computeVerticalScrollOffset();
12866        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12867        if (range == 0) return false;
12868        if (direction < 0) {
12869            return offset > 0;
12870        } else {
12871            return offset < range - 1;
12872        }
12873    }
12874
12875    /**
12876     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12877     * scrollbars are painted only if they have been awakened first.</p>
12878     *
12879     * @param canvas the canvas on which to draw the scrollbars
12880     *
12881     * @see #awakenScrollBars(int)
12882     */
12883    protected final void onDrawScrollBars(Canvas canvas) {
12884        // scrollbars are drawn only when the animation is running
12885        final ScrollabilityCache cache = mScrollCache;
12886        if (cache != null) {
12887
12888            int state = cache.state;
12889
12890            if (state == ScrollabilityCache.OFF) {
12891                return;
12892            }
12893
12894            boolean invalidate = false;
12895
12896            if (state == ScrollabilityCache.FADING) {
12897                // We're fading -- get our fade interpolation
12898                if (cache.interpolatorValues == null) {
12899                    cache.interpolatorValues = new float[1];
12900                }
12901
12902                float[] values = cache.interpolatorValues;
12903
12904                // Stops the animation if we're done
12905                if (cache.scrollBarInterpolator.timeToValues(values) ==
12906                        Interpolator.Result.FREEZE_END) {
12907                    cache.state = ScrollabilityCache.OFF;
12908                } else {
12909                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
12910                }
12911
12912                // This will make the scroll bars inval themselves after
12913                // drawing. We only want this when we're fading so that
12914                // we prevent excessive redraws
12915                invalidate = true;
12916            } else {
12917                // We're just on -- but we may have been fading before so
12918                // reset alpha
12919                cache.scrollBar.mutate().setAlpha(255);
12920            }
12921
12922
12923            final int viewFlags = mViewFlags;
12924
12925            final boolean drawHorizontalScrollBar =
12926                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12927            final boolean drawVerticalScrollBar =
12928                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12929                && !isVerticalScrollBarHidden();
12930
12931            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12932                final int width = mRight - mLeft;
12933                final int height = mBottom - mTop;
12934
12935                final ScrollBarDrawable scrollBar = cache.scrollBar;
12936
12937                final int scrollX = mScrollX;
12938                final int scrollY = mScrollY;
12939                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12940
12941                int left;
12942                int top;
12943                int right;
12944                int bottom;
12945
12946                if (drawHorizontalScrollBar) {
12947                    int size = scrollBar.getSize(false);
12948                    if (size <= 0) {
12949                        size = cache.scrollBarSize;
12950                    }
12951
12952                    scrollBar.setParameters(computeHorizontalScrollRange(),
12953                                            computeHorizontalScrollOffset(),
12954                                            computeHorizontalScrollExtent(), false);
12955                    final int verticalScrollBarGap = drawVerticalScrollBar ?
12956                            getVerticalScrollbarWidth() : 0;
12957                    top = scrollY + height - size - (mUserPaddingBottom & inside);
12958                    left = scrollX + (mPaddingLeft & inside);
12959                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12960                    bottom = top + size;
12961                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12962                    if (invalidate) {
12963                        invalidate(left, top, right, bottom);
12964                    }
12965                }
12966
12967                if (drawVerticalScrollBar) {
12968                    int size = scrollBar.getSize(true);
12969                    if (size <= 0) {
12970                        size = cache.scrollBarSize;
12971                    }
12972
12973                    scrollBar.setParameters(computeVerticalScrollRange(),
12974                                            computeVerticalScrollOffset(),
12975                                            computeVerticalScrollExtent(), true);
12976                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
12977                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12978                        verticalScrollbarPosition = isLayoutRtl() ?
12979                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12980                    }
12981                    switch (verticalScrollbarPosition) {
12982                        default:
12983                        case SCROLLBAR_POSITION_RIGHT:
12984                            left = scrollX + width - size - (mUserPaddingRight & inside);
12985                            break;
12986                        case SCROLLBAR_POSITION_LEFT:
12987                            left = scrollX + (mUserPaddingLeft & inside);
12988                            break;
12989                    }
12990                    top = scrollY + (mPaddingTop & inside);
12991                    right = left + size;
12992                    bottom = scrollY + height - (mUserPaddingBottom & inside);
12993                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12994                    if (invalidate) {
12995                        invalidate(left, top, right, bottom);
12996                    }
12997                }
12998            }
12999        }
13000    }
13001
13002    /**
13003     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13004     * FastScroller is visible.
13005     * @return whether to temporarily hide the vertical scrollbar
13006     * @hide
13007     */
13008    protected boolean isVerticalScrollBarHidden() {
13009        return false;
13010    }
13011
13012    /**
13013     * <p>Draw the horizontal scrollbar if
13014     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13015     *
13016     * @param canvas the canvas on which to draw the scrollbar
13017     * @param scrollBar the scrollbar's drawable
13018     *
13019     * @see #isHorizontalScrollBarEnabled()
13020     * @see #computeHorizontalScrollRange()
13021     * @see #computeHorizontalScrollExtent()
13022     * @see #computeHorizontalScrollOffset()
13023     * @see android.widget.ScrollBarDrawable
13024     * @hide
13025     */
13026    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13027            int l, int t, int r, int b) {
13028        scrollBar.setBounds(l, t, r, b);
13029        scrollBar.draw(canvas);
13030    }
13031
13032    /**
13033     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13034     * returns true.</p>
13035     *
13036     * @param canvas the canvas on which to draw the scrollbar
13037     * @param scrollBar the scrollbar's drawable
13038     *
13039     * @see #isVerticalScrollBarEnabled()
13040     * @see #computeVerticalScrollRange()
13041     * @see #computeVerticalScrollExtent()
13042     * @see #computeVerticalScrollOffset()
13043     * @see android.widget.ScrollBarDrawable
13044     * @hide
13045     */
13046    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13047            int l, int t, int r, int b) {
13048        scrollBar.setBounds(l, t, r, b);
13049        scrollBar.draw(canvas);
13050    }
13051
13052    /**
13053     * Implement this to do your drawing.
13054     *
13055     * @param canvas the canvas on which the background will be drawn
13056     */
13057    protected void onDraw(Canvas canvas) {
13058    }
13059
13060    /*
13061     * Caller is responsible for calling requestLayout if necessary.
13062     * (This allows addViewInLayout to not request a new layout.)
13063     */
13064    void assignParent(ViewParent parent) {
13065        if (mParent == null) {
13066            mParent = parent;
13067        } else if (parent == null) {
13068            mParent = null;
13069        } else {
13070            throw new RuntimeException("view " + this + " being added, but"
13071                    + " it already has a parent");
13072        }
13073    }
13074
13075    /**
13076     * This is called when the view is attached to a window.  At this point it
13077     * has a Surface and will start drawing.  Note that this function is
13078     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13079     * however it may be called any time before the first onDraw -- including
13080     * before or after {@link #onMeasure(int, int)}.
13081     *
13082     * @see #onDetachedFromWindow()
13083     */
13084    protected void onAttachedToWindow() {
13085        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13086            mParent.requestTransparentRegion(this);
13087        }
13088
13089        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
13090            initialAwakenScrollBars();
13091            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
13092        }
13093
13094        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13095
13096        jumpDrawablesToCurrentState();
13097
13098        resetSubtreeAccessibilityStateChanged();
13099
13100        // rebuild, since Outline not maintained while View is detached
13101        rebuildOutline();
13102
13103        if (isFocused()) {
13104            InputMethodManager imm = InputMethodManager.peekInstance();
13105            if (imm != null) {
13106                imm.focusIn(this);
13107            }
13108        }
13109    }
13110
13111    /**
13112     * Resolve all RTL related properties.
13113     *
13114     * @return true if resolution of RTL properties has been done
13115     *
13116     * @hide
13117     */
13118    public boolean resolveRtlPropertiesIfNeeded() {
13119        if (!needRtlPropertiesResolution()) return false;
13120
13121        // Order is important here: LayoutDirection MUST be resolved first
13122        if (!isLayoutDirectionResolved()) {
13123            resolveLayoutDirection();
13124            resolveLayoutParams();
13125        }
13126        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
13127        if (!isTextDirectionResolved()) {
13128            resolveTextDirection();
13129        }
13130        if (!isTextAlignmentResolved()) {
13131            resolveTextAlignment();
13132        }
13133        // Should resolve Drawables before Padding because we need the layout direction of the
13134        // Drawable to correctly resolve Padding.
13135        if (!areDrawablesResolved()) {
13136            resolveDrawables();
13137        }
13138        if (!isPaddingResolved()) {
13139            resolvePadding();
13140        }
13141        onRtlPropertiesChanged(getLayoutDirection());
13142        return true;
13143    }
13144
13145    /**
13146     * Reset resolution of all RTL related properties.
13147     *
13148     * @hide
13149     */
13150    public void resetRtlProperties() {
13151        resetResolvedLayoutDirection();
13152        resetResolvedTextDirection();
13153        resetResolvedTextAlignment();
13154        resetResolvedPadding();
13155        resetResolvedDrawables();
13156    }
13157
13158    /**
13159     * @see #onScreenStateChanged(int)
13160     */
13161    void dispatchScreenStateChanged(int screenState) {
13162        onScreenStateChanged(screenState);
13163    }
13164
13165    /**
13166     * This method is called whenever the state of the screen this view is
13167     * attached to changes. A state change will usually occurs when the screen
13168     * turns on or off (whether it happens automatically or the user does it
13169     * manually.)
13170     *
13171     * @param screenState The new state of the screen. Can be either
13172     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13173     */
13174    public void onScreenStateChanged(int screenState) {
13175    }
13176
13177    /**
13178     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13179     */
13180    private boolean hasRtlSupport() {
13181        return mContext.getApplicationInfo().hasRtlSupport();
13182    }
13183
13184    /**
13185     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13186     * RTL not supported)
13187     */
13188    private boolean isRtlCompatibilityMode() {
13189        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13190        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13191    }
13192
13193    /**
13194     * @return true if RTL properties need resolution.
13195     *
13196     */
13197    private boolean needRtlPropertiesResolution() {
13198        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13199    }
13200
13201    /**
13202     * Called when any RTL property (layout direction or text direction or text alignment) has
13203     * been changed.
13204     *
13205     * Subclasses need to override this method to take care of cached information that depends on the
13206     * resolved layout direction, or to inform child views that inherit their layout direction.
13207     *
13208     * The default implementation does nothing.
13209     *
13210     * @param layoutDirection the direction of the layout
13211     *
13212     * @see #LAYOUT_DIRECTION_LTR
13213     * @see #LAYOUT_DIRECTION_RTL
13214     */
13215    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13216    }
13217
13218    /**
13219     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13220     * that the parent directionality can and will be resolved before its children.
13221     *
13222     * @return true if resolution has been done, false otherwise.
13223     *
13224     * @hide
13225     */
13226    public boolean resolveLayoutDirection() {
13227        // Clear any previous layout direction resolution
13228        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13229
13230        if (hasRtlSupport()) {
13231            // Set resolved depending on layout direction
13232            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13233                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13234                case LAYOUT_DIRECTION_INHERIT:
13235                    // We cannot resolve yet. LTR is by default and let the resolution happen again
13236                    // later to get the correct resolved value
13237                    if (!canResolveLayoutDirection()) return false;
13238
13239                    // Parent has not yet resolved, LTR is still the default
13240                    try {
13241                        if (!mParent.isLayoutDirectionResolved()) return false;
13242
13243                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13244                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13245                        }
13246                    } catch (AbstractMethodError e) {
13247                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13248                                " does not fully implement ViewParent", e);
13249                    }
13250                    break;
13251                case LAYOUT_DIRECTION_RTL:
13252                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13253                    break;
13254                case LAYOUT_DIRECTION_LOCALE:
13255                    if((LAYOUT_DIRECTION_RTL ==
13256                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13257                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13258                    }
13259                    break;
13260                default:
13261                    // Nothing to do, LTR by default
13262            }
13263        }
13264
13265        // Set to resolved
13266        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13267        return true;
13268    }
13269
13270    /**
13271     * Check if layout direction resolution can be done.
13272     *
13273     * @return true if layout direction resolution can be done otherwise return false.
13274     */
13275    public boolean canResolveLayoutDirection() {
13276        switch (getRawLayoutDirection()) {
13277            case LAYOUT_DIRECTION_INHERIT:
13278                if (mParent != null) {
13279                    try {
13280                        return mParent.canResolveLayoutDirection();
13281                    } catch (AbstractMethodError e) {
13282                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13283                                " does not fully implement ViewParent", e);
13284                    }
13285                }
13286                return false;
13287
13288            default:
13289                return true;
13290        }
13291    }
13292
13293    /**
13294     * Reset the resolved layout direction. Layout direction will be resolved during a call to
13295     * {@link #onMeasure(int, int)}.
13296     *
13297     * @hide
13298     */
13299    public void resetResolvedLayoutDirection() {
13300        // Reset the current resolved bits
13301        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13302    }
13303
13304    /**
13305     * @return true if the layout direction is inherited.
13306     *
13307     * @hide
13308     */
13309    public boolean isLayoutDirectionInherited() {
13310        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13311    }
13312
13313    /**
13314     * @return true if layout direction has been resolved.
13315     */
13316    public boolean isLayoutDirectionResolved() {
13317        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13318    }
13319
13320    /**
13321     * Return if padding has been resolved
13322     *
13323     * @hide
13324     */
13325    boolean isPaddingResolved() {
13326        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13327    }
13328
13329    /**
13330     * Resolves padding depending on layout direction, if applicable, and
13331     * recomputes internal padding values to adjust for scroll bars.
13332     *
13333     * @hide
13334     */
13335    public void resolvePadding() {
13336        final int resolvedLayoutDirection = getLayoutDirection();
13337
13338        if (!isRtlCompatibilityMode()) {
13339            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13340            // If start / end padding are defined, they will be resolved (hence overriding) to
13341            // left / right or right / left depending on the resolved layout direction.
13342            // If start / end padding are not defined, use the left / right ones.
13343            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13344                Rect padding = sThreadLocal.get();
13345                if (padding == null) {
13346                    padding = new Rect();
13347                    sThreadLocal.set(padding);
13348                }
13349                mBackground.getPadding(padding);
13350                if (!mLeftPaddingDefined) {
13351                    mUserPaddingLeftInitial = padding.left;
13352                }
13353                if (!mRightPaddingDefined) {
13354                    mUserPaddingRightInitial = padding.right;
13355                }
13356            }
13357            switch (resolvedLayoutDirection) {
13358                case LAYOUT_DIRECTION_RTL:
13359                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13360                        mUserPaddingRight = mUserPaddingStart;
13361                    } else {
13362                        mUserPaddingRight = mUserPaddingRightInitial;
13363                    }
13364                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13365                        mUserPaddingLeft = mUserPaddingEnd;
13366                    } else {
13367                        mUserPaddingLeft = mUserPaddingLeftInitial;
13368                    }
13369                    break;
13370                case LAYOUT_DIRECTION_LTR:
13371                default:
13372                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13373                        mUserPaddingLeft = mUserPaddingStart;
13374                    } else {
13375                        mUserPaddingLeft = mUserPaddingLeftInitial;
13376                    }
13377                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13378                        mUserPaddingRight = mUserPaddingEnd;
13379                    } else {
13380                        mUserPaddingRight = mUserPaddingRightInitial;
13381                    }
13382            }
13383
13384            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13385        }
13386
13387        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13388        onRtlPropertiesChanged(resolvedLayoutDirection);
13389
13390        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13391    }
13392
13393    /**
13394     * Reset the resolved layout direction.
13395     *
13396     * @hide
13397     */
13398    public void resetResolvedPadding() {
13399        resetResolvedPaddingInternal();
13400    }
13401
13402    /**
13403     * Used when we only want to reset *this* view's padding and not trigger overrides
13404     * in ViewGroup that reset children too.
13405     */
13406    void resetResolvedPaddingInternal() {
13407        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13408    }
13409
13410    /**
13411     * This is called when the view is detached from a window.  At this point it
13412     * no longer has a surface for drawing.
13413     *
13414     * @see #onAttachedToWindow()
13415     */
13416    protected void onDetachedFromWindow() {
13417    }
13418
13419    /**
13420     * This is a framework-internal mirror of onDetachedFromWindow() that's called
13421     * after onDetachedFromWindow().
13422     *
13423     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13424     * The super method should be called at the end of the overridden method to ensure
13425     * subclasses are destroyed first
13426     *
13427     * @hide
13428     */
13429    protected void onDetachedFromWindowInternal() {
13430        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13431        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13432
13433        removeUnsetPressCallback();
13434        removeLongPressCallback();
13435        removePerformClickCallback();
13436        removeSendViewScrolledAccessibilityEventCallback();
13437        stopNestedScroll();
13438
13439        // Anything that started animating right before detach should already
13440        // be in its final state when re-attached.
13441        jumpDrawablesToCurrentState();
13442
13443        destroyDrawingCache();
13444
13445        cleanupDraw();
13446        mCurrentAnimation = null;
13447    }
13448
13449    private void cleanupDraw() {
13450        resetDisplayList();
13451        if (mAttachInfo != null) {
13452            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13453        }
13454    }
13455
13456    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13457    }
13458
13459    /**
13460     * @return The number of times this view has been attached to a window
13461     */
13462    protected int getWindowAttachCount() {
13463        return mWindowAttachCount;
13464    }
13465
13466    /**
13467     * Retrieve a unique token identifying the window this view is attached to.
13468     * @return Return the window's token for use in
13469     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13470     */
13471    public IBinder getWindowToken() {
13472        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13473    }
13474
13475    /**
13476     * Retrieve the {@link WindowId} for the window this view is
13477     * currently attached to.
13478     */
13479    public WindowId getWindowId() {
13480        if (mAttachInfo == null) {
13481            return null;
13482        }
13483        if (mAttachInfo.mWindowId == null) {
13484            try {
13485                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13486                        mAttachInfo.mWindowToken);
13487                mAttachInfo.mWindowId = new WindowId(
13488                        mAttachInfo.mIWindowId);
13489            } catch (RemoteException e) {
13490            }
13491        }
13492        return mAttachInfo.mWindowId;
13493    }
13494
13495    /**
13496     * Retrieve a unique token identifying the top-level "real" window of
13497     * the window that this view is attached to.  That is, this is like
13498     * {@link #getWindowToken}, except if the window this view in is a panel
13499     * window (attached to another containing window), then the token of
13500     * the containing window is returned instead.
13501     *
13502     * @return Returns the associated window token, either
13503     * {@link #getWindowToken()} or the containing window's token.
13504     */
13505    public IBinder getApplicationWindowToken() {
13506        AttachInfo ai = mAttachInfo;
13507        if (ai != null) {
13508            IBinder appWindowToken = ai.mPanelParentWindowToken;
13509            if (appWindowToken == null) {
13510                appWindowToken = ai.mWindowToken;
13511            }
13512            return appWindowToken;
13513        }
13514        return null;
13515    }
13516
13517    /**
13518     * Gets the logical display to which the view's window has been attached.
13519     *
13520     * @return The logical display, or null if the view is not currently attached to a window.
13521     */
13522    public Display getDisplay() {
13523        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13524    }
13525
13526    /**
13527     * Retrieve private session object this view hierarchy is using to
13528     * communicate with the window manager.
13529     * @return the session object to communicate with the window manager
13530     */
13531    /*package*/ IWindowSession getWindowSession() {
13532        return mAttachInfo != null ? mAttachInfo.mSession : null;
13533    }
13534
13535    /**
13536     * @param info the {@link android.view.View.AttachInfo} to associated with
13537     *        this view
13538     */
13539    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13540        //System.out.println("Attached! " + this);
13541        mAttachInfo = info;
13542        if (mOverlay != null) {
13543            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13544        }
13545        mWindowAttachCount++;
13546        // We will need to evaluate the drawable state at least once.
13547        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13548        if (mFloatingTreeObserver != null) {
13549            info.mTreeObserver.merge(mFloatingTreeObserver);
13550            mFloatingTreeObserver = null;
13551        }
13552        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13553            mAttachInfo.mScrollContainers.add(this);
13554            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13555        }
13556        performCollectViewAttributes(mAttachInfo, visibility);
13557        onAttachedToWindow();
13558
13559        ListenerInfo li = mListenerInfo;
13560        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13561                li != null ? li.mOnAttachStateChangeListeners : null;
13562        if (listeners != null && listeners.size() > 0) {
13563            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13564            // perform the dispatching. The iterator is a safe guard against listeners that
13565            // could mutate the list by calling the various add/remove methods. This prevents
13566            // the array from being modified while we iterate it.
13567            for (OnAttachStateChangeListener listener : listeners) {
13568                listener.onViewAttachedToWindow(this);
13569            }
13570        }
13571
13572        int vis = info.mWindowVisibility;
13573        if (vis != GONE) {
13574            onWindowVisibilityChanged(vis);
13575        }
13576        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13577            // If nobody has evaluated the drawable state yet, then do it now.
13578            refreshDrawableState();
13579        }
13580        needGlobalAttributesUpdate(false);
13581    }
13582
13583    void dispatchDetachedFromWindow() {
13584        AttachInfo info = mAttachInfo;
13585        if (info != null) {
13586            int vis = info.mWindowVisibility;
13587            if (vis != GONE) {
13588                onWindowVisibilityChanged(GONE);
13589            }
13590        }
13591
13592        onDetachedFromWindow();
13593        onDetachedFromWindowInternal();
13594
13595        ListenerInfo li = mListenerInfo;
13596        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13597                li != null ? li.mOnAttachStateChangeListeners : null;
13598        if (listeners != null && listeners.size() > 0) {
13599            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13600            // perform the dispatching. The iterator is a safe guard against listeners that
13601            // could mutate the list by calling the various add/remove methods. This prevents
13602            // the array from being modified while we iterate it.
13603            for (OnAttachStateChangeListener listener : listeners) {
13604                listener.onViewDetachedFromWindow(this);
13605            }
13606        }
13607
13608        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13609            mAttachInfo.mScrollContainers.remove(this);
13610            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13611        }
13612
13613        mAttachInfo = null;
13614        if (mOverlay != null) {
13615            mOverlay.getOverlayView().dispatchDetachedFromWindow();
13616        }
13617    }
13618
13619    /**
13620     * Cancel any deferred high-level input events that were previously posted to the event queue.
13621     *
13622     * <p>Many views post high-level events such as click handlers to the event queue
13623     * to run deferred in order to preserve a desired user experience - clearing visible
13624     * pressed states before executing, etc. This method will abort any events of this nature
13625     * that are currently in flight.</p>
13626     *
13627     * <p>Custom views that generate their own high-level deferred input events should override
13628     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13629     *
13630     * <p>This will also cancel pending input events for any child views.</p>
13631     *
13632     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13633     * This will not impact newer events posted after this call that may occur as a result of
13634     * lower-level input events still waiting in the queue. If you are trying to prevent
13635     * double-submitted  events for the duration of some sort of asynchronous transaction
13636     * you should also take other steps to protect against unexpected double inputs e.g. calling
13637     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13638     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13639     */
13640    public final void cancelPendingInputEvents() {
13641        dispatchCancelPendingInputEvents();
13642    }
13643
13644    /**
13645     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13646     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13647     */
13648    void dispatchCancelPendingInputEvents() {
13649        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13650        onCancelPendingInputEvents();
13651        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13652            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13653                    " did not call through to super.onCancelPendingInputEvents()");
13654        }
13655    }
13656
13657    /**
13658     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13659     * a parent view.
13660     *
13661     * <p>This method is responsible for removing any pending high-level input events that were
13662     * posted to the event queue to run later. Custom view classes that post their own deferred
13663     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13664     * {@link android.os.Handler} should override this method, call
13665     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13666     * </p>
13667     */
13668    public void onCancelPendingInputEvents() {
13669        removePerformClickCallback();
13670        cancelLongPress();
13671        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13672    }
13673
13674    /**
13675     * Store this view hierarchy's frozen state into the given container.
13676     *
13677     * @param container The SparseArray in which to save the view's state.
13678     *
13679     * @see #restoreHierarchyState(android.util.SparseArray)
13680     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13681     * @see #onSaveInstanceState()
13682     */
13683    public void saveHierarchyState(SparseArray<Parcelable> container) {
13684        dispatchSaveInstanceState(container);
13685    }
13686
13687    /**
13688     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13689     * this view and its children. May be overridden to modify how freezing happens to a
13690     * view's children; for example, some views may want to not store state for their children.
13691     *
13692     * @param container The SparseArray in which to save the view's state.
13693     *
13694     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13695     * @see #saveHierarchyState(android.util.SparseArray)
13696     * @see #onSaveInstanceState()
13697     */
13698    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13699        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13700            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13701            Parcelable state = onSaveInstanceState();
13702            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13703                throw new IllegalStateException(
13704                        "Derived class did not call super.onSaveInstanceState()");
13705            }
13706            if (state != null) {
13707                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13708                // + ": " + state);
13709                container.put(mID, state);
13710            }
13711        }
13712    }
13713
13714    /**
13715     * Hook allowing a view to generate a representation of its internal state
13716     * that can later be used to create a new instance with that same state.
13717     * This state should only contain information that is not persistent or can
13718     * not be reconstructed later. For example, you will never store your
13719     * current position on screen because that will be computed again when a
13720     * new instance of the view is placed in its view hierarchy.
13721     * <p>
13722     * Some examples of things you may store here: the current cursor position
13723     * in a text view (but usually not the text itself since that is stored in a
13724     * content provider or other persistent storage), the currently selected
13725     * item in a list view.
13726     *
13727     * @return Returns a Parcelable object containing the view's current dynamic
13728     *         state, or null if there is nothing interesting to save. The
13729     *         default implementation returns null.
13730     * @see #onRestoreInstanceState(android.os.Parcelable)
13731     * @see #saveHierarchyState(android.util.SparseArray)
13732     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13733     * @see #setSaveEnabled(boolean)
13734     */
13735    protected Parcelable onSaveInstanceState() {
13736        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13737        return BaseSavedState.EMPTY_STATE;
13738    }
13739
13740    /**
13741     * Restore this view hierarchy's frozen state from the given container.
13742     *
13743     * @param container The SparseArray which holds previously frozen states.
13744     *
13745     * @see #saveHierarchyState(android.util.SparseArray)
13746     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13747     * @see #onRestoreInstanceState(android.os.Parcelable)
13748     */
13749    public void restoreHierarchyState(SparseArray<Parcelable> container) {
13750        dispatchRestoreInstanceState(container);
13751    }
13752
13753    /**
13754     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13755     * state for this view and its children. May be overridden to modify how restoring
13756     * happens to a view's children; for example, some views may want to not store state
13757     * for their children.
13758     *
13759     * @param container The SparseArray which holds previously saved state.
13760     *
13761     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13762     * @see #restoreHierarchyState(android.util.SparseArray)
13763     * @see #onRestoreInstanceState(android.os.Parcelable)
13764     */
13765    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13766        if (mID != NO_ID) {
13767            Parcelable state = container.get(mID);
13768            if (state != null) {
13769                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13770                // + ": " + state);
13771                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13772                onRestoreInstanceState(state);
13773                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13774                    throw new IllegalStateException(
13775                            "Derived class did not call super.onRestoreInstanceState()");
13776                }
13777            }
13778        }
13779    }
13780
13781    /**
13782     * Hook allowing a view to re-apply a representation of its internal state that had previously
13783     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13784     * null state.
13785     *
13786     * @param state The frozen state that had previously been returned by
13787     *        {@link #onSaveInstanceState}.
13788     *
13789     * @see #onSaveInstanceState()
13790     * @see #restoreHierarchyState(android.util.SparseArray)
13791     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13792     */
13793    protected void onRestoreInstanceState(Parcelable state) {
13794        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13795        if (state != BaseSavedState.EMPTY_STATE && state != null) {
13796            throw new IllegalArgumentException("Wrong state class, expecting View State but "
13797                    + "received " + state.getClass().toString() + " instead. This usually happens "
13798                    + "when two views of different type have the same id in the same hierarchy. "
13799                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13800                    + "other views do not use the same id.");
13801        }
13802    }
13803
13804    /**
13805     * <p>Return the time at which the drawing of the view hierarchy started.</p>
13806     *
13807     * @return the drawing start time in milliseconds
13808     */
13809    public long getDrawingTime() {
13810        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13811    }
13812
13813    /**
13814     * <p>Enables or disables the duplication of the parent's state into this view. When
13815     * duplication is enabled, this view gets its drawable state from its parent rather
13816     * than from its own internal properties.</p>
13817     *
13818     * <p>Note: in the current implementation, setting this property to true after the
13819     * view was added to a ViewGroup might have no effect at all. This property should
13820     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13821     *
13822     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13823     * property is enabled, an exception will be thrown.</p>
13824     *
13825     * <p>Note: if the child view uses and updates additional states which are unknown to the
13826     * parent, these states should not be affected by this method.</p>
13827     *
13828     * @param enabled True to enable duplication of the parent's drawable state, false
13829     *                to disable it.
13830     *
13831     * @see #getDrawableState()
13832     * @see #isDuplicateParentStateEnabled()
13833     */
13834    public void setDuplicateParentStateEnabled(boolean enabled) {
13835        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13836    }
13837
13838    /**
13839     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13840     *
13841     * @return True if this view's drawable state is duplicated from the parent,
13842     *         false otherwise
13843     *
13844     * @see #getDrawableState()
13845     * @see #setDuplicateParentStateEnabled(boolean)
13846     */
13847    public boolean isDuplicateParentStateEnabled() {
13848        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13849    }
13850
13851    /**
13852     * <p>Specifies the type of layer backing this view. The layer can be
13853     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13854     * {@link #LAYER_TYPE_HARDWARE}.</p>
13855     *
13856     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13857     * instance that controls how the layer is composed on screen. The following
13858     * properties of the paint are taken into account when composing the layer:</p>
13859     * <ul>
13860     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13861     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13862     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13863     * </ul>
13864     *
13865     * <p>If this view has an alpha value set to < 1.0 by calling
13866     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
13867     * by this view's alpha value.</p>
13868     *
13869     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13870     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13871     * for more information on when and how to use layers.</p>
13872     *
13873     * @param layerType The type of layer to use with this view, must be one of
13874     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13875     *        {@link #LAYER_TYPE_HARDWARE}
13876     * @param paint The paint used to compose the layer. This argument is optional
13877     *        and can be null. It is ignored when the layer type is
13878     *        {@link #LAYER_TYPE_NONE}
13879     *
13880     * @see #getLayerType()
13881     * @see #LAYER_TYPE_NONE
13882     * @see #LAYER_TYPE_SOFTWARE
13883     * @see #LAYER_TYPE_HARDWARE
13884     * @see #setAlpha(float)
13885     *
13886     * @attr ref android.R.styleable#View_layerType
13887     */
13888    public void setLayerType(int layerType, Paint paint) {
13889        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13890            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13891                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13892        }
13893
13894        boolean typeChanged = mRenderNode.setLayerType(layerType);
13895
13896        if (!typeChanged) {
13897            setLayerPaint(paint);
13898            return;
13899        }
13900
13901        // Destroy any previous software drawing cache if needed
13902        if (mLayerType == LAYER_TYPE_SOFTWARE) {
13903            destroyDrawingCache();
13904        }
13905
13906        mLayerType = layerType;
13907        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
13908        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13909        mRenderNode.setLayerPaint(mLayerPaint);
13910
13911        // draw() behaves differently if we are on a layer, so we need to
13912        // invalidate() here
13913        invalidateParentCaches();
13914        invalidate(true);
13915    }
13916
13917    /**
13918     * Updates the {@link Paint} object used with the current layer (used only if the current
13919     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13920     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13921     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13922     * ensure that the view gets redrawn immediately.
13923     *
13924     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13925     * instance that controls how the layer is composed on screen. The following
13926     * properties of the paint are taken into account when composing the layer:</p>
13927     * <ul>
13928     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13929     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13930     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13931     * </ul>
13932     *
13933     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13934     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
13935     *
13936     * @param paint The paint used to compose the layer. This argument is optional
13937     *        and can be null. It is ignored when the layer type is
13938     *        {@link #LAYER_TYPE_NONE}
13939     *
13940     * @see #setLayerType(int, android.graphics.Paint)
13941     */
13942    public void setLayerPaint(Paint paint) {
13943        int layerType = getLayerType();
13944        if (layerType != LAYER_TYPE_NONE) {
13945            mLayerPaint = paint == null ? new Paint() : paint;
13946            if (layerType == LAYER_TYPE_HARDWARE) {
13947                if (mRenderNode.setLayerPaint(mLayerPaint)) {
13948                    invalidateViewProperty(false, false);
13949                }
13950            } else {
13951                invalidate();
13952            }
13953        }
13954    }
13955
13956    /**
13957     * Indicates whether this view has a static layer. A view with layer type
13958     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13959     * dynamic.
13960     */
13961    boolean hasStaticLayer() {
13962        return true;
13963    }
13964
13965    /**
13966     * Indicates what type of layer is currently associated with this view. By default
13967     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13968     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13969     * for more information on the different types of layers.
13970     *
13971     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13972     *         {@link #LAYER_TYPE_HARDWARE}
13973     *
13974     * @see #setLayerType(int, android.graphics.Paint)
13975     * @see #buildLayer()
13976     * @see #LAYER_TYPE_NONE
13977     * @see #LAYER_TYPE_SOFTWARE
13978     * @see #LAYER_TYPE_HARDWARE
13979     */
13980    public int getLayerType() {
13981        return mLayerType;
13982    }
13983
13984    /**
13985     * Forces this view's layer to be created and this view to be rendered
13986     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13987     * invoking this method will have no effect.
13988     *
13989     * This method can for instance be used to render a view into its layer before
13990     * starting an animation. If this view is complex, rendering into the layer
13991     * before starting the animation will avoid skipping frames.
13992     *
13993     * @throws IllegalStateException If this view is not attached to a window
13994     *
13995     * @see #setLayerType(int, android.graphics.Paint)
13996     */
13997    public void buildLayer() {
13998        if (mLayerType == LAYER_TYPE_NONE) return;
13999
14000        final AttachInfo attachInfo = mAttachInfo;
14001        if (attachInfo == null) {
14002            throw new IllegalStateException("This view must be attached to a window first");
14003        }
14004
14005        if (getWidth() == 0 || getHeight() == 0) {
14006            return;
14007        }
14008
14009        switch (mLayerType) {
14010            case LAYER_TYPE_HARDWARE:
14011                updateDisplayListIfDirty();
14012                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14013                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14014                }
14015                break;
14016            case LAYER_TYPE_SOFTWARE:
14017                buildDrawingCache(true);
14018                break;
14019        }
14020    }
14021
14022    /**
14023     * If this View draws with a HardwareLayer, returns it.
14024     * Otherwise returns null
14025     *
14026     * TODO: Only TextureView uses this, can we eliminate it?
14027     */
14028    HardwareLayer getHardwareLayer() {
14029        return null;
14030    }
14031
14032    /**
14033     * Destroys all hardware rendering resources. This method is invoked
14034     * when the system needs to reclaim resources. Upon execution of this
14035     * method, you should free any OpenGL resources created by the view.
14036     *
14037     * Note: you <strong>must</strong> call
14038     * <code>super.destroyHardwareResources()</code> when overriding
14039     * this method.
14040     *
14041     * @hide
14042     */
14043    protected void destroyHardwareResources() {
14044        // Although the Layer will be destroyed by RenderNode, we want to release
14045        // the staging display list, which is also a signal to RenderNode that it's
14046        // safe to free its copy of the display list as it knows that we will
14047        // push an updated DisplayList if we try to draw again
14048        resetDisplayList();
14049    }
14050
14051    /**
14052     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14053     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14054     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14055     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14056     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14057     * null.</p>
14058     *
14059     * <p>Enabling the drawing cache is similar to
14060     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14061     * acceleration is turned off. When hardware acceleration is turned on, enabling the
14062     * drawing cache has no effect on rendering because the system uses a different mechanism
14063     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14064     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14065     * for information on how to enable software and hardware layers.</p>
14066     *
14067     * <p>This API can be used to manually generate
14068     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14069     * {@link #getDrawingCache()}.</p>
14070     *
14071     * @param enabled true to enable the drawing cache, false otherwise
14072     *
14073     * @see #isDrawingCacheEnabled()
14074     * @see #getDrawingCache()
14075     * @see #buildDrawingCache()
14076     * @see #setLayerType(int, android.graphics.Paint)
14077     */
14078    public void setDrawingCacheEnabled(boolean enabled) {
14079        mCachingFailed = false;
14080        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14081    }
14082
14083    /**
14084     * <p>Indicates whether the drawing cache is enabled for this view.</p>
14085     *
14086     * @return true if the drawing cache is enabled
14087     *
14088     * @see #setDrawingCacheEnabled(boolean)
14089     * @see #getDrawingCache()
14090     */
14091    @ViewDebug.ExportedProperty(category = "drawing")
14092    public boolean isDrawingCacheEnabled() {
14093        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
14094    }
14095
14096    /**
14097     * Debugging utility which recursively outputs the dirty state of a view and its
14098     * descendants.
14099     *
14100     * @hide
14101     */
14102    @SuppressWarnings({"UnusedDeclaration"})
14103    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
14104        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
14105                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
14106                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
14107                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
14108        if (clear) {
14109            mPrivateFlags &= clearMask;
14110        }
14111        if (this instanceof ViewGroup) {
14112            ViewGroup parent = (ViewGroup) this;
14113            final int count = parent.getChildCount();
14114            for (int i = 0; i < count; i++) {
14115                final View child = parent.getChildAt(i);
14116                child.outputDirtyFlags(indent + "  ", clear, clearMask);
14117            }
14118        }
14119    }
14120
14121    /**
14122     * This method is used by ViewGroup to cause its children to restore or recreate their
14123     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
14124     * to recreate its own display list, which would happen if it went through the normal
14125     * draw/dispatchDraw mechanisms.
14126     *
14127     * @hide
14128     */
14129    protected void dispatchGetDisplayList() {}
14130
14131    /**
14132     * A view that is not attached or hardware accelerated cannot create a display list.
14133     * This method checks these conditions and returns the appropriate result.
14134     *
14135     * @return true if view has the ability to create a display list, false otherwise.
14136     *
14137     * @hide
14138     */
14139    public boolean canHaveDisplayList() {
14140        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
14141    }
14142
14143    private void updateDisplayListIfDirty() {
14144        final RenderNode renderNode = mRenderNode;
14145        if (!canHaveDisplayList()) {
14146            // can't populate RenderNode, don't try
14147            return;
14148        }
14149
14150        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14151                || !renderNode.isValid()
14152                || (mRecreateDisplayList)) {
14153            // Don't need to recreate the display list, just need to tell our
14154            // children to restore/recreate theirs
14155            if (renderNode.isValid()
14156                    && !mRecreateDisplayList) {
14157                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14158                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14159                dispatchGetDisplayList();
14160
14161                return; // no work needed
14162            }
14163
14164            // If we got here, we're recreating it. Mark it as such to ensure that
14165            // we copy in child display lists into ours in drawChild()
14166            mRecreateDisplayList = true;
14167
14168            int width = mRight - mLeft;
14169            int height = mBottom - mTop;
14170            int layerType = getLayerType();
14171
14172            final HardwareCanvas canvas = renderNode.start(width, height);
14173            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14174
14175            try {
14176                final HardwareLayer layer = getHardwareLayer();
14177                if (layer != null && layer.isValid()) {
14178                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14179                } else if (layerType == LAYER_TYPE_SOFTWARE) {
14180                    buildDrawingCache(true);
14181                    Bitmap cache = getDrawingCache(true);
14182                    if (cache != null) {
14183                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14184                    }
14185                } else {
14186                    computeScroll();
14187
14188                    canvas.translate(-mScrollX, -mScrollY);
14189                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14190                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14191
14192                    // Fast path for layouts with no backgrounds
14193                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14194                        dispatchDraw(canvas);
14195                        if (mOverlay != null && !mOverlay.isEmpty()) {
14196                            mOverlay.getOverlayView().draw(canvas);
14197                        }
14198                    } else {
14199                        draw(canvas);
14200                    }
14201                }
14202            } finally {
14203                renderNode.end(canvas);
14204                setDisplayListProperties(renderNode);
14205            }
14206        } else {
14207            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14208            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14209        }
14210    }
14211
14212    /**
14213     * Returns a RenderNode with View draw content recorded, which can be
14214     * used to draw this view again without executing its draw method.
14215     *
14216     * @return A RenderNode ready to replay, or null if caching is not enabled.
14217     *
14218     * @hide
14219     */
14220    public RenderNode getDisplayList() {
14221        updateDisplayListIfDirty();
14222        return mRenderNode;
14223    }
14224
14225    private void resetDisplayList() {
14226        if (mRenderNode.isValid()) {
14227            mRenderNode.destroyDisplayListData();
14228        }
14229
14230        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14231            mBackgroundRenderNode.destroyDisplayListData();
14232        }
14233    }
14234
14235    /**
14236     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14237     *
14238     * @return A non-scaled bitmap representing this view or null if cache is disabled.
14239     *
14240     * @see #getDrawingCache(boolean)
14241     */
14242    public Bitmap getDrawingCache() {
14243        return getDrawingCache(false);
14244    }
14245
14246    /**
14247     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14248     * is null when caching is disabled. If caching is enabled and the cache is not ready,
14249     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14250     * draw from the cache when the cache is enabled. To benefit from the cache, you must
14251     * request the drawing cache by calling this method and draw it on screen if the
14252     * returned bitmap is not null.</p>
14253     *
14254     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14255     * this method will create a bitmap of the same size as this view. Because this bitmap
14256     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14257     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14258     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14259     * size than the view. This implies that your application must be able to handle this
14260     * size.</p>
14261     *
14262     * @param autoScale Indicates whether the generated bitmap should be scaled based on
14263     *        the current density of the screen when the application is in compatibility
14264     *        mode.
14265     *
14266     * @return A bitmap representing this view or null if cache is disabled.
14267     *
14268     * @see #setDrawingCacheEnabled(boolean)
14269     * @see #isDrawingCacheEnabled()
14270     * @see #buildDrawingCache(boolean)
14271     * @see #destroyDrawingCache()
14272     */
14273    public Bitmap getDrawingCache(boolean autoScale) {
14274        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14275            return null;
14276        }
14277        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14278            buildDrawingCache(autoScale);
14279        }
14280        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14281    }
14282
14283    /**
14284     * <p>Frees the resources used by the drawing cache. If you call
14285     * {@link #buildDrawingCache()} manually without calling
14286     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14287     * should cleanup the cache with this method afterwards.</p>
14288     *
14289     * @see #setDrawingCacheEnabled(boolean)
14290     * @see #buildDrawingCache()
14291     * @see #getDrawingCache()
14292     */
14293    public void destroyDrawingCache() {
14294        if (mDrawingCache != null) {
14295            mDrawingCache.recycle();
14296            mDrawingCache = null;
14297        }
14298        if (mUnscaledDrawingCache != null) {
14299            mUnscaledDrawingCache.recycle();
14300            mUnscaledDrawingCache = null;
14301        }
14302    }
14303
14304    /**
14305     * Setting a solid background color for the drawing cache's bitmaps will improve
14306     * performance and memory usage. Note, though that this should only be used if this
14307     * view will always be drawn on top of a solid color.
14308     *
14309     * @param color The background color to use for the drawing cache's bitmap
14310     *
14311     * @see #setDrawingCacheEnabled(boolean)
14312     * @see #buildDrawingCache()
14313     * @see #getDrawingCache()
14314     */
14315    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
14316        if (color != mDrawingCacheBackgroundColor) {
14317            mDrawingCacheBackgroundColor = color;
14318            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14319        }
14320    }
14321
14322    /**
14323     * @see #setDrawingCacheBackgroundColor(int)
14324     *
14325     * @return The background color to used for the drawing cache's bitmap
14326     */
14327    @ColorInt
14328    public int getDrawingCacheBackgroundColor() {
14329        return mDrawingCacheBackgroundColor;
14330    }
14331
14332    /**
14333     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14334     *
14335     * @see #buildDrawingCache(boolean)
14336     */
14337    public void buildDrawingCache() {
14338        buildDrawingCache(false);
14339    }
14340
14341    /**
14342     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14343     *
14344     * <p>If you call {@link #buildDrawingCache()} manually without calling
14345     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14346     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14347     *
14348     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14349     * this method will create a bitmap of the same size as this view. Because this bitmap
14350     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14351     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14352     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14353     * size than the view. This implies that your application must be able to handle this
14354     * size.</p>
14355     *
14356     * <p>You should avoid calling this method when hardware acceleration is enabled. If
14357     * you do not need the drawing cache bitmap, calling this method will increase memory
14358     * usage and cause the view to be rendered in software once, thus negatively impacting
14359     * performance.</p>
14360     *
14361     * @see #getDrawingCache()
14362     * @see #destroyDrawingCache()
14363     */
14364    public void buildDrawingCache(boolean autoScale) {
14365        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14366                mDrawingCache == null : mUnscaledDrawingCache == null)) {
14367            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
14368                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
14369                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
14370            }
14371            try {
14372                buildDrawingCacheImpl(autoScale);
14373            } finally {
14374                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
14375            }
14376        }
14377    }
14378
14379    /**
14380     * private, internal implementation of buildDrawingCache, used to enable tracing
14381     */
14382    private void buildDrawingCacheImpl(boolean autoScale) {
14383        mCachingFailed = false;
14384
14385        int width = mRight - mLeft;
14386        int height = mBottom - mTop;
14387
14388        final AttachInfo attachInfo = mAttachInfo;
14389        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14390
14391        if (autoScale && scalingRequired) {
14392            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14393            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14394        }
14395
14396        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14397        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14398        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14399
14400        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14401        final long drawingCacheSize =
14402                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14403        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14404            if (width > 0 && height > 0) {
14405                Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14406                        + projectedBitmapSize + " bytes, only "
14407                        + drawingCacheSize + " available");
14408            }
14409            destroyDrawingCache();
14410            mCachingFailed = true;
14411            return;
14412        }
14413
14414        boolean clear = true;
14415        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14416
14417        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14418            Bitmap.Config quality;
14419            if (!opaque) {
14420                // Never pick ARGB_4444 because it looks awful
14421                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14422                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14423                    case DRAWING_CACHE_QUALITY_AUTO:
14424                    case DRAWING_CACHE_QUALITY_LOW:
14425                    case DRAWING_CACHE_QUALITY_HIGH:
14426                    default:
14427                        quality = Bitmap.Config.ARGB_8888;
14428                        break;
14429                }
14430            } else {
14431                // Optimization for translucent windows
14432                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14433                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14434            }
14435
14436            // Try to cleanup memory
14437            if (bitmap != null) bitmap.recycle();
14438
14439            try {
14440                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14441                        width, height, quality);
14442                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14443                if (autoScale) {
14444                    mDrawingCache = bitmap;
14445                } else {
14446                    mUnscaledDrawingCache = bitmap;
14447                }
14448                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14449            } catch (OutOfMemoryError e) {
14450                // If there is not enough memory to create the bitmap cache, just
14451                // ignore the issue as bitmap caches are not required to draw the
14452                // view hierarchy
14453                if (autoScale) {
14454                    mDrawingCache = null;
14455                } else {
14456                    mUnscaledDrawingCache = null;
14457                }
14458                mCachingFailed = true;
14459                return;
14460            }
14461
14462            clear = drawingCacheBackgroundColor != 0;
14463        }
14464
14465        Canvas canvas;
14466        if (attachInfo != null) {
14467            canvas = attachInfo.mCanvas;
14468            if (canvas == null) {
14469                canvas = new Canvas();
14470            }
14471            canvas.setBitmap(bitmap);
14472            // Temporarily clobber the cached Canvas in case one of our children
14473            // is also using a drawing cache. Without this, the children would
14474            // steal the canvas by attaching their own bitmap to it and bad, bad
14475            // thing would happen (invisible views, corrupted drawings, etc.)
14476            attachInfo.mCanvas = null;
14477        } else {
14478            // This case should hopefully never or seldom happen
14479            canvas = new Canvas(bitmap);
14480        }
14481
14482        if (clear) {
14483            bitmap.eraseColor(drawingCacheBackgroundColor);
14484        }
14485
14486        computeScroll();
14487        final int restoreCount = canvas.save();
14488
14489        if (autoScale && scalingRequired) {
14490            final float scale = attachInfo.mApplicationScale;
14491            canvas.scale(scale, scale);
14492        }
14493
14494        canvas.translate(-mScrollX, -mScrollY);
14495
14496        mPrivateFlags |= PFLAG_DRAWN;
14497        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14498                mLayerType != LAYER_TYPE_NONE) {
14499            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14500        }
14501
14502        // Fast path for layouts with no backgrounds
14503        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14504            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14505            dispatchDraw(canvas);
14506            if (mOverlay != null && !mOverlay.isEmpty()) {
14507                mOverlay.getOverlayView().draw(canvas);
14508            }
14509        } else {
14510            draw(canvas);
14511        }
14512
14513        canvas.restoreToCount(restoreCount);
14514        canvas.setBitmap(null);
14515
14516        if (attachInfo != null) {
14517            // Restore the cached Canvas for our siblings
14518            attachInfo.mCanvas = canvas;
14519        }
14520    }
14521
14522    /**
14523     * Create a snapshot of the view into a bitmap.  We should probably make
14524     * some form of this public, but should think about the API.
14525     */
14526    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14527        int width = mRight - mLeft;
14528        int height = mBottom - mTop;
14529
14530        final AttachInfo attachInfo = mAttachInfo;
14531        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14532        width = (int) ((width * scale) + 0.5f);
14533        height = (int) ((height * scale) + 0.5f);
14534
14535        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14536                width > 0 ? width : 1, height > 0 ? height : 1, quality);
14537        if (bitmap == null) {
14538            throw new OutOfMemoryError();
14539        }
14540
14541        Resources resources = getResources();
14542        if (resources != null) {
14543            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14544        }
14545
14546        Canvas canvas;
14547        if (attachInfo != null) {
14548            canvas = attachInfo.mCanvas;
14549            if (canvas == null) {
14550                canvas = new Canvas();
14551            }
14552            canvas.setBitmap(bitmap);
14553            // Temporarily clobber the cached Canvas in case one of our children
14554            // is also using a drawing cache. Without this, the children would
14555            // steal the canvas by attaching their own bitmap to it and bad, bad
14556            // things would happen (invisible views, corrupted drawings, etc.)
14557            attachInfo.mCanvas = null;
14558        } else {
14559            // This case should hopefully never or seldom happen
14560            canvas = new Canvas(bitmap);
14561        }
14562
14563        if ((backgroundColor & 0xff000000) != 0) {
14564            bitmap.eraseColor(backgroundColor);
14565        }
14566
14567        computeScroll();
14568        final int restoreCount = canvas.save();
14569        canvas.scale(scale, scale);
14570        canvas.translate(-mScrollX, -mScrollY);
14571
14572        // Temporarily remove the dirty mask
14573        int flags = mPrivateFlags;
14574        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14575
14576        // Fast path for layouts with no backgrounds
14577        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14578            dispatchDraw(canvas);
14579            if (mOverlay != null && !mOverlay.isEmpty()) {
14580                mOverlay.getOverlayView().draw(canvas);
14581            }
14582        } else {
14583            draw(canvas);
14584        }
14585
14586        mPrivateFlags = flags;
14587
14588        canvas.restoreToCount(restoreCount);
14589        canvas.setBitmap(null);
14590
14591        if (attachInfo != null) {
14592            // Restore the cached Canvas for our siblings
14593            attachInfo.mCanvas = canvas;
14594        }
14595
14596        return bitmap;
14597    }
14598
14599    /**
14600     * Indicates whether this View is currently in edit mode. A View is usually
14601     * in edit mode when displayed within a developer tool. For instance, if
14602     * this View is being drawn by a visual user interface builder, this method
14603     * should return true.
14604     *
14605     * Subclasses should check the return value of this method to provide
14606     * different behaviors if their normal behavior might interfere with the
14607     * host environment. For instance: the class spawns a thread in its
14608     * constructor, the drawing code relies on device-specific features, etc.
14609     *
14610     * This method is usually checked in the drawing code of custom widgets.
14611     *
14612     * @return True if this View is in edit mode, false otherwise.
14613     */
14614    public boolean isInEditMode() {
14615        return false;
14616    }
14617
14618    /**
14619     * If the View draws content inside its padding and enables fading edges,
14620     * it needs to support padding offsets. Padding offsets are added to the
14621     * fading edges to extend the length of the fade so that it covers pixels
14622     * drawn inside the padding.
14623     *
14624     * Subclasses of this class should override this method if they need
14625     * to draw content inside the padding.
14626     *
14627     * @return True if padding offset must be applied, false otherwise.
14628     *
14629     * @see #getLeftPaddingOffset()
14630     * @see #getRightPaddingOffset()
14631     * @see #getTopPaddingOffset()
14632     * @see #getBottomPaddingOffset()
14633     *
14634     * @since CURRENT
14635     */
14636    protected boolean isPaddingOffsetRequired() {
14637        return false;
14638    }
14639
14640    /**
14641     * Amount by which to extend the left fading region. Called only when
14642     * {@link #isPaddingOffsetRequired()} returns true.
14643     *
14644     * @return The left padding offset in pixels.
14645     *
14646     * @see #isPaddingOffsetRequired()
14647     *
14648     * @since CURRENT
14649     */
14650    protected int getLeftPaddingOffset() {
14651        return 0;
14652    }
14653
14654    /**
14655     * Amount by which to extend the right fading region. Called only when
14656     * {@link #isPaddingOffsetRequired()} returns true.
14657     *
14658     * @return The right padding offset in pixels.
14659     *
14660     * @see #isPaddingOffsetRequired()
14661     *
14662     * @since CURRENT
14663     */
14664    protected int getRightPaddingOffset() {
14665        return 0;
14666    }
14667
14668    /**
14669     * Amount by which to extend the top fading region. Called only when
14670     * {@link #isPaddingOffsetRequired()} returns true.
14671     *
14672     * @return The top padding offset in pixels.
14673     *
14674     * @see #isPaddingOffsetRequired()
14675     *
14676     * @since CURRENT
14677     */
14678    protected int getTopPaddingOffset() {
14679        return 0;
14680    }
14681
14682    /**
14683     * Amount by which to extend the bottom fading region. Called only when
14684     * {@link #isPaddingOffsetRequired()} returns true.
14685     *
14686     * @return The bottom padding offset in pixels.
14687     *
14688     * @see #isPaddingOffsetRequired()
14689     *
14690     * @since CURRENT
14691     */
14692    protected int getBottomPaddingOffset() {
14693        return 0;
14694    }
14695
14696    /**
14697     * @hide
14698     * @param offsetRequired
14699     */
14700    protected int getFadeTop(boolean offsetRequired) {
14701        int top = mPaddingTop;
14702        if (offsetRequired) top += getTopPaddingOffset();
14703        return top;
14704    }
14705
14706    /**
14707     * @hide
14708     * @param offsetRequired
14709     */
14710    protected int getFadeHeight(boolean offsetRequired) {
14711        int padding = mPaddingTop;
14712        if (offsetRequired) padding += getTopPaddingOffset();
14713        return mBottom - mTop - mPaddingBottom - padding;
14714    }
14715
14716    /**
14717     * <p>Indicates whether this view is attached to a hardware accelerated
14718     * window or not.</p>
14719     *
14720     * <p>Even if this method returns true, it does not mean that every call
14721     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14722     * accelerated {@link android.graphics.Canvas}. For instance, if this view
14723     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14724     * window is hardware accelerated,
14725     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14726     * return false, and this method will return true.</p>
14727     *
14728     * @return True if the view is attached to a window and the window is
14729     *         hardware accelerated; false in any other case.
14730     */
14731    @ViewDebug.ExportedProperty(category = "drawing")
14732    public boolean isHardwareAccelerated() {
14733        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14734    }
14735
14736    /**
14737     * Sets a rectangular area on this view to which the view will be clipped
14738     * when it is drawn. Setting the value to null will remove the clip bounds
14739     * and the view will draw normally, using its full bounds.
14740     *
14741     * @param clipBounds The rectangular area, in the local coordinates of
14742     * this view, to which future drawing operations will be clipped.
14743     */
14744    public void setClipBounds(Rect clipBounds) {
14745        if (clipBounds == mClipBounds
14746                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
14747            return;
14748        }
14749        if (clipBounds != null) {
14750            if (mClipBounds == null) {
14751                mClipBounds = new Rect(clipBounds);
14752            } else {
14753                mClipBounds.set(clipBounds);
14754            }
14755        } else {
14756            mClipBounds = null;
14757        }
14758        mRenderNode.setClipBounds(mClipBounds);
14759        invalidateViewProperty(false, false);
14760    }
14761
14762    /**
14763     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14764     *
14765     * @return A copy of the current clip bounds if clip bounds are set,
14766     * otherwise null.
14767     */
14768    public Rect getClipBounds() {
14769        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14770    }
14771
14772    /**
14773     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14774     * case of an active Animation being run on the view.
14775     */
14776    private boolean drawAnimation(ViewGroup parent, long drawingTime,
14777            Animation a, boolean scalingRequired) {
14778        Transformation invalidationTransform;
14779        final int flags = parent.mGroupFlags;
14780        final boolean initialized = a.isInitialized();
14781        if (!initialized) {
14782            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14783            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14784            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14785            onAnimationStart();
14786        }
14787
14788        final Transformation t = parent.getChildTransformation();
14789        boolean more = a.getTransformation(drawingTime, t, 1f);
14790        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14791            if (parent.mInvalidationTransformation == null) {
14792                parent.mInvalidationTransformation = new Transformation();
14793            }
14794            invalidationTransform = parent.mInvalidationTransformation;
14795            a.getTransformation(drawingTime, invalidationTransform, 1f);
14796        } else {
14797            invalidationTransform = t;
14798        }
14799
14800        if (more) {
14801            if (!a.willChangeBounds()) {
14802                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14803                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14804                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14805                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14806                    // The child need to draw an animation, potentially offscreen, so
14807                    // make sure we do not cancel invalidate requests
14808                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14809                    parent.invalidate(mLeft, mTop, mRight, mBottom);
14810                }
14811            } else {
14812                if (parent.mInvalidateRegion == null) {
14813                    parent.mInvalidateRegion = new RectF();
14814                }
14815                final RectF region = parent.mInvalidateRegion;
14816                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14817                        invalidationTransform);
14818
14819                // The child need to draw an animation, potentially offscreen, so
14820                // make sure we do not cancel invalidate requests
14821                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14822
14823                final int left = mLeft + (int) region.left;
14824                final int top = mTop + (int) region.top;
14825                parent.invalidate(left, top, left + (int) (region.width() + .5f),
14826                        top + (int) (region.height() + .5f));
14827            }
14828        }
14829        return more;
14830    }
14831
14832    /**
14833     * This method is called by getDisplayList() when a display list is recorded for a View.
14834     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14835     */
14836    void setDisplayListProperties(RenderNode renderNode) {
14837        if (renderNode != null) {
14838            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14839            renderNode.setClipToBounds(mParent instanceof ViewGroup
14840                    && ((ViewGroup) mParent).getClipChildren());
14841
14842            float alpha = 1;
14843            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14844                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14845                ViewGroup parentVG = (ViewGroup) mParent;
14846                final Transformation t = parentVG.getChildTransformation();
14847                if (parentVG.getChildStaticTransformation(this, t)) {
14848                    final int transformType = t.getTransformationType();
14849                    if (transformType != Transformation.TYPE_IDENTITY) {
14850                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14851                            alpha = t.getAlpha();
14852                        }
14853                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14854                            renderNode.setStaticMatrix(t.getMatrix());
14855                        }
14856                    }
14857                }
14858            }
14859            if (mTransformationInfo != null) {
14860                alpha *= getFinalAlpha();
14861                if (alpha < 1) {
14862                    final int multipliedAlpha = (int) (255 * alpha);
14863                    if (onSetAlpha(multipliedAlpha)) {
14864                        alpha = 1;
14865                    }
14866                }
14867                renderNode.setAlpha(alpha);
14868            } else if (alpha < 1) {
14869                renderNode.setAlpha(alpha);
14870            }
14871        }
14872    }
14873
14874    /**
14875     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14876     * This draw() method is an implementation detail and is not intended to be overridden or
14877     * to be called from anywhere else other than ViewGroup.drawChild().
14878     */
14879    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14880        boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14881        boolean more = false;
14882        final boolean childHasIdentityMatrix = hasIdentityMatrix();
14883        final int flags = parent.mGroupFlags;
14884
14885        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14886            parent.getChildTransformation().clear();
14887            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14888        }
14889
14890        Transformation transformToApply = null;
14891        boolean concatMatrix = false;
14892
14893        boolean scalingRequired = false;
14894        boolean caching;
14895        int layerType = getLayerType();
14896
14897        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14898        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14899                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14900            caching = true;
14901            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14902            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14903        } else {
14904            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14905        }
14906
14907        final Animation a = getAnimation();
14908        if (a != null) {
14909            more = drawAnimation(parent, drawingTime, a, scalingRequired);
14910            concatMatrix = a.willChangeTransformationMatrix();
14911            if (concatMatrix) {
14912                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14913            }
14914            transformToApply = parent.getChildTransformation();
14915        } else {
14916            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14917                // No longer animating: clear out old animation matrix
14918                mRenderNode.setAnimationMatrix(null);
14919                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14920            }
14921            if (!usingRenderNodeProperties &&
14922                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14923                final Transformation t = parent.getChildTransformation();
14924                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14925                if (hasTransform) {
14926                    final int transformType = t.getTransformationType();
14927                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14928                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14929                }
14930            }
14931        }
14932
14933        concatMatrix |= !childHasIdentityMatrix;
14934
14935        // Sets the flag as early as possible to allow draw() implementations
14936        // to call invalidate() successfully when doing animations
14937        mPrivateFlags |= PFLAG_DRAWN;
14938
14939        if (!concatMatrix &&
14940                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14941                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14942                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14943                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14944            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14945            return more;
14946        }
14947        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14948
14949        if (hardwareAccelerated) {
14950            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14951            // retain the flag's value temporarily in the mRecreateDisplayList flag
14952            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14953            mPrivateFlags &= ~PFLAG_INVALIDATED;
14954        }
14955
14956        RenderNode renderNode = null;
14957        Bitmap cache = null;
14958        boolean hasDisplayList = false;
14959        if (caching) {
14960            if (!hardwareAccelerated) {
14961                if (layerType != LAYER_TYPE_NONE) {
14962                    layerType = LAYER_TYPE_SOFTWARE;
14963                    buildDrawingCache(true);
14964                }
14965                cache = getDrawingCache(true);
14966            } else {
14967                switch (layerType) {
14968                    case LAYER_TYPE_SOFTWARE:
14969                        if (usingRenderNodeProperties) {
14970                            hasDisplayList = canHaveDisplayList();
14971                        } else {
14972                            buildDrawingCache(true);
14973                            cache = getDrawingCache(true);
14974                        }
14975                        break;
14976                    case LAYER_TYPE_HARDWARE:
14977                        if (usingRenderNodeProperties) {
14978                            hasDisplayList = canHaveDisplayList();
14979                        }
14980                        break;
14981                    case LAYER_TYPE_NONE:
14982                        // Delay getting the display list until animation-driven alpha values are
14983                        // set up and possibly passed on to the view
14984                        hasDisplayList = canHaveDisplayList();
14985                        break;
14986                }
14987            }
14988        }
14989        usingRenderNodeProperties &= hasDisplayList;
14990        if (usingRenderNodeProperties) {
14991            renderNode = getDisplayList();
14992            if (!renderNode.isValid()) {
14993                // Uncommon, but possible. If a view is removed from the hierarchy during the call
14994                // to getDisplayList(), the display list will be marked invalid and we should not
14995                // try to use it again.
14996                renderNode = null;
14997                hasDisplayList = false;
14998                usingRenderNodeProperties = false;
14999            }
15000        }
15001
15002        int sx = 0;
15003        int sy = 0;
15004        if (!hasDisplayList) {
15005            computeScroll();
15006            sx = mScrollX;
15007            sy = mScrollY;
15008        }
15009
15010        final boolean hasNoCache = cache == null || hasDisplayList;
15011        final boolean offsetForScroll = cache == null && !hasDisplayList &&
15012                layerType != LAYER_TYPE_HARDWARE;
15013
15014        int restoreTo = -1;
15015        if (!usingRenderNodeProperties || transformToApply != null) {
15016            restoreTo = canvas.save();
15017        }
15018        if (offsetForScroll) {
15019            canvas.translate(mLeft - sx, mTop - sy);
15020        } else {
15021            if (!usingRenderNodeProperties) {
15022                canvas.translate(mLeft, mTop);
15023            }
15024            if (scalingRequired) {
15025                if (usingRenderNodeProperties) {
15026                    // TODO: Might not need this if we put everything inside the DL
15027                    restoreTo = canvas.save();
15028                }
15029                // mAttachInfo cannot be null, otherwise scalingRequired == false
15030                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15031                canvas.scale(scale, scale);
15032            }
15033        }
15034
15035        float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
15036        if (transformToApply != null || alpha < 1 ||  !hasIdentityMatrix() ||
15037                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15038            if (transformToApply != null || !childHasIdentityMatrix) {
15039                int transX = 0;
15040                int transY = 0;
15041
15042                if (offsetForScroll) {
15043                    transX = -sx;
15044                    transY = -sy;
15045                }
15046
15047                if (transformToApply != null) {
15048                    if (concatMatrix) {
15049                        if (usingRenderNodeProperties) {
15050                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
15051                        } else {
15052                            // Undo the scroll translation, apply the transformation matrix,
15053                            // then redo the scroll translate to get the correct result.
15054                            canvas.translate(-transX, -transY);
15055                            canvas.concat(transformToApply.getMatrix());
15056                            canvas.translate(transX, transY);
15057                        }
15058                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15059                    }
15060
15061                    float transformAlpha = transformToApply.getAlpha();
15062                    if (transformAlpha < 1) {
15063                        alpha *= transformAlpha;
15064                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15065                    }
15066                }
15067
15068                if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
15069                    canvas.translate(-transX, -transY);
15070                    canvas.concat(getMatrix());
15071                    canvas.translate(transX, transY);
15072                }
15073            }
15074
15075            // Deal with alpha if it is or used to be <1
15076            if (alpha < 1 ||
15077                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15078                if (alpha < 1) {
15079                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15080                } else {
15081                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15082                }
15083                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15084                if (hasNoCache) {
15085                    final int multipliedAlpha = (int) (255 * alpha);
15086                    if (!onSetAlpha(multipliedAlpha)) {
15087                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15088                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
15089                                layerType != LAYER_TYPE_NONE) {
15090                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
15091                        }
15092                        if (usingRenderNodeProperties) {
15093                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15094                        } else  if (layerType == LAYER_TYPE_NONE) {
15095                            final int scrollX = hasDisplayList ? 0 : sx;
15096                            final int scrollY = hasDisplayList ? 0 : sy;
15097                            canvas.saveLayerAlpha(scrollX, scrollY,
15098                                    scrollX + (mRight - mLeft), scrollY + (mBottom - mTop),
15099                                    multipliedAlpha, layerFlags);
15100                        }
15101                    } else {
15102                        // Alpha is handled by the child directly, clobber the layer's alpha
15103                        mPrivateFlags |= PFLAG_ALPHA_SET;
15104                    }
15105                }
15106            }
15107        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15108            onSetAlpha(255);
15109            mPrivateFlags &= ~PFLAG_ALPHA_SET;
15110        }
15111
15112        if (!usingRenderNodeProperties) {
15113            // apply clips directly, since RenderNode won't do it for this draw
15114            if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN
15115                    && cache == null) {
15116                if (offsetForScroll) {
15117                    canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
15118                } else {
15119                    if (!scalingRequired || cache == null) {
15120                        canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
15121                    } else {
15122                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
15123                    }
15124                }
15125            }
15126
15127            if (mClipBounds != null) {
15128                // clip bounds ignore scroll
15129                canvas.clipRect(mClipBounds);
15130            }
15131        }
15132
15133
15134
15135        if (!usingRenderNodeProperties && hasDisplayList) {
15136            renderNode = getDisplayList();
15137            if (!renderNode.isValid()) {
15138                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15139                // to getDisplayList(), the display list will be marked invalid and we should not
15140                // try to use it again.
15141                renderNode = null;
15142                hasDisplayList = false;
15143            }
15144        }
15145
15146        if (hasNoCache) {
15147            boolean layerRendered = false;
15148            if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
15149                final HardwareLayer layer = getHardwareLayer();
15150                if (layer != null && layer.isValid()) {
15151                    int restoreAlpha = mLayerPaint.getAlpha();
15152                    mLayerPaint.setAlpha((int) (alpha * 255));
15153                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
15154                    mLayerPaint.setAlpha(restoreAlpha);
15155                    layerRendered = true;
15156                } else {
15157                    final int scrollX = hasDisplayList ? 0 : sx;
15158                    final int scrollY = hasDisplayList ? 0 : sy;
15159                    canvas.saveLayer(scrollX, scrollY,
15160                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
15161                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
15162                }
15163            }
15164
15165            if (!layerRendered) {
15166                if (!hasDisplayList) {
15167                    // Fast path for layouts with no backgrounds
15168                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15169                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15170                        dispatchDraw(canvas);
15171                    } else {
15172                        draw(canvas);
15173                    }
15174                } else {
15175                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15176                    ((HardwareCanvas) canvas).drawRenderNode(renderNode, flags);
15177                }
15178            }
15179        } else if (cache != null) {
15180            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15181            Paint cachePaint;
15182            int restoreAlpha = 0;
15183
15184            if (layerType == LAYER_TYPE_NONE) {
15185                cachePaint = parent.mCachePaint;
15186                if (cachePaint == null) {
15187                    cachePaint = new Paint();
15188                    cachePaint.setDither(false);
15189                    parent.mCachePaint = cachePaint;
15190                }
15191            } else {
15192                cachePaint = mLayerPaint;
15193                restoreAlpha = mLayerPaint.getAlpha();
15194            }
15195            cachePaint.setAlpha((int) (alpha * 255));
15196            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15197            cachePaint.setAlpha(restoreAlpha);
15198        }
15199
15200        if (restoreTo >= 0) {
15201            canvas.restoreToCount(restoreTo);
15202        }
15203
15204        if (a != null && !more) {
15205            if (!hardwareAccelerated && !a.getFillAfter()) {
15206                onSetAlpha(255);
15207            }
15208            parent.finishAnimatingView(this, a);
15209        }
15210
15211        if (more && hardwareAccelerated) {
15212            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15213                // alpha animations should cause the child to recreate its display list
15214                invalidate(true);
15215            }
15216        }
15217
15218        mRecreateDisplayList = false;
15219
15220        return more;
15221    }
15222
15223    /**
15224     * Manually render this view (and all of its children) to the given Canvas.
15225     * The view must have already done a full layout before this function is
15226     * called.  When implementing a view, implement
15227     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15228     * If you do need to override this method, call the superclass version.
15229     *
15230     * @param canvas The Canvas to which the View is rendered.
15231     */
15232    public void draw(Canvas canvas) {
15233        final int privateFlags = mPrivateFlags;
15234        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15235                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15236        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15237
15238        /*
15239         * Draw traversal performs several drawing steps which must be executed
15240         * in the appropriate order:
15241         *
15242         *      1. Draw the background
15243         *      2. If necessary, save the canvas' layers to prepare for fading
15244         *      3. Draw view's content
15245         *      4. Draw children
15246         *      5. If necessary, draw the fading edges and restore layers
15247         *      6. Draw decorations (scrollbars for instance)
15248         */
15249
15250        // Step 1, draw the background, if needed
15251        int saveCount;
15252
15253        if (!dirtyOpaque) {
15254            drawBackground(canvas);
15255        }
15256
15257        // skip step 2 & 5 if possible (common case)
15258        final int viewFlags = mViewFlags;
15259        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15260        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15261        if (!verticalEdges && !horizontalEdges) {
15262            // Step 3, draw the content
15263            if (!dirtyOpaque) onDraw(canvas);
15264
15265            // Step 4, draw the children
15266            dispatchDraw(canvas);
15267
15268            // Step 6, draw decorations (scrollbars)
15269            onDrawScrollBars(canvas);
15270
15271            if (mOverlay != null && !mOverlay.isEmpty()) {
15272                mOverlay.getOverlayView().dispatchDraw(canvas);
15273            }
15274
15275            // we're done...
15276            return;
15277        }
15278
15279        /*
15280         * Here we do the full fledged routine...
15281         * (this is an uncommon case where speed matters less,
15282         * this is why we repeat some of the tests that have been
15283         * done above)
15284         */
15285
15286        boolean drawTop = false;
15287        boolean drawBottom = false;
15288        boolean drawLeft = false;
15289        boolean drawRight = false;
15290
15291        float topFadeStrength = 0.0f;
15292        float bottomFadeStrength = 0.0f;
15293        float leftFadeStrength = 0.0f;
15294        float rightFadeStrength = 0.0f;
15295
15296        // Step 2, save the canvas' layers
15297        int paddingLeft = mPaddingLeft;
15298
15299        final boolean offsetRequired = isPaddingOffsetRequired();
15300        if (offsetRequired) {
15301            paddingLeft += getLeftPaddingOffset();
15302        }
15303
15304        int left = mScrollX + paddingLeft;
15305        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15306        int top = mScrollY + getFadeTop(offsetRequired);
15307        int bottom = top + getFadeHeight(offsetRequired);
15308
15309        if (offsetRequired) {
15310            right += getRightPaddingOffset();
15311            bottom += getBottomPaddingOffset();
15312        }
15313
15314        final ScrollabilityCache scrollabilityCache = mScrollCache;
15315        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15316        int length = (int) fadeHeight;
15317
15318        // clip the fade length if top and bottom fades overlap
15319        // overlapping fades produce odd-looking artifacts
15320        if (verticalEdges && (top + length > bottom - length)) {
15321            length = (bottom - top) / 2;
15322        }
15323
15324        // also clip horizontal fades if necessary
15325        if (horizontalEdges && (left + length > right - length)) {
15326            length = (right - left) / 2;
15327        }
15328
15329        if (verticalEdges) {
15330            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15331            drawTop = topFadeStrength * fadeHeight > 1.0f;
15332            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15333            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15334        }
15335
15336        if (horizontalEdges) {
15337            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15338            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15339            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15340            drawRight = rightFadeStrength * fadeHeight > 1.0f;
15341        }
15342
15343        saveCount = canvas.getSaveCount();
15344
15345        int solidColor = getSolidColor();
15346        if (solidColor == 0) {
15347            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15348
15349            if (drawTop) {
15350                canvas.saveLayer(left, top, right, top + length, null, flags);
15351            }
15352
15353            if (drawBottom) {
15354                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15355            }
15356
15357            if (drawLeft) {
15358                canvas.saveLayer(left, top, left + length, bottom, null, flags);
15359            }
15360
15361            if (drawRight) {
15362                canvas.saveLayer(right - length, top, right, bottom, null, flags);
15363            }
15364        } else {
15365            scrollabilityCache.setFadeColor(solidColor);
15366        }
15367
15368        // Step 3, draw the content
15369        if (!dirtyOpaque) onDraw(canvas);
15370
15371        // Step 4, draw the children
15372        dispatchDraw(canvas);
15373
15374        // Step 5, draw the fade effect and restore layers
15375        final Paint p = scrollabilityCache.paint;
15376        final Matrix matrix = scrollabilityCache.matrix;
15377        final Shader fade = scrollabilityCache.shader;
15378
15379        if (drawTop) {
15380            matrix.setScale(1, fadeHeight * topFadeStrength);
15381            matrix.postTranslate(left, top);
15382            fade.setLocalMatrix(matrix);
15383            p.setShader(fade);
15384            canvas.drawRect(left, top, right, top + length, p);
15385        }
15386
15387        if (drawBottom) {
15388            matrix.setScale(1, fadeHeight * bottomFadeStrength);
15389            matrix.postRotate(180);
15390            matrix.postTranslate(left, bottom);
15391            fade.setLocalMatrix(matrix);
15392            p.setShader(fade);
15393            canvas.drawRect(left, bottom - length, right, bottom, p);
15394        }
15395
15396        if (drawLeft) {
15397            matrix.setScale(1, fadeHeight * leftFadeStrength);
15398            matrix.postRotate(-90);
15399            matrix.postTranslate(left, top);
15400            fade.setLocalMatrix(matrix);
15401            p.setShader(fade);
15402            canvas.drawRect(left, top, left + length, bottom, p);
15403        }
15404
15405        if (drawRight) {
15406            matrix.setScale(1, fadeHeight * rightFadeStrength);
15407            matrix.postRotate(90);
15408            matrix.postTranslate(right, top);
15409            fade.setLocalMatrix(matrix);
15410            p.setShader(fade);
15411            canvas.drawRect(right - length, top, right, bottom, p);
15412        }
15413
15414        canvas.restoreToCount(saveCount);
15415
15416        // Step 6, draw decorations (scrollbars)
15417        onDrawScrollBars(canvas);
15418
15419        if (mOverlay != null && !mOverlay.isEmpty()) {
15420            mOverlay.getOverlayView().dispatchDraw(canvas);
15421        }
15422    }
15423
15424    /**
15425     * Draws the background onto the specified canvas.
15426     *
15427     * @param canvas Canvas on which to draw the background
15428     */
15429    private void drawBackground(Canvas canvas) {
15430        final Drawable background = mBackground;
15431        if (background == null) {
15432            return;
15433        }
15434
15435        if (mBackgroundSizeChanged) {
15436            background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
15437            mBackgroundSizeChanged = false;
15438            rebuildOutline();
15439        }
15440
15441        // Attempt to use a display list if requested.
15442        if (canvas.isHardwareAccelerated() && mAttachInfo != null
15443                && mAttachInfo.mHardwareRenderer != null) {
15444            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15445
15446            final RenderNode renderNode = mBackgroundRenderNode;
15447            if (renderNode != null && renderNode.isValid()) {
15448                setBackgroundRenderNodeProperties(renderNode);
15449                ((HardwareCanvas) canvas).drawRenderNode(renderNode);
15450                return;
15451            }
15452        }
15453
15454        final int scrollX = mScrollX;
15455        final int scrollY = mScrollY;
15456        if ((scrollX | scrollY) == 0) {
15457            background.draw(canvas);
15458        } else {
15459            canvas.translate(scrollX, scrollY);
15460            background.draw(canvas);
15461            canvas.translate(-scrollX, -scrollY);
15462        }
15463    }
15464
15465    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
15466        renderNode.setTranslationX(mScrollX);
15467        renderNode.setTranslationY(mScrollY);
15468    }
15469
15470    /**
15471     * Creates a new display list or updates the existing display list for the
15472     * specified Drawable.
15473     *
15474     * @param drawable Drawable for which to create a display list
15475     * @param renderNode Existing RenderNode, or {@code null}
15476     * @return A valid display list for the specified drawable
15477     */
15478    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15479        if (renderNode == null) {
15480            renderNode = RenderNode.create(drawable.getClass().getName(), this);
15481        }
15482
15483        final Rect bounds = drawable.getBounds();
15484        final int width = bounds.width();
15485        final int height = bounds.height();
15486        final HardwareCanvas canvas = renderNode.start(width, height);
15487
15488        // Reverse left/top translation done by drawable canvas, which will
15489        // instead be applied by rendernode's LTRB bounds below. This way, the
15490        // drawable's bounds match with its rendernode bounds and its content
15491        // will lie within those bounds in the rendernode tree.
15492        canvas.translate(-bounds.left, -bounds.top);
15493
15494        try {
15495            drawable.draw(canvas);
15496        } finally {
15497            renderNode.end(canvas);
15498        }
15499
15500        // Set up drawable properties that are view-independent.
15501        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15502        renderNode.setProjectBackwards(drawable.isProjected());
15503        renderNode.setProjectionReceiver(true);
15504        renderNode.setClipToBounds(false);
15505        return renderNode;
15506    }
15507
15508    /**
15509     * Returns the overlay for this view, creating it if it does not yet exist.
15510     * Adding drawables to the overlay will cause them to be displayed whenever
15511     * the view itself is redrawn. Objects in the overlay should be actively
15512     * managed: remove them when they should not be displayed anymore. The
15513     * overlay will always have the same size as its host view.
15514     *
15515     * <p>Note: Overlays do not currently work correctly with {@link
15516     * SurfaceView} or {@link TextureView}; contents in overlays for these
15517     * types of views may not display correctly.</p>
15518     *
15519     * @return The ViewOverlay object for this view.
15520     * @see ViewOverlay
15521     */
15522    public ViewOverlay getOverlay() {
15523        if (mOverlay == null) {
15524            mOverlay = new ViewOverlay(mContext, this);
15525        }
15526        return mOverlay;
15527    }
15528
15529    /**
15530     * Override this if your view is known to always be drawn on top of a solid color background,
15531     * and needs to draw fading edges. Returning a non-zero color enables the view system to
15532     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15533     * should be set to 0xFF.
15534     *
15535     * @see #setVerticalFadingEdgeEnabled(boolean)
15536     * @see #setHorizontalFadingEdgeEnabled(boolean)
15537     *
15538     * @return The known solid color background for this view, or 0 if the color may vary
15539     */
15540    @ViewDebug.ExportedProperty(category = "drawing")
15541    @ColorInt
15542    public int getSolidColor() {
15543        return 0;
15544    }
15545
15546    /**
15547     * Build a human readable string representation of the specified view flags.
15548     *
15549     * @param flags the view flags to convert to a string
15550     * @return a String representing the supplied flags
15551     */
15552    private static String printFlags(int flags) {
15553        String output = "";
15554        int numFlags = 0;
15555        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15556            output += "TAKES_FOCUS";
15557            numFlags++;
15558        }
15559
15560        switch (flags & VISIBILITY_MASK) {
15561        case INVISIBLE:
15562            if (numFlags > 0) {
15563                output += " ";
15564            }
15565            output += "INVISIBLE";
15566            // USELESS HERE numFlags++;
15567            break;
15568        case GONE:
15569            if (numFlags > 0) {
15570                output += " ";
15571            }
15572            output += "GONE";
15573            // USELESS HERE numFlags++;
15574            break;
15575        default:
15576            break;
15577        }
15578        return output;
15579    }
15580
15581    /**
15582     * Build a human readable string representation of the specified private
15583     * view flags.
15584     *
15585     * @param privateFlags the private view flags to convert to a string
15586     * @return a String representing the supplied flags
15587     */
15588    private static String printPrivateFlags(int privateFlags) {
15589        String output = "";
15590        int numFlags = 0;
15591
15592        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15593            output += "WANTS_FOCUS";
15594            numFlags++;
15595        }
15596
15597        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15598            if (numFlags > 0) {
15599                output += " ";
15600            }
15601            output += "FOCUSED";
15602            numFlags++;
15603        }
15604
15605        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15606            if (numFlags > 0) {
15607                output += " ";
15608            }
15609            output += "SELECTED";
15610            numFlags++;
15611        }
15612
15613        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15614            if (numFlags > 0) {
15615                output += " ";
15616            }
15617            output += "IS_ROOT_NAMESPACE";
15618            numFlags++;
15619        }
15620
15621        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15622            if (numFlags > 0) {
15623                output += " ";
15624            }
15625            output += "HAS_BOUNDS";
15626            numFlags++;
15627        }
15628
15629        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15630            if (numFlags > 0) {
15631                output += " ";
15632            }
15633            output += "DRAWN";
15634            // USELESS HERE numFlags++;
15635        }
15636        return output;
15637    }
15638
15639    /**
15640     * <p>Indicates whether or not this view's layout will be requested during
15641     * the next hierarchy layout pass.</p>
15642     *
15643     * @return true if the layout will be forced during next layout pass
15644     */
15645    public boolean isLayoutRequested() {
15646        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15647    }
15648
15649    /**
15650     * Return true if o is a ViewGroup that is laying out using optical bounds.
15651     * @hide
15652     */
15653    public static boolean isLayoutModeOptical(Object o) {
15654        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15655    }
15656
15657    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15658        Insets parentInsets = mParent instanceof View ?
15659                ((View) mParent).getOpticalInsets() : Insets.NONE;
15660        Insets childInsets = getOpticalInsets();
15661        return setFrame(
15662                left   + parentInsets.left - childInsets.left,
15663                top    + parentInsets.top  - childInsets.top,
15664                right  + parentInsets.left + childInsets.right,
15665                bottom + parentInsets.top  + childInsets.bottom);
15666    }
15667
15668    /**
15669     * Assign a size and position to a view and all of its
15670     * descendants
15671     *
15672     * <p>This is the second phase of the layout mechanism.
15673     * (The first is measuring). In this phase, each parent calls
15674     * layout on all of its children to position them.
15675     * This is typically done using the child measurements
15676     * that were stored in the measure pass().</p>
15677     *
15678     * <p>Derived classes should not override this method.
15679     * Derived classes with children should override
15680     * onLayout. In that method, they should
15681     * call layout on each of their children.</p>
15682     *
15683     * @param l Left position, relative to parent
15684     * @param t Top position, relative to parent
15685     * @param r Right position, relative to parent
15686     * @param b Bottom position, relative to parent
15687     */
15688    @SuppressWarnings({"unchecked"})
15689    public void layout(int l, int t, int r, int b) {
15690        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15691            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15692            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15693        }
15694
15695        int oldL = mLeft;
15696        int oldT = mTop;
15697        int oldB = mBottom;
15698        int oldR = mRight;
15699
15700        boolean changed = isLayoutModeOptical(mParent) ?
15701                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15702
15703        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15704            onLayout(changed, l, t, r, b);
15705            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15706
15707            ListenerInfo li = mListenerInfo;
15708            if (li != null && li.mOnLayoutChangeListeners != null) {
15709                ArrayList<OnLayoutChangeListener> listenersCopy =
15710                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15711                int numListeners = listenersCopy.size();
15712                for (int i = 0; i < numListeners; ++i) {
15713                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15714                }
15715            }
15716        }
15717
15718        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15719        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15720    }
15721
15722    /**
15723     * Called from layout when this view should
15724     * assign a size and position to each of its children.
15725     *
15726     * Derived classes with children should override
15727     * this method and call layout on each of
15728     * their children.
15729     * @param changed This is a new size or position for this view
15730     * @param left Left position, relative to parent
15731     * @param top Top position, relative to parent
15732     * @param right Right position, relative to parent
15733     * @param bottom Bottom position, relative to parent
15734     */
15735    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15736    }
15737
15738    /**
15739     * Assign a size and position to this view.
15740     *
15741     * This is called from layout.
15742     *
15743     * @param left Left position, relative to parent
15744     * @param top Top position, relative to parent
15745     * @param right Right position, relative to parent
15746     * @param bottom Bottom position, relative to parent
15747     * @return true if the new size and position are different than the
15748     *         previous ones
15749     * {@hide}
15750     */
15751    protected boolean setFrame(int left, int top, int right, int bottom) {
15752        boolean changed = false;
15753
15754        if (DBG) {
15755            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15756                    + right + "," + bottom + ")");
15757        }
15758
15759        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15760            changed = true;
15761
15762            // Remember our drawn bit
15763            int drawn = mPrivateFlags & PFLAG_DRAWN;
15764
15765            int oldWidth = mRight - mLeft;
15766            int oldHeight = mBottom - mTop;
15767            int newWidth = right - left;
15768            int newHeight = bottom - top;
15769            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15770
15771            // Invalidate our old position
15772            invalidate(sizeChanged);
15773
15774            mLeft = left;
15775            mTop = top;
15776            mRight = right;
15777            mBottom = bottom;
15778            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15779
15780            mPrivateFlags |= PFLAG_HAS_BOUNDS;
15781
15782
15783            if (sizeChanged) {
15784                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15785            }
15786
15787            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
15788                // If we are visible, force the DRAWN bit to on so that
15789                // this invalidate will go through (at least to our parent).
15790                // This is because someone may have invalidated this view
15791                // before this call to setFrame came in, thereby clearing
15792                // the DRAWN bit.
15793                mPrivateFlags |= PFLAG_DRAWN;
15794                invalidate(sizeChanged);
15795                // parent display list may need to be recreated based on a change in the bounds
15796                // of any child
15797                invalidateParentCaches();
15798            }
15799
15800            // Reset drawn bit to original value (invalidate turns it off)
15801            mPrivateFlags |= drawn;
15802
15803            mBackgroundSizeChanged = true;
15804
15805            notifySubtreeAccessibilityStateChangedIfNeeded();
15806        }
15807        return changed;
15808    }
15809
15810    /**
15811     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
15812     * @hide
15813     */
15814    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
15815        setFrame(left, top, right, bottom);
15816    }
15817
15818    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15819        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15820        if (mOverlay != null) {
15821            mOverlay.getOverlayView().setRight(newWidth);
15822            mOverlay.getOverlayView().setBottom(newHeight);
15823        }
15824        rebuildOutline();
15825    }
15826
15827    /**
15828     * Finalize inflating a view from XML.  This is called as the last phase
15829     * of inflation, after all child views have been added.
15830     *
15831     * <p>Even if the subclass overrides onFinishInflate, they should always be
15832     * sure to call the super method, so that we get called.
15833     */
15834    protected void onFinishInflate() {
15835    }
15836
15837    /**
15838     * Returns the resources associated with this view.
15839     *
15840     * @return Resources object.
15841     */
15842    public Resources getResources() {
15843        return mResources;
15844    }
15845
15846    /**
15847     * Invalidates the specified Drawable.
15848     *
15849     * @param drawable the drawable to invalidate
15850     */
15851    @Override
15852    public void invalidateDrawable(@NonNull Drawable drawable) {
15853        if (verifyDrawable(drawable)) {
15854            final Rect dirty = drawable.getDirtyBounds();
15855            final int scrollX = mScrollX;
15856            final int scrollY = mScrollY;
15857
15858            invalidate(dirty.left + scrollX, dirty.top + scrollY,
15859                    dirty.right + scrollX, dirty.bottom + scrollY);
15860            rebuildOutline();
15861        }
15862    }
15863
15864    /**
15865     * Schedules an action on a drawable to occur at a specified time.
15866     *
15867     * @param who the recipient of the action
15868     * @param what the action to run on the drawable
15869     * @param when the time at which the action must occur. Uses the
15870     *        {@link SystemClock#uptimeMillis} timebase.
15871     */
15872    @Override
15873    public void scheduleDrawable(Drawable who, Runnable what, long when) {
15874        if (verifyDrawable(who) && what != null) {
15875            final long delay = when - SystemClock.uptimeMillis();
15876            if (mAttachInfo != null) {
15877                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15878                        Choreographer.CALLBACK_ANIMATION, what, who,
15879                        Choreographer.subtractFrameDelay(delay));
15880            } else {
15881                ViewRootImpl.getRunQueue().postDelayed(what, delay);
15882            }
15883        }
15884    }
15885
15886    /**
15887     * Cancels a scheduled action on a drawable.
15888     *
15889     * @param who the recipient of the action
15890     * @param what the action to cancel
15891     */
15892    @Override
15893    public void unscheduleDrawable(Drawable who, Runnable what) {
15894        if (verifyDrawable(who) && what != null) {
15895            if (mAttachInfo != null) {
15896                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15897                        Choreographer.CALLBACK_ANIMATION, what, who);
15898            }
15899            ViewRootImpl.getRunQueue().removeCallbacks(what);
15900        }
15901    }
15902
15903    /**
15904     * Unschedule any events associated with the given Drawable.  This can be
15905     * used when selecting a new Drawable into a view, so that the previous
15906     * one is completely unscheduled.
15907     *
15908     * @param who The Drawable to unschedule.
15909     *
15910     * @see #drawableStateChanged
15911     */
15912    public void unscheduleDrawable(Drawable who) {
15913        if (mAttachInfo != null && who != null) {
15914            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15915                    Choreographer.CALLBACK_ANIMATION, null, who);
15916        }
15917    }
15918
15919    /**
15920     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15921     * that the View directionality can and will be resolved before its Drawables.
15922     *
15923     * Will call {@link View#onResolveDrawables} when resolution is done.
15924     *
15925     * @hide
15926     */
15927    protected void resolveDrawables() {
15928        // Drawables resolution may need to happen before resolving the layout direction (which is
15929        // done only during the measure() call).
15930        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15931        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15932        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15933        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15934        // direction to be resolved as its resolved value will be the same as its raw value.
15935        if (!isLayoutDirectionResolved() &&
15936                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15937            return;
15938        }
15939
15940        final int layoutDirection = isLayoutDirectionResolved() ?
15941                getLayoutDirection() : getRawLayoutDirection();
15942
15943        if (mBackground != null) {
15944            mBackground.setLayoutDirection(layoutDirection);
15945        }
15946        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15947        onResolveDrawables(layoutDirection);
15948    }
15949
15950    boolean areDrawablesResolved() {
15951        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15952    }
15953
15954    /**
15955     * Called when layout direction has been resolved.
15956     *
15957     * The default implementation does nothing.
15958     *
15959     * @param layoutDirection The resolved layout direction.
15960     *
15961     * @see #LAYOUT_DIRECTION_LTR
15962     * @see #LAYOUT_DIRECTION_RTL
15963     *
15964     * @hide
15965     */
15966    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15967    }
15968
15969    /**
15970     * @hide
15971     */
15972    protected void resetResolvedDrawables() {
15973        resetResolvedDrawablesInternal();
15974    }
15975
15976    void resetResolvedDrawablesInternal() {
15977        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15978    }
15979
15980    /**
15981     * If your view subclass is displaying its own Drawable objects, it should
15982     * override this function and return true for any Drawable it is
15983     * displaying.  This allows animations for those drawables to be
15984     * scheduled.
15985     *
15986     * <p>Be sure to call through to the super class when overriding this
15987     * function.
15988     *
15989     * @param who The Drawable to verify.  Return true if it is one you are
15990     *            displaying, else return the result of calling through to the
15991     *            super class.
15992     *
15993     * @return boolean If true than the Drawable is being displayed in the
15994     *         view; else false and it is not allowed to animate.
15995     *
15996     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15997     * @see #drawableStateChanged()
15998     */
15999    protected boolean verifyDrawable(Drawable who) {
16000        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who);
16001    }
16002
16003    /**
16004     * This function is called whenever the state of the view changes in such
16005     * a way that it impacts the state of drawables being shown.
16006     * <p>
16007     * If the View has a StateListAnimator, it will also be called to run necessary state
16008     * change animations.
16009     * <p>
16010     * Be sure to call through to the superclass when overriding this function.
16011     *
16012     * @see Drawable#setState(int[])
16013     */
16014    protected void drawableStateChanged() {
16015        final int[] state = getDrawableState();
16016
16017        final Drawable d = mBackground;
16018        if (d != null && d.isStateful()) {
16019            d.setState(state);
16020        }
16021
16022        if (mScrollCache != null) {
16023            final Drawable scrollBar = mScrollCache.scrollBar;
16024            if (scrollBar != null && scrollBar.isStateful()) {
16025                scrollBar.setState(state);
16026            }
16027        }
16028
16029        if (mStateListAnimator != null) {
16030            mStateListAnimator.setState(state);
16031        }
16032    }
16033
16034    /**
16035     * This function is called whenever the view hotspot changes and needs to
16036     * be propagated to drawables or child views managed by the view.
16037     * <p>
16038     * Dispatching to child views is handled by
16039     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16040     * <p>
16041     * Be sure to call through to the superclass when overriding this function.
16042     *
16043     * @param x hotspot x coordinate
16044     * @param y hotspot y coordinate
16045     */
16046    public void drawableHotspotChanged(float x, float y) {
16047        if (mBackground != null) {
16048            mBackground.setHotspot(x, y);
16049        }
16050
16051        dispatchDrawableHotspotChanged(x, y);
16052    }
16053
16054    /**
16055     * Dispatches drawableHotspotChanged to all of this View's children.
16056     *
16057     * @param x hotspot x coordinate
16058     * @param y hotspot y coordinate
16059     * @see #drawableHotspotChanged(float, float)
16060     */
16061    public void dispatchDrawableHotspotChanged(float x, float y) {
16062    }
16063
16064    /**
16065     * Call this to force a view to update its drawable state. This will cause
16066     * drawableStateChanged to be called on this view. Views that are interested
16067     * in the new state should call getDrawableState.
16068     *
16069     * @see #drawableStateChanged
16070     * @see #getDrawableState
16071     */
16072    public void refreshDrawableState() {
16073        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16074        drawableStateChanged();
16075
16076        ViewParent parent = mParent;
16077        if (parent != null) {
16078            parent.childDrawableStateChanged(this);
16079        }
16080    }
16081
16082    /**
16083     * Return an array of resource IDs of the drawable states representing the
16084     * current state of the view.
16085     *
16086     * @return The current drawable state
16087     *
16088     * @see Drawable#setState(int[])
16089     * @see #drawableStateChanged()
16090     * @see #onCreateDrawableState(int)
16091     */
16092    public final int[] getDrawableState() {
16093        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16094            return mDrawableState;
16095        } else {
16096            mDrawableState = onCreateDrawableState(0);
16097            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16098            return mDrawableState;
16099        }
16100    }
16101
16102    /**
16103     * Generate the new {@link android.graphics.drawable.Drawable} state for
16104     * this view. This is called by the view
16105     * system when the cached Drawable state is determined to be invalid.  To
16106     * retrieve the current state, you should use {@link #getDrawableState}.
16107     *
16108     * @param extraSpace if non-zero, this is the number of extra entries you
16109     * would like in the returned array in which you can place your own
16110     * states.
16111     *
16112     * @return Returns an array holding the current {@link Drawable} state of
16113     * the view.
16114     *
16115     * @see #mergeDrawableStates(int[], int[])
16116     */
16117    protected int[] onCreateDrawableState(int extraSpace) {
16118        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
16119                mParent instanceof View) {
16120            return ((View) mParent).onCreateDrawableState(extraSpace);
16121        }
16122
16123        int[] drawableState;
16124
16125        int privateFlags = mPrivateFlags;
16126
16127        int viewStateIndex = 0;
16128        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
16129        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
16130        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
16131        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
16132        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
16133        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
16134        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16135                HardwareRenderer.isAvailable()) {
16136            // This is set if HW acceleration is requested, even if the current
16137            // process doesn't allow it.  This is just to allow app preview
16138            // windows to better match their app.
16139            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
16140        }
16141        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
16142
16143        final int privateFlags2 = mPrivateFlags2;
16144        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
16145            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
16146        }
16147        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
16148            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
16149        }
16150
16151        drawableState = StateSet.get(viewStateIndex);
16152
16153        //noinspection ConstantIfStatement
16154        if (false) {
16155            Log.i("View", "drawableStateIndex=" + viewStateIndex);
16156            Log.i("View", toString()
16157                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16158                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16159                    + " fo=" + hasFocus()
16160                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16161                    + " wf=" + hasWindowFocus()
16162                    + ": " + Arrays.toString(drawableState));
16163        }
16164
16165        if (extraSpace == 0) {
16166            return drawableState;
16167        }
16168
16169        final int[] fullState;
16170        if (drawableState != null) {
16171            fullState = new int[drawableState.length + extraSpace];
16172            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16173        } else {
16174            fullState = new int[extraSpace];
16175        }
16176
16177        return fullState;
16178    }
16179
16180    /**
16181     * Merge your own state values in <var>additionalState</var> into the base
16182     * state values <var>baseState</var> that were returned by
16183     * {@link #onCreateDrawableState(int)}.
16184     *
16185     * @param baseState The base state values returned by
16186     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16187     * own additional state values.
16188     *
16189     * @param additionalState The additional state values you would like
16190     * added to <var>baseState</var>; this array is not modified.
16191     *
16192     * @return As a convenience, the <var>baseState</var> array you originally
16193     * passed into the function is returned.
16194     *
16195     * @see #onCreateDrawableState(int)
16196     */
16197    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16198        final int N = baseState.length;
16199        int i = N - 1;
16200        while (i >= 0 && baseState[i] == 0) {
16201            i--;
16202        }
16203        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16204        return baseState;
16205    }
16206
16207    /**
16208     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16209     * on all Drawable objects associated with this view.
16210     * <p>
16211     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16212     * attached to this view.
16213     */
16214    public void jumpDrawablesToCurrentState() {
16215        if (mBackground != null) {
16216            mBackground.jumpToCurrentState();
16217        }
16218        if (mStateListAnimator != null) {
16219            mStateListAnimator.jumpToCurrentState();
16220        }
16221    }
16222
16223    /**
16224     * Sets the background color for this view.
16225     * @param color the color of the background
16226     */
16227    @RemotableViewMethod
16228    public void setBackgroundColor(@ColorInt int color) {
16229        if (mBackground instanceof ColorDrawable) {
16230            ((ColorDrawable) mBackground.mutate()).setColor(color);
16231            computeOpaqueFlags();
16232            mBackgroundResource = 0;
16233        } else {
16234            setBackground(new ColorDrawable(color));
16235        }
16236    }
16237
16238    /**
16239     * If the view has a ColorDrawable background, returns the color of that
16240     * drawable.
16241     *
16242     * @return The color of the ColorDrawable background, if set, otherwise 0.
16243     */
16244    @ColorInt
16245    public int getBackgroundColor() {
16246        if (mBackground instanceof ColorDrawable) {
16247            return ((ColorDrawable) mBackground).getColor();
16248        }
16249        return 0;
16250    }
16251
16252    /**
16253     * Set the background to a given resource. The resource should refer to
16254     * a Drawable object or 0 to remove the background.
16255     * @param resid The identifier of the resource.
16256     *
16257     * @attr ref android.R.styleable#View_background
16258     */
16259    @RemotableViewMethod
16260    public void setBackgroundResource(@DrawableRes int resid) {
16261        if (resid != 0 && resid == mBackgroundResource) {
16262            return;
16263        }
16264
16265        Drawable d = null;
16266        if (resid != 0) {
16267            d = mContext.getDrawable(resid);
16268        }
16269        setBackground(d);
16270
16271        mBackgroundResource = resid;
16272    }
16273
16274    /**
16275     * Set the background to a given Drawable, or remove the background. If the
16276     * background has padding, this View's padding is set to the background's
16277     * padding. However, when a background is removed, this View's padding isn't
16278     * touched. If setting the padding is desired, please use
16279     * {@link #setPadding(int, int, int, int)}.
16280     *
16281     * @param background The Drawable to use as the background, or null to remove the
16282     *        background
16283     */
16284    public void setBackground(Drawable background) {
16285        //noinspection deprecation
16286        setBackgroundDrawable(background);
16287    }
16288
16289    /**
16290     * @deprecated use {@link #setBackground(Drawable)} instead
16291     */
16292    @Deprecated
16293    public void setBackgroundDrawable(Drawable background) {
16294        computeOpaqueFlags();
16295
16296        if (background == mBackground) {
16297            return;
16298        }
16299
16300        boolean requestLayout = false;
16301
16302        mBackgroundResource = 0;
16303
16304        /*
16305         * Regardless of whether we're setting a new background or not, we want
16306         * to clear the previous drawable.
16307         */
16308        if (mBackground != null) {
16309            mBackground.setCallback(null);
16310            unscheduleDrawable(mBackground);
16311        }
16312
16313        if (background != null) {
16314            Rect padding = sThreadLocal.get();
16315            if (padding == null) {
16316                padding = new Rect();
16317                sThreadLocal.set(padding);
16318            }
16319            resetResolvedDrawablesInternal();
16320            background.setLayoutDirection(getLayoutDirection());
16321            if (background.getPadding(padding)) {
16322                resetResolvedPaddingInternal();
16323                switch (background.getLayoutDirection()) {
16324                    case LAYOUT_DIRECTION_RTL:
16325                        mUserPaddingLeftInitial = padding.right;
16326                        mUserPaddingRightInitial = padding.left;
16327                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16328                        break;
16329                    case LAYOUT_DIRECTION_LTR:
16330                    default:
16331                        mUserPaddingLeftInitial = padding.left;
16332                        mUserPaddingRightInitial = padding.right;
16333                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16334                }
16335                mLeftPaddingDefined = false;
16336                mRightPaddingDefined = false;
16337            }
16338
16339            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
16340            // if it has a different minimum size, we should layout again
16341            if (mBackground == null
16342                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
16343                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16344                requestLayout = true;
16345            }
16346
16347            background.setCallback(this);
16348            if (background.isStateful()) {
16349                background.setState(getDrawableState());
16350            }
16351            background.setVisible(getVisibility() == VISIBLE, false);
16352            mBackground = background;
16353
16354            applyBackgroundTint();
16355
16356            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16357                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16358                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16359                requestLayout = true;
16360            }
16361        } else {
16362            /* Remove the background */
16363            mBackground = null;
16364
16365            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16366                /*
16367                 * This view ONLY drew the background before and we're removing
16368                 * the background, so now it won't draw anything
16369                 * (hence we SKIP_DRAW)
16370                 */
16371                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16372                mPrivateFlags |= PFLAG_SKIP_DRAW;
16373            }
16374
16375            /*
16376             * When the background is set, we try to apply its padding to this
16377             * View. When the background is removed, we don't touch this View's
16378             * padding. This is noted in the Javadocs. Hence, we don't need to
16379             * requestLayout(), the invalidate() below is sufficient.
16380             */
16381
16382            // The old background's minimum size could have affected this
16383            // View's layout, so let's requestLayout
16384            requestLayout = true;
16385        }
16386
16387        computeOpaqueFlags();
16388
16389        if (requestLayout) {
16390            requestLayout();
16391        }
16392
16393        mBackgroundSizeChanged = true;
16394        invalidate(true);
16395    }
16396
16397    /**
16398     * Gets the background drawable
16399     *
16400     * @return The drawable used as the background for this view, if any.
16401     *
16402     * @see #setBackground(Drawable)
16403     *
16404     * @attr ref android.R.styleable#View_background
16405     */
16406    public Drawable getBackground() {
16407        return mBackground;
16408    }
16409
16410    /**
16411     * Applies a tint to the background drawable. Does not modify the current tint
16412     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16413     * <p>
16414     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16415     * mutate the drawable and apply the specified tint and tint mode using
16416     * {@link Drawable#setTintList(ColorStateList)}.
16417     *
16418     * @param tint the tint to apply, may be {@code null} to clear tint
16419     *
16420     * @attr ref android.R.styleable#View_backgroundTint
16421     * @see #getBackgroundTintList()
16422     * @see Drawable#setTintList(ColorStateList)
16423     */
16424    public void setBackgroundTintList(@Nullable ColorStateList tint) {
16425        if (mBackgroundTint == null) {
16426            mBackgroundTint = new TintInfo();
16427        }
16428        mBackgroundTint.mTintList = tint;
16429        mBackgroundTint.mHasTintList = true;
16430
16431        applyBackgroundTint();
16432    }
16433
16434    /**
16435     * Return the tint applied to the background drawable, if specified.
16436     *
16437     * @return the tint applied to the background drawable
16438     * @attr ref android.R.styleable#View_backgroundTint
16439     * @see #setBackgroundTintList(ColorStateList)
16440     */
16441    @Nullable
16442    public ColorStateList getBackgroundTintList() {
16443        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16444    }
16445
16446    /**
16447     * Specifies the blending mode used to apply the tint specified by
16448     * {@link #setBackgroundTintList(ColorStateList)}} to the background
16449     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16450     *
16451     * @param tintMode the blending mode used to apply the tint, may be
16452     *                 {@code null} to clear tint
16453     * @attr ref android.R.styleable#View_backgroundTintMode
16454     * @see #getBackgroundTintMode()
16455     * @see Drawable#setTintMode(PorterDuff.Mode)
16456     */
16457    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16458        if (mBackgroundTint == null) {
16459            mBackgroundTint = new TintInfo();
16460        }
16461        mBackgroundTint.mTintMode = tintMode;
16462        mBackgroundTint.mHasTintMode = true;
16463
16464        applyBackgroundTint();
16465    }
16466
16467    /**
16468     * Return the blending mode used to apply the tint to the background
16469     * drawable, if specified.
16470     *
16471     * @return the blending mode used to apply the tint to the background
16472     *         drawable
16473     * @attr ref android.R.styleable#View_backgroundTintMode
16474     * @see #setBackgroundTintMode(PorterDuff.Mode)
16475     */
16476    @Nullable
16477    public PorterDuff.Mode getBackgroundTintMode() {
16478        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16479    }
16480
16481    private void applyBackgroundTint() {
16482        if (mBackground != null && mBackgroundTint != null) {
16483            final TintInfo tintInfo = mBackgroundTint;
16484            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16485                mBackground = mBackground.mutate();
16486
16487                if (tintInfo.mHasTintList) {
16488                    mBackground.setTintList(tintInfo.mTintList);
16489                }
16490
16491                if (tintInfo.mHasTintMode) {
16492                    mBackground.setTintMode(tintInfo.mTintMode);
16493                }
16494
16495                // The drawable (or one of its children) may not have been
16496                // stateful before applying the tint, so let's try again.
16497                if (mBackground.isStateful()) {
16498                    mBackground.setState(getDrawableState());
16499                }
16500            }
16501        }
16502    }
16503
16504    /**
16505     * Sets the padding. The view may add on the space required to display
16506     * the scrollbars, depending on the style and visibility of the scrollbars.
16507     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
16508     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
16509     * from the values set in this call.
16510     *
16511     * @attr ref android.R.styleable#View_padding
16512     * @attr ref android.R.styleable#View_paddingBottom
16513     * @attr ref android.R.styleable#View_paddingLeft
16514     * @attr ref android.R.styleable#View_paddingRight
16515     * @attr ref android.R.styleable#View_paddingTop
16516     * @param left the left padding in pixels
16517     * @param top the top padding in pixels
16518     * @param right the right padding in pixels
16519     * @param bottom the bottom padding in pixels
16520     */
16521    public void setPadding(int left, int top, int right, int bottom) {
16522        resetResolvedPaddingInternal();
16523
16524        mUserPaddingStart = UNDEFINED_PADDING;
16525        mUserPaddingEnd = UNDEFINED_PADDING;
16526
16527        mUserPaddingLeftInitial = left;
16528        mUserPaddingRightInitial = right;
16529
16530        mLeftPaddingDefined = true;
16531        mRightPaddingDefined = true;
16532
16533        internalSetPadding(left, top, right, bottom);
16534    }
16535
16536    /**
16537     * @hide
16538     */
16539    protected void internalSetPadding(int left, int top, int right, int bottom) {
16540        mUserPaddingLeft = left;
16541        mUserPaddingRight = right;
16542        mUserPaddingBottom = bottom;
16543
16544        final int viewFlags = mViewFlags;
16545        boolean changed = false;
16546
16547        // Common case is there are no scroll bars.
16548        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
16549            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
16550                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
16551                        ? 0 : getVerticalScrollbarWidth();
16552                switch (mVerticalScrollbarPosition) {
16553                    case SCROLLBAR_POSITION_DEFAULT:
16554                        if (isLayoutRtl()) {
16555                            left += offset;
16556                        } else {
16557                            right += offset;
16558                        }
16559                        break;
16560                    case SCROLLBAR_POSITION_RIGHT:
16561                        right += offset;
16562                        break;
16563                    case SCROLLBAR_POSITION_LEFT:
16564                        left += offset;
16565                        break;
16566                }
16567            }
16568            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
16569                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
16570                        ? 0 : getHorizontalScrollbarHeight();
16571            }
16572        }
16573
16574        if (mPaddingLeft != left) {
16575            changed = true;
16576            mPaddingLeft = left;
16577        }
16578        if (mPaddingTop != top) {
16579            changed = true;
16580            mPaddingTop = top;
16581        }
16582        if (mPaddingRight != right) {
16583            changed = true;
16584            mPaddingRight = right;
16585        }
16586        if (mPaddingBottom != bottom) {
16587            changed = true;
16588            mPaddingBottom = bottom;
16589        }
16590
16591        if (changed) {
16592            requestLayout();
16593            invalidateOutline();
16594        }
16595    }
16596
16597    /**
16598     * Sets the relative padding. The view may add on the space required to display
16599     * the scrollbars, depending on the style and visibility of the scrollbars.
16600     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
16601     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
16602     * from the values set in this call.
16603     *
16604     * @attr ref android.R.styleable#View_padding
16605     * @attr ref android.R.styleable#View_paddingBottom
16606     * @attr ref android.R.styleable#View_paddingStart
16607     * @attr ref android.R.styleable#View_paddingEnd
16608     * @attr ref android.R.styleable#View_paddingTop
16609     * @param start the start padding in pixels
16610     * @param top the top padding in pixels
16611     * @param end the end padding in pixels
16612     * @param bottom the bottom padding in pixels
16613     */
16614    public void setPaddingRelative(int start, int top, int end, int bottom) {
16615        resetResolvedPaddingInternal();
16616
16617        mUserPaddingStart = start;
16618        mUserPaddingEnd = end;
16619        mLeftPaddingDefined = true;
16620        mRightPaddingDefined = true;
16621
16622        switch(getLayoutDirection()) {
16623            case LAYOUT_DIRECTION_RTL:
16624                mUserPaddingLeftInitial = end;
16625                mUserPaddingRightInitial = start;
16626                internalSetPadding(end, top, start, bottom);
16627                break;
16628            case LAYOUT_DIRECTION_LTR:
16629            default:
16630                mUserPaddingLeftInitial = start;
16631                mUserPaddingRightInitial = end;
16632                internalSetPadding(start, top, end, bottom);
16633        }
16634    }
16635
16636    /**
16637     * Returns the top padding of this view.
16638     *
16639     * @return the top padding in pixels
16640     */
16641    public int getPaddingTop() {
16642        return mPaddingTop;
16643    }
16644
16645    /**
16646     * Returns the bottom padding of this view. If there are inset and enabled
16647     * scrollbars, this value may include the space required to display the
16648     * scrollbars as well.
16649     *
16650     * @return the bottom padding in pixels
16651     */
16652    public int getPaddingBottom() {
16653        return mPaddingBottom;
16654    }
16655
16656    /**
16657     * Returns the left padding of this view. If there are inset and enabled
16658     * scrollbars, this value may include the space required to display the
16659     * scrollbars as well.
16660     *
16661     * @return the left padding in pixels
16662     */
16663    public int getPaddingLeft() {
16664        if (!isPaddingResolved()) {
16665            resolvePadding();
16666        }
16667        return mPaddingLeft;
16668    }
16669
16670    /**
16671     * Returns the start padding of this view depending on its resolved layout direction.
16672     * If there are inset and enabled scrollbars, this value may include the space
16673     * required to display the scrollbars as well.
16674     *
16675     * @return the start padding in pixels
16676     */
16677    public int getPaddingStart() {
16678        if (!isPaddingResolved()) {
16679            resolvePadding();
16680        }
16681        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16682                mPaddingRight : mPaddingLeft;
16683    }
16684
16685    /**
16686     * Returns the right padding of this view. If there are inset and enabled
16687     * scrollbars, this value may include the space required to display the
16688     * scrollbars as well.
16689     *
16690     * @return the right padding in pixels
16691     */
16692    public int getPaddingRight() {
16693        if (!isPaddingResolved()) {
16694            resolvePadding();
16695        }
16696        return mPaddingRight;
16697    }
16698
16699    /**
16700     * Returns the end padding of this view depending on its resolved layout direction.
16701     * If there are inset and enabled scrollbars, this value may include the space
16702     * required to display the scrollbars as well.
16703     *
16704     * @return the end padding in pixels
16705     */
16706    public int getPaddingEnd() {
16707        if (!isPaddingResolved()) {
16708            resolvePadding();
16709        }
16710        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16711                mPaddingLeft : mPaddingRight;
16712    }
16713
16714    /**
16715     * Return if the padding has been set through relative values
16716     * {@link #setPaddingRelative(int, int, int, int)} or through
16717     * @attr ref android.R.styleable#View_paddingStart or
16718     * @attr ref android.R.styleable#View_paddingEnd
16719     *
16720     * @return true if the padding is relative or false if it is not.
16721     */
16722    public boolean isPaddingRelative() {
16723        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
16724    }
16725
16726    Insets computeOpticalInsets() {
16727        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
16728    }
16729
16730    /**
16731     * @hide
16732     */
16733    public void resetPaddingToInitialValues() {
16734        if (isRtlCompatibilityMode()) {
16735            mPaddingLeft = mUserPaddingLeftInitial;
16736            mPaddingRight = mUserPaddingRightInitial;
16737            return;
16738        }
16739        if (isLayoutRtl()) {
16740            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16741            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16742        } else {
16743            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16744            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16745        }
16746    }
16747
16748    /**
16749     * @hide
16750     */
16751    public Insets getOpticalInsets() {
16752        if (mLayoutInsets == null) {
16753            mLayoutInsets = computeOpticalInsets();
16754        }
16755        return mLayoutInsets;
16756    }
16757
16758    /**
16759     * Set this view's optical insets.
16760     *
16761     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
16762     * property. Views that compute their own optical insets should call it as part of measurement.
16763     * This method does not request layout. If you are setting optical insets outside of
16764     * measure/layout itself you will want to call requestLayout() yourself.
16765     * </p>
16766     * @hide
16767     */
16768    public void setOpticalInsets(Insets insets) {
16769        mLayoutInsets = insets;
16770    }
16771
16772    /**
16773     * Changes the selection state of this view. A view can be selected or not.
16774     * Note that selection is not the same as focus. Views are typically
16775     * selected in the context of an AdapterView like ListView or GridView;
16776     * the selected view is the view that is highlighted.
16777     *
16778     * @param selected true if the view must be selected, false otherwise
16779     */
16780    public void setSelected(boolean selected) {
16781        //noinspection DoubleNegation
16782        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16783            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16784            if (!selected) resetPressedState();
16785            invalidate(true);
16786            refreshDrawableState();
16787            dispatchSetSelected(selected);
16788            if (selected) {
16789                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
16790            } else {
16791                notifyViewAccessibilityStateChangedIfNeeded(
16792                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16793            }
16794        }
16795    }
16796
16797    /**
16798     * Dispatch setSelected to all of this View's children.
16799     *
16800     * @see #setSelected(boolean)
16801     *
16802     * @param selected The new selected state
16803     */
16804    protected void dispatchSetSelected(boolean selected) {
16805    }
16806
16807    /**
16808     * Indicates the selection state of this view.
16809     *
16810     * @return true if the view is selected, false otherwise
16811     */
16812    @ViewDebug.ExportedProperty
16813    public boolean isSelected() {
16814        return (mPrivateFlags & PFLAG_SELECTED) != 0;
16815    }
16816
16817    /**
16818     * Changes the activated state of this view. A view can be activated or not.
16819     * Note that activation is not the same as selection.  Selection is
16820     * a transient property, representing the view (hierarchy) the user is
16821     * currently interacting with.  Activation is a longer-term state that the
16822     * user can move views in and out of.  For example, in a list view with
16823     * single or multiple selection enabled, the views in the current selection
16824     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
16825     * here.)  The activated state is propagated down to children of the view it
16826     * is set on.
16827     *
16828     * @param activated true if the view must be activated, false otherwise
16829     */
16830    public void setActivated(boolean activated) {
16831        //noinspection DoubleNegation
16832        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16833            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16834            invalidate(true);
16835            refreshDrawableState();
16836            dispatchSetActivated(activated);
16837        }
16838    }
16839
16840    /**
16841     * Dispatch setActivated to all of this View's children.
16842     *
16843     * @see #setActivated(boolean)
16844     *
16845     * @param activated The new activated state
16846     */
16847    protected void dispatchSetActivated(boolean activated) {
16848    }
16849
16850    /**
16851     * Indicates the activation state of this view.
16852     *
16853     * @return true if the view is activated, false otherwise
16854     */
16855    @ViewDebug.ExportedProperty
16856    public boolean isActivated() {
16857        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16858    }
16859
16860    /**
16861     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16862     * observer can be used to get notifications when global events, like
16863     * layout, happen.
16864     *
16865     * The returned ViewTreeObserver observer is not guaranteed to remain
16866     * valid for the lifetime of this View. If the caller of this method keeps
16867     * a long-lived reference to ViewTreeObserver, it should always check for
16868     * the return value of {@link ViewTreeObserver#isAlive()}.
16869     *
16870     * @return The ViewTreeObserver for this view's hierarchy.
16871     */
16872    public ViewTreeObserver getViewTreeObserver() {
16873        if (mAttachInfo != null) {
16874            return mAttachInfo.mTreeObserver;
16875        }
16876        if (mFloatingTreeObserver == null) {
16877            mFloatingTreeObserver = new ViewTreeObserver();
16878        }
16879        return mFloatingTreeObserver;
16880    }
16881
16882    /**
16883     * <p>Finds the topmost view in the current view hierarchy.</p>
16884     *
16885     * @return the topmost view containing this view
16886     */
16887    public View getRootView() {
16888        if (mAttachInfo != null) {
16889            final View v = mAttachInfo.mRootView;
16890            if (v != null) {
16891                return v;
16892            }
16893        }
16894
16895        View parent = this;
16896
16897        while (parent.mParent != null && parent.mParent instanceof View) {
16898            parent = (View) parent.mParent;
16899        }
16900
16901        return parent;
16902    }
16903
16904    /**
16905     * Transforms a motion event from view-local coordinates to on-screen
16906     * coordinates.
16907     *
16908     * @param ev the view-local motion event
16909     * @return false if the transformation could not be applied
16910     * @hide
16911     */
16912    public boolean toGlobalMotionEvent(MotionEvent ev) {
16913        final AttachInfo info = mAttachInfo;
16914        if (info == null) {
16915            return false;
16916        }
16917
16918        final Matrix m = info.mTmpMatrix;
16919        m.set(Matrix.IDENTITY_MATRIX);
16920        transformMatrixToGlobal(m);
16921        ev.transform(m);
16922        return true;
16923    }
16924
16925    /**
16926     * Transforms a motion event from on-screen coordinates to view-local
16927     * coordinates.
16928     *
16929     * @param ev the on-screen motion event
16930     * @return false if the transformation could not be applied
16931     * @hide
16932     */
16933    public boolean toLocalMotionEvent(MotionEvent ev) {
16934        final AttachInfo info = mAttachInfo;
16935        if (info == null) {
16936            return false;
16937        }
16938
16939        final Matrix m = info.mTmpMatrix;
16940        m.set(Matrix.IDENTITY_MATRIX);
16941        transformMatrixToLocal(m);
16942        ev.transform(m);
16943        return true;
16944    }
16945
16946    /**
16947     * Modifies the input matrix such that it maps view-local coordinates to
16948     * on-screen coordinates.
16949     *
16950     * @param m input matrix to modify
16951     * @hide
16952     */
16953    public void transformMatrixToGlobal(Matrix m) {
16954        final ViewParent parent = mParent;
16955        if (parent instanceof View) {
16956            final View vp = (View) parent;
16957            vp.transformMatrixToGlobal(m);
16958            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
16959        } else if (parent instanceof ViewRootImpl) {
16960            final ViewRootImpl vr = (ViewRootImpl) parent;
16961            vr.transformMatrixToGlobal(m);
16962            m.preTranslate(0, -vr.mCurScrollY);
16963        }
16964
16965        m.preTranslate(mLeft, mTop);
16966
16967        if (!hasIdentityMatrix()) {
16968            m.preConcat(getMatrix());
16969        }
16970    }
16971
16972    /**
16973     * Modifies the input matrix such that it maps on-screen coordinates to
16974     * view-local coordinates.
16975     *
16976     * @param m input matrix to modify
16977     * @hide
16978     */
16979    public void transformMatrixToLocal(Matrix m) {
16980        final ViewParent parent = mParent;
16981        if (parent instanceof View) {
16982            final View vp = (View) parent;
16983            vp.transformMatrixToLocal(m);
16984            m.postTranslate(vp.mScrollX, vp.mScrollY);
16985        } else if (parent instanceof ViewRootImpl) {
16986            final ViewRootImpl vr = (ViewRootImpl) parent;
16987            vr.transformMatrixToLocal(m);
16988            m.postTranslate(0, vr.mCurScrollY);
16989        }
16990
16991        m.postTranslate(-mLeft, -mTop);
16992
16993        if (!hasIdentityMatrix()) {
16994            m.postConcat(getInverseMatrix());
16995        }
16996    }
16997
16998    /**
16999     * @hide
17000     */
17001    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
17002            @ViewDebug.IntToString(from = 0, to = "x"),
17003            @ViewDebug.IntToString(from = 1, to = "y")
17004    })
17005    public int[] getLocationOnScreen() {
17006        int[] location = new int[2];
17007        getLocationOnScreen(location);
17008        return location;
17009    }
17010
17011    /**
17012     * <p>Computes the coordinates of this view on the screen. The argument
17013     * must be an array of two integers. After the method returns, the array
17014     * contains the x and y location in that order.</p>
17015     *
17016     * @param location an array of two integers in which to hold the coordinates
17017     */
17018    public void getLocationOnScreen(int[] location) {
17019        getLocationInWindow(location);
17020
17021        final AttachInfo info = mAttachInfo;
17022        if (info != null) {
17023            location[0] += info.mWindowLeft;
17024            location[1] += info.mWindowTop;
17025        }
17026    }
17027
17028    /**
17029     * <p>Computes the coordinates of this view in its window. The argument
17030     * must be an array of two integers. After the method returns, the array
17031     * contains the x and y location in that order.</p>
17032     *
17033     * @param location an array of two integers in which to hold the coordinates
17034     */
17035    public void getLocationInWindow(int[] location) {
17036        if (location == null || location.length < 2) {
17037            throw new IllegalArgumentException("location must be an array of two integers");
17038        }
17039
17040        if (mAttachInfo == null) {
17041            // When the view is not attached to a window, this method does not make sense
17042            location[0] = location[1] = 0;
17043            return;
17044        }
17045
17046        float[] position = mAttachInfo.mTmpTransformLocation;
17047        position[0] = position[1] = 0.0f;
17048
17049        if (!hasIdentityMatrix()) {
17050            getMatrix().mapPoints(position);
17051        }
17052
17053        position[0] += mLeft;
17054        position[1] += mTop;
17055
17056        ViewParent viewParent = mParent;
17057        while (viewParent instanceof View) {
17058            final View view = (View) viewParent;
17059
17060            position[0] -= view.mScrollX;
17061            position[1] -= view.mScrollY;
17062
17063            if (!view.hasIdentityMatrix()) {
17064                view.getMatrix().mapPoints(position);
17065            }
17066
17067            position[0] += view.mLeft;
17068            position[1] += view.mTop;
17069
17070            viewParent = view.mParent;
17071         }
17072
17073        if (viewParent instanceof ViewRootImpl) {
17074            // *cough*
17075            final ViewRootImpl vr = (ViewRootImpl) viewParent;
17076            position[1] -= vr.mCurScrollY;
17077        }
17078
17079        location[0] = (int) (position[0] + 0.5f);
17080        location[1] = (int) (position[1] + 0.5f);
17081    }
17082
17083    /**
17084     * {@hide}
17085     * @param id the id of the view to be found
17086     * @return the view of the specified id, null if cannot be found
17087     */
17088    protected View findViewTraversal(@IdRes int id) {
17089        if (id == mID) {
17090            return this;
17091        }
17092        return null;
17093    }
17094
17095    /**
17096     * {@hide}
17097     * @param tag the tag of the view to be found
17098     * @return the view of specified tag, null if cannot be found
17099     */
17100    protected View findViewWithTagTraversal(Object tag) {
17101        if (tag != null && tag.equals(mTag)) {
17102            return this;
17103        }
17104        return null;
17105    }
17106
17107    /**
17108     * {@hide}
17109     * @param predicate The predicate to evaluate.
17110     * @param childToSkip If not null, ignores this child during the recursive traversal.
17111     * @return The first view that matches the predicate or null.
17112     */
17113    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
17114        if (predicate.apply(this)) {
17115            return this;
17116        }
17117        return null;
17118    }
17119
17120    /**
17121     * Look for a child view with the given id.  If this view has the given
17122     * id, return this view.
17123     *
17124     * @param id The id to search for.
17125     * @return The view that has the given id in the hierarchy or null
17126     */
17127    @Nullable
17128    public final View findViewById(@IdRes int id) {
17129        if (id < 0) {
17130            return null;
17131        }
17132        return findViewTraversal(id);
17133    }
17134
17135    /**
17136     * Finds a view by its unuque and stable accessibility id.
17137     *
17138     * @param accessibilityId The searched accessibility id.
17139     * @return The found view.
17140     */
17141    final View findViewByAccessibilityId(int accessibilityId) {
17142        if (accessibilityId < 0) {
17143            return null;
17144        }
17145        return findViewByAccessibilityIdTraversal(accessibilityId);
17146    }
17147
17148    /**
17149     * Performs the traversal to find a view by its unuque and stable accessibility id.
17150     *
17151     * <strong>Note:</strong>This method does not stop at the root namespace
17152     * boundary since the user can touch the screen at an arbitrary location
17153     * potentially crossing the root namespace bounday which will send an
17154     * accessibility event to accessibility services and they should be able
17155     * to obtain the event source. Also accessibility ids are guaranteed to be
17156     * unique in the window.
17157     *
17158     * @param accessibilityId The accessibility id.
17159     * @return The found view.
17160     *
17161     * @hide
17162     */
17163    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17164        if (getAccessibilityViewId() == accessibilityId) {
17165            return this;
17166        }
17167        return null;
17168    }
17169
17170    /**
17171     * Look for a child view with the given tag.  If this view has the given
17172     * tag, return this view.
17173     *
17174     * @param tag The tag to search for, using "tag.equals(getTag())".
17175     * @return The View that has the given tag in the hierarchy or null
17176     */
17177    public final View findViewWithTag(Object tag) {
17178        if (tag == null) {
17179            return null;
17180        }
17181        return findViewWithTagTraversal(tag);
17182    }
17183
17184    /**
17185     * {@hide}
17186     * Look for a child view that matches the specified predicate.
17187     * If this view matches the predicate, return this view.
17188     *
17189     * @param predicate The predicate to evaluate.
17190     * @return The first view that matches the predicate or null.
17191     */
17192    public final View findViewByPredicate(Predicate<View> predicate) {
17193        return findViewByPredicateTraversal(predicate, null);
17194    }
17195
17196    /**
17197     * {@hide}
17198     * Look for a child view that matches the specified predicate,
17199     * starting with the specified view and its descendents and then
17200     * recusively searching the ancestors and siblings of that view
17201     * until this view is reached.
17202     *
17203     * This method is useful in cases where the predicate does not match
17204     * a single unique view (perhaps multiple views use the same id)
17205     * and we are trying to find the view that is "closest" in scope to the
17206     * starting view.
17207     *
17208     * @param start The view to start from.
17209     * @param predicate The predicate to evaluate.
17210     * @return The first view that matches the predicate or null.
17211     */
17212    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17213        View childToSkip = null;
17214        for (;;) {
17215            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17216            if (view != null || start == this) {
17217                return view;
17218            }
17219
17220            ViewParent parent = start.getParent();
17221            if (parent == null || !(parent instanceof View)) {
17222                return null;
17223            }
17224
17225            childToSkip = start;
17226            start = (View) parent;
17227        }
17228    }
17229
17230    /**
17231     * Sets the identifier for this view. The identifier does not have to be
17232     * unique in this view's hierarchy. The identifier should be a positive
17233     * number.
17234     *
17235     * @see #NO_ID
17236     * @see #getId()
17237     * @see #findViewById(int)
17238     *
17239     * @param id a number used to identify the view
17240     *
17241     * @attr ref android.R.styleable#View_id
17242     */
17243    public void setId(@IdRes int id) {
17244        mID = id;
17245        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17246            mID = generateViewId();
17247        }
17248    }
17249
17250    /**
17251     * {@hide}
17252     *
17253     * @param isRoot true if the view belongs to the root namespace, false
17254     *        otherwise
17255     */
17256    public void setIsRootNamespace(boolean isRoot) {
17257        if (isRoot) {
17258            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17259        } else {
17260            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17261        }
17262    }
17263
17264    /**
17265     * {@hide}
17266     *
17267     * @return true if the view belongs to the root namespace, false otherwise
17268     */
17269    public boolean isRootNamespace() {
17270        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17271    }
17272
17273    /**
17274     * Returns this view's identifier.
17275     *
17276     * @return a positive integer used to identify the view or {@link #NO_ID}
17277     *         if the view has no ID
17278     *
17279     * @see #setId(int)
17280     * @see #findViewById(int)
17281     * @attr ref android.R.styleable#View_id
17282     */
17283    @IdRes
17284    @ViewDebug.CapturedViewProperty
17285    public int getId() {
17286        return mID;
17287    }
17288
17289    /**
17290     * Returns this view's tag.
17291     *
17292     * @return the Object stored in this view as a tag, or {@code null} if not
17293     *         set
17294     *
17295     * @see #setTag(Object)
17296     * @see #getTag(int)
17297     */
17298    @ViewDebug.ExportedProperty
17299    public Object getTag() {
17300        return mTag;
17301    }
17302
17303    /**
17304     * Sets the tag associated with this view. A tag can be used to mark
17305     * a view in its hierarchy and does not have to be unique within the
17306     * hierarchy. Tags can also be used to store data within a view without
17307     * resorting to another data structure.
17308     *
17309     * @param tag an Object to tag the view with
17310     *
17311     * @see #getTag()
17312     * @see #setTag(int, Object)
17313     */
17314    public void setTag(final Object tag) {
17315        mTag = tag;
17316    }
17317
17318    /**
17319     * Returns the tag associated with this view and the specified key.
17320     *
17321     * @param key The key identifying the tag
17322     *
17323     * @return the Object stored in this view as a tag, or {@code null} if not
17324     *         set
17325     *
17326     * @see #setTag(int, Object)
17327     * @see #getTag()
17328     */
17329    public Object getTag(int key) {
17330        if (mKeyedTags != null) return mKeyedTags.get(key);
17331        return null;
17332    }
17333
17334    /**
17335     * Sets a tag associated with this view and a key. A tag can be used
17336     * to mark a view in its hierarchy and does not have to be unique within
17337     * the hierarchy. Tags can also be used to store data within a view
17338     * without resorting to another data structure.
17339     *
17340     * The specified key should be an id declared in the resources of the
17341     * application to ensure it is unique (see the <a
17342     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17343     * Keys identified as belonging to
17344     * the Android framework or not associated with any package will cause
17345     * an {@link IllegalArgumentException} to be thrown.
17346     *
17347     * @param key The key identifying the tag
17348     * @param tag An Object to tag the view with
17349     *
17350     * @throws IllegalArgumentException If they specified key is not valid
17351     *
17352     * @see #setTag(Object)
17353     * @see #getTag(int)
17354     */
17355    public void setTag(int key, final Object tag) {
17356        // If the package id is 0x00 or 0x01, it's either an undefined package
17357        // or a framework id
17358        if ((key >>> 24) < 2) {
17359            throw new IllegalArgumentException("The key must be an application-specific "
17360                    + "resource id.");
17361        }
17362
17363        setKeyedTag(key, tag);
17364    }
17365
17366    /**
17367     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17368     * framework id.
17369     *
17370     * @hide
17371     */
17372    public void setTagInternal(int key, Object tag) {
17373        if ((key >>> 24) != 0x1) {
17374            throw new IllegalArgumentException("The key must be a framework-specific "
17375                    + "resource id.");
17376        }
17377
17378        setKeyedTag(key, tag);
17379    }
17380
17381    private void setKeyedTag(int key, Object tag) {
17382        if (mKeyedTags == null) {
17383            mKeyedTags = new SparseArray<Object>(2);
17384        }
17385
17386        mKeyedTags.put(key, tag);
17387    }
17388
17389    /**
17390     * Prints information about this view in the log output, with the tag
17391     * {@link #VIEW_LOG_TAG}.
17392     *
17393     * @hide
17394     */
17395    public void debug() {
17396        debug(0);
17397    }
17398
17399    /**
17400     * Prints information about this view in the log output, with the tag
17401     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
17402     * indentation defined by the <code>depth</code>.
17403     *
17404     * @param depth the indentation level
17405     *
17406     * @hide
17407     */
17408    protected void debug(int depth) {
17409        String output = debugIndent(depth - 1);
17410
17411        output += "+ " + this;
17412        int id = getId();
17413        if (id != -1) {
17414            output += " (id=" + id + ")";
17415        }
17416        Object tag = getTag();
17417        if (tag != null) {
17418            output += " (tag=" + tag + ")";
17419        }
17420        Log.d(VIEW_LOG_TAG, output);
17421
17422        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
17423            output = debugIndent(depth) + " FOCUSED";
17424            Log.d(VIEW_LOG_TAG, output);
17425        }
17426
17427        output = debugIndent(depth);
17428        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
17429                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
17430                + "} ";
17431        Log.d(VIEW_LOG_TAG, output);
17432
17433        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
17434                || mPaddingBottom != 0) {
17435            output = debugIndent(depth);
17436            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
17437                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
17438            Log.d(VIEW_LOG_TAG, output);
17439        }
17440
17441        output = debugIndent(depth);
17442        output += "mMeasureWidth=" + mMeasuredWidth +
17443                " mMeasureHeight=" + mMeasuredHeight;
17444        Log.d(VIEW_LOG_TAG, output);
17445
17446        output = debugIndent(depth);
17447        if (mLayoutParams == null) {
17448            output += "BAD! no layout params";
17449        } else {
17450            output = mLayoutParams.debug(output);
17451        }
17452        Log.d(VIEW_LOG_TAG, output);
17453
17454        output = debugIndent(depth);
17455        output += "flags={";
17456        output += View.printFlags(mViewFlags);
17457        output += "}";
17458        Log.d(VIEW_LOG_TAG, output);
17459
17460        output = debugIndent(depth);
17461        output += "privateFlags={";
17462        output += View.printPrivateFlags(mPrivateFlags);
17463        output += "}";
17464        Log.d(VIEW_LOG_TAG, output);
17465    }
17466
17467    /**
17468     * Creates a string of whitespaces used for indentation.
17469     *
17470     * @param depth the indentation level
17471     * @return a String containing (depth * 2 + 3) * 2 white spaces
17472     *
17473     * @hide
17474     */
17475    protected static String debugIndent(int depth) {
17476        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
17477        for (int i = 0; i < (depth * 2) + 3; i++) {
17478            spaces.append(' ').append(' ');
17479        }
17480        return spaces.toString();
17481    }
17482
17483    /**
17484     * <p>Return the offset of the widget's text baseline from the widget's top
17485     * boundary. If this widget does not support baseline alignment, this
17486     * method returns -1. </p>
17487     *
17488     * @return the offset of the baseline within the widget's bounds or -1
17489     *         if baseline alignment is not supported
17490     */
17491    @ViewDebug.ExportedProperty(category = "layout")
17492    public int getBaseline() {
17493        return -1;
17494    }
17495
17496    /**
17497     * Returns whether the view hierarchy is currently undergoing a layout pass. This
17498     * information is useful to avoid situations such as calling {@link #requestLayout()} during
17499     * a layout pass.
17500     *
17501     * @return whether the view hierarchy is currently undergoing a layout pass
17502     */
17503    public boolean isInLayout() {
17504        ViewRootImpl viewRoot = getViewRootImpl();
17505        return (viewRoot != null && viewRoot.isInLayout());
17506    }
17507
17508    /**
17509     * Call this when something has changed which has invalidated the
17510     * layout of this view. This will schedule a layout pass of the view
17511     * tree. This should not be called while the view hierarchy is currently in a layout
17512     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
17513     * end of the current layout pass (and then layout will run again) or after the current
17514     * frame is drawn and the next layout occurs.
17515     *
17516     * <p>Subclasses which override this method should call the superclass method to
17517     * handle possible request-during-layout errors correctly.</p>
17518     */
17519    public void requestLayout() {
17520        if (mMeasureCache != null) mMeasureCache.clear();
17521
17522        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
17523            // Only trigger request-during-layout logic if this is the view requesting it,
17524            // not the views in its parent hierarchy
17525            ViewRootImpl viewRoot = getViewRootImpl();
17526            if (viewRoot != null && viewRoot.isInLayout()) {
17527                if (!viewRoot.requestLayoutDuringLayout(this)) {
17528                    return;
17529                }
17530            }
17531            mAttachInfo.mViewRequestingLayout = this;
17532        }
17533
17534        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17535        mPrivateFlags |= PFLAG_INVALIDATED;
17536
17537        if (mParent != null && !mParent.isLayoutRequested()) {
17538            mParent.requestLayout();
17539        }
17540        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
17541            mAttachInfo.mViewRequestingLayout = null;
17542        }
17543    }
17544
17545    /**
17546     * Forces this view to be laid out during the next layout pass.
17547     * This method does not call requestLayout() or forceLayout()
17548     * on the parent.
17549     */
17550    public void forceLayout() {
17551        if (mMeasureCache != null) mMeasureCache.clear();
17552
17553        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17554        mPrivateFlags |= PFLAG_INVALIDATED;
17555    }
17556
17557    /**
17558     * <p>
17559     * This is called to find out how big a view should be. The parent
17560     * supplies constraint information in the width and height parameters.
17561     * </p>
17562     *
17563     * <p>
17564     * The actual measurement work of a view is performed in
17565     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
17566     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
17567     * </p>
17568     *
17569     *
17570     * @param widthMeasureSpec Horizontal space requirements as imposed by the
17571     *        parent
17572     * @param heightMeasureSpec Vertical space requirements as imposed by the
17573     *        parent
17574     *
17575     * @see #onMeasure(int, int)
17576     */
17577    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
17578        boolean optical = isLayoutModeOptical(this);
17579        if (optical != isLayoutModeOptical(mParent)) {
17580            Insets insets = getOpticalInsets();
17581            int oWidth  = insets.left + insets.right;
17582            int oHeight = insets.top  + insets.bottom;
17583            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
17584            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
17585        }
17586
17587        // Suppress sign extension for the low bytes
17588        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
17589        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
17590
17591        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17592        final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
17593                MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
17594        final boolean matchingSize = isExactly &&
17595                getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
17596                getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
17597        if (forceLayout || !matchingSize &&
17598                (widthMeasureSpec != mOldWidthMeasureSpec ||
17599                        heightMeasureSpec != mOldHeightMeasureSpec)) {
17600
17601            // first clears the measured dimension flag
17602            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
17603
17604            resolveRtlPropertiesIfNeeded();
17605
17606            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
17607            if (cacheIndex < 0 || sIgnoreMeasureCache) {
17608                // measure ourselves, this should set the measured dimension flag back
17609                onMeasure(widthMeasureSpec, heightMeasureSpec);
17610                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17611            } else {
17612                long value = mMeasureCache.valueAt(cacheIndex);
17613                // Casting a long to int drops the high 32 bits, no mask needed
17614                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
17615                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17616            }
17617
17618            // flag not set, setMeasuredDimension() was not invoked, we raise
17619            // an exception to warn the developer
17620            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
17621                throw new IllegalStateException("onMeasure() did not set the"
17622                        + " measured dimension by calling"
17623                        + " setMeasuredDimension()");
17624            }
17625
17626            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
17627        }
17628
17629        mOldWidthMeasureSpec = widthMeasureSpec;
17630        mOldHeightMeasureSpec = heightMeasureSpec;
17631
17632        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
17633                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
17634    }
17635
17636    /**
17637     * <p>
17638     * Measure the view and its content to determine the measured width and the
17639     * measured height. This method is invoked by {@link #measure(int, int)} and
17640     * should be overridden by subclasses to provide accurate and efficient
17641     * measurement of their contents.
17642     * </p>
17643     *
17644     * <p>
17645     * <strong>CONTRACT:</strong> When overriding this method, you
17646     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
17647     * measured width and height of this view. Failure to do so will trigger an
17648     * <code>IllegalStateException</code>, thrown by
17649     * {@link #measure(int, int)}. Calling the superclass'
17650     * {@link #onMeasure(int, int)} is a valid use.
17651     * </p>
17652     *
17653     * <p>
17654     * The base class implementation of measure defaults to the background size,
17655     * unless a larger size is allowed by the MeasureSpec. Subclasses should
17656     * override {@link #onMeasure(int, int)} to provide better measurements of
17657     * their content.
17658     * </p>
17659     *
17660     * <p>
17661     * If this method is overridden, it is the subclass's responsibility to make
17662     * sure the measured height and width are at least the view's minimum height
17663     * and width ({@link #getSuggestedMinimumHeight()} and
17664     * {@link #getSuggestedMinimumWidth()}).
17665     * </p>
17666     *
17667     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
17668     *                         The requirements are encoded with
17669     *                         {@link android.view.View.MeasureSpec}.
17670     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
17671     *                         The requirements are encoded with
17672     *                         {@link android.view.View.MeasureSpec}.
17673     *
17674     * @see #getMeasuredWidth()
17675     * @see #getMeasuredHeight()
17676     * @see #setMeasuredDimension(int, int)
17677     * @see #getSuggestedMinimumHeight()
17678     * @see #getSuggestedMinimumWidth()
17679     * @see android.view.View.MeasureSpec#getMode(int)
17680     * @see android.view.View.MeasureSpec#getSize(int)
17681     */
17682    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17683        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
17684                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
17685    }
17686
17687    /**
17688     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
17689     * measured width and measured height. Failing to do so will trigger an
17690     * exception at measurement time.</p>
17691     *
17692     * @param measuredWidth The measured width of this view.  May be a complex
17693     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17694     * {@link #MEASURED_STATE_TOO_SMALL}.
17695     * @param measuredHeight The measured height of this view.  May be a complex
17696     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17697     * {@link #MEASURED_STATE_TOO_SMALL}.
17698     */
17699    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
17700        boolean optical = isLayoutModeOptical(this);
17701        if (optical != isLayoutModeOptical(mParent)) {
17702            Insets insets = getOpticalInsets();
17703            int opticalWidth  = insets.left + insets.right;
17704            int opticalHeight = insets.top  + insets.bottom;
17705
17706            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
17707            measuredHeight += optical ? opticalHeight : -opticalHeight;
17708        }
17709        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
17710    }
17711
17712    /**
17713     * Sets the measured dimension without extra processing for things like optical bounds.
17714     * Useful for reapplying consistent values that have already been cooked with adjustments
17715     * for optical bounds, etc. such as those from the measurement cache.
17716     *
17717     * @param measuredWidth The measured width of this view.  May be a complex
17718     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17719     * {@link #MEASURED_STATE_TOO_SMALL}.
17720     * @param measuredHeight The measured height of this view.  May be a complex
17721     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17722     * {@link #MEASURED_STATE_TOO_SMALL}.
17723     */
17724    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
17725        mMeasuredWidth = measuredWidth;
17726        mMeasuredHeight = measuredHeight;
17727
17728        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
17729    }
17730
17731    /**
17732     * Merge two states as returned by {@link #getMeasuredState()}.
17733     * @param curState The current state as returned from a view or the result
17734     * of combining multiple views.
17735     * @param newState The new view state to combine.
17736     * @return Returns a new integer reflecting the combination of the two
17737     * states.
17738     */
17739    public static int combineMeasuredStates(int curState, int newState) {
17740        return curState | newState;
17741    }
17742
17743    /**
17744     * Version of {@link #resolveSizeAndState(int, int, int)}
17745     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
17746     */
17747    public static int resolveSize(int size, int measureSpec) {
17748        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
17749    }
17750
17751    /**
17752     * Utility to reconcile a desired size and state, with constraints imposed
17753     * by a MeasureSpec. Will take the desired size, unless a different size
17754     * is imposed by the constraints. The returned value is a compound integer,
17755     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
17756     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
17757     * resulting size is smaller than the size the view wants to be.
17758     *
17759     * @param size How big the view wants to be.
17760     * @param measureSpec Constraints imposed by the parent.
17761     * @param childMeasuredState Size information bit mask for the view's
17762     *                           children.
17763     * @return Size information bit mask as defined by
17764     *         {@link #MEASURED_SIZE_MASK} and
17765     *         {@link #MEASURED_STATE_TOO_SMALL}.
17766     */
17767    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
17768        final int specMode = MeasureSpec.getMode(measureSpec);
17769        final int specSize = MeasureSpec.getSize(measureSpec);
17770        final int result;
17771        switch (specMode) {
17772            case MeasureSpec.AT_MOST:
17773                if (specSize < size) {
17774                    result = specSize | MEASURED_STATE_TOO_SMALL;
17775                } else {
17776                    result = size;
17777                }
17778                break;
17779            case MeasureSpec.EXACTLY:
17780                result = specSize;
17781                break;
17782            case MeasureSpec.UNSPECIFIED:
17783            default:
17784                result = size;
17785        }
17786        return result | (childMeasuredState & MEASURED_STATE_MASK);
17787    }
17788
17789    /**
17790     * Utility to return a default size. Uses the supplied size if the
17791     * MeasureSpec imposed no constraints. Will get larger if allowed
17792     * by the MeasureSpec.
17793     *
17794     * @param size Default size for this view
17795     * @param measureSpec Constraints imposed by the parent
17796     * @return The size this view should be.
17797     */
17798    public static int getDefaultSize(int size, int measureSpec) {
17799        int result = size;
17800        int specMode = MeasureSpec.getMode(measureSpec);
17801        int specSize = MeasureSpec.getSize(measureSpec);
17802
17803        switch (specMode) {
17804        case MeasureSpec.UNSPECIFIED:
17805            result = size;
17806            break;
17807        case MeasureSpec.AT_MOST:
17808        case MeasureSpec.EXACTLY:
17809            result = specSize;
17810            break;
17811        }
17812        return result;
17813    }
17814
17815    /**
17816     * Returns the suggested minimum height that the view should use. This
17817     * returns the maximum of the view's minimum height
17818     * and the background's minimum height
17819     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17820     * <p>
17821     * When being used in {@link #onMeasure(int, int)}, the caller should still
17822     * ensure the returned height is within the requirements of the parent.
17823     *
17824     * @return The suggested minimum height of the view.
17825     */
17826    protected int getSuggestedMinimumHeight() {
17827        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17828
17829    }
17830
17831    /**
17832     * Returns the suggested minimum width that the view should use. This
17833     * returns the maximum of the view's minimum width)
17834     * and the background's minimum width
17835     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17836     * <p>
17837     * When being used in {@link #onMeasure(int, int)}, the caller should still
17838     * ensure the returned width is within the requirements of the parent.
17839     *
17840     * @return The suggested minimum width of the view.
17841     */
17842    protected int getSuggestedMinimumWidth() {
17843        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17844    }
17845
17846    /**
17847     * Returns the minimum height of the view.
17848     *
17849     * @return the minimum height the view will try to be.
17850     *
17851     * @see #setMinimumHeight(int)
17852     *
17853     * @attr ref android.R.styleable#View_minHeight
17854     */
17855    public int getMinimumHeight() {
17856        return mMinHeight;
17857    }
17858
17859    /**
17860     * Sets the minimum height of the view. It is not guaranteed the view will
17861     * be able to achieve this minimum height (for example, if its parent layout
17862     * constrains it with less available height).
17863     *
17864     * @param minHeight The minimum height the view will try to be.
17865     *
17866     * @see #getMinimumHeight()
17867     *
17868     * @attr ref android.R.styleable#View_minHeight
17869     */
17870    public void setMinimumHeight(int minHeight) {
17871        mMinHeight = minHeight;
17872        requestLayout();
17873    }
17874
17875    /**
17876     * Returns the minimum width of the view.
17877     *
17878     * @return the minimum width the view will try to be.
17879     *
17880     * @see #setMinimumWidth(int)
17881     *
17882     * @attr ref android.R.styleable#View_minWidth
17883     */
17884    public int getMinimumWidth() {
17885        return mMinWidth;
17886    }
17887
17888    /**
17889     * Sets the minimum width of the view. It is not guaranteed the view will
17890     * be able to achieve this minimum width (for example, if its parent layout
17891     * constrains it with less available width).
17892     *
17893     * @param minWidth The minimum width the view will try to be.
17894     *
17895     * @see #getMinimumWidth()
17896     *
17897     * @attr ref android.R.styleable#View_minWidth
17898     */
17899    public void setMinimumWidth(int minWidth) {
17900        mMinWidth = minWidth;
17901        requestLayout();
17902
17903    }
17904
17905    /**
17906     * Get the animation currently associated with this view.
17907     *
17908     * @return The animation that is currently playing or
17909     *         scheduled to play for this view.
17910     */
17911    public Animation getAnimation() {
17912        return mCurrentAnimation;
17913    }
17914
17915    /**
17916     * Start the specified animation now.
17917     *
17918     * @param animation the animation to start now
17919     */
17920    public void startAnimation(Animation animation) {
17921        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17922        setAnimation(animation);
17923        invalidateParentCaches();
17924        invalidate(true);
17925    }
17926
17927    /**
17928     * Cancels any animations for this view.
17929     */
17930    public void clearAnimation() {
17931        if (mCurrentAnimation != null) {
17932            mCurrentAnimation.detach();
17933        }
17934        mCurrentAnimation = null;
17935        invalidateParentIfNeeded();
17936    }
17937
17938    /**
17939     * Sets the next animation to play for this view.
17940     * If you want the animation to play immediately, use
17941     * {@link #startAnimation(android.view.animation.Animation)} instead.
17942     * This method provides allows fine-grained
17943     * control over the start time and invalidation, but you
17944     * must make sure that 1) the animation has a start time set, and
17945     * 2) the view's parent (which controls animations on its children)
17946     * will be invalidated when the animation is supposed to
17947     * start.
17948     *
17949     * @param animation The next animation, or null.
17950     */
17951    public void setAnimation(Animation animation) {
17952        mCurrentAnimation = animation;
17953
17954        if (animation != null) {
17955            // If the screen is off assume the animation start time is now instead of
17956            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17957            // would cause the animation to start when the screen turns back on
17958            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17959                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17960                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17961            }
17962            animation.reset();
17963        }
17964    }
17965
17966    /**
17967     * Invoked by a parent ViewGroup to notify the start of the animation
17968     * currently associated with this view. If you override this method,
17969     * always call super.onAnimationStart();
17970     *
17971     * @see #setAnimation(android.view.animation.Animation)
17972     * @see #getAnimation()
17973     */
17974    protected void onAnimationStart() {
17975        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17976    }
17977
17978    /**
17979     * Invoked by a parent ViewGroup to notify the end of the animation
17980     * currently associated with this view. If you override this method,
17981     * always call super.onAnimationEnd();
17982     *
17983     * @see #setAnimation(android.view.animation.Animation)
17984     * @see #getAnimation()
17985     */
17986    protected void onAnimationEnd() {
17987        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17988    }
17989
17990    /**
17991     * Invoked if there is a Transform that involves alpha. Subclass that can
17992     * draw themselves with the specified alpha should return true, and then
17993     * respect that alpha when their onDraw() is called. If this returns false
17994     * then the view may be redirected to draw into an offscreen buffer to
17995     * fulfill the request, which will look fine, but may be slower than if the
17996     * subclass handles it internally. The default implementation returns false.
17997     *
17998     * @param alpha The alpha (0..255) to apply to the view's drawing
17999     * @return true if the view can draw with the specified alpha.
18000     */
18001    protected boolean onSetAlpha(int alpha) {
18002        return false;
18003    }
18004
18005    /**
18006     * This is used by the RootView to perform an optimization when
18007     * the view hierarchy contains one or several SurfaceView.
18008     * SurfaceView is always considered transparent, but its children are not,
18009     * therefore all View objects remove themselves from the global transparent
18010     * region (passed as a parameter to this function).
18011     *
18012     * @param region The transparent region for this ViewAncestor (window).
18013     *
18014     * @return Returns true if the effective visibility of the view at this
18015     * point is opaque, regardless of the transparent region; returns false
18016     * if it is possible for underlying windows to be seen behind the view.
18017     *
18018     * {@hide}
18019     */
18020    public boolean gatherTransparentRegion(Region region) {
18021        final AttachInfo attachInfo = mAttachInfo;
18022        if (region != null && attachInfo != null) {
18023            final int pflags = mPrivateFlags;
18024            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
18025                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
18026                // remove it from the transparent region.
18027                final int[] location = attachInfo.mTransparentLocation;
18028                getLocationInWindow(location);
18029                region.op(location[0], location[1], location[0] + mRight - mLeft,
18030                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
18031            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
18032                    mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
18033                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
18034                // exists, so we remove the background drawable's non-transparent
18035                // parts from this transparent region.
18036                applyDrawableToTransparentRegion(mBackground, region);
18037            }
18038        }
18039        return true;
18040    }
18041
18042    /**
18043     * Play a sound effect for this view.
18044     *
18045     * <p>The framework will play sound effects for some built in actions, such as
18046     * clicking, but you may wish to play these effects in your widget,
18047     * for instance, for internal navigation.
18048     *
18049     * <p>The sound effect will only be played if sound effects are enabled by the user, and
18050     * {@link #isSoundEffectsEnabled()} is true.
18051     *
18052     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
18053     */
18054    public void playSoundEffect(int soundConstant) {
18055        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
18056            return;
18057        }
18058        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
18059    }
18060
18061    /**
18062     * BZZZTT!!1!
18063     *
18064     * <p>Provide haptic feedback to the user for this view.
18065     *
18066     * <p>The framework will provide haptic feedback for some built in actions,
18067     * such as long presses, but you may wish to provide feedback for your
18068     * own widget.
18069     *
18070     * <p>The feedback will only be performed if
18071     * {@link #isHapticFeedbackEnabled()} is true.
18072     *
18073     * @param feedbackConstant One of the constants defined in
18074     * {@link HapticFeedbackConstants}
18075     */
18076    public boolean performHapticFeedback(int feedbackConstant) {
18077        return performHapticFeedback(feedbackConstant, 0);
18078    }
18079
18080    /**
18081     * BZZZTT!!1!
18082     *
18083     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
18084     *
18085     * @param feedbackConstant One of the constants defined in
18086     * {@link HapticFeedbackConstants}
18087     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
18088     */
18089    public boolean performHapticFeedback(int feedbackConstant, int flags) {
18090        if (mAttachInfo == null) {
18091            return false;
18092        }
18093        //noinspection SimplifiableIfStatement
18094        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
18095                && !isHapticFeedbackEnabled()) {
18096            return false;
18097        }
18098        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
18099                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
18100    }
18101
18102    /**
18103     * Request that the visibility of the status bar or other screen/window
18104     * decorations be changed.
18105     *
18106     * <p>This method is used to put the over device UI into temporary modes
18107     * where the user's attention is focused more on the application content,
18108     * by dimming or hiding surrounding system affordances.  This is typically
18109     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
18110     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
18111     * to be placed behind the action bar (and with these flags other system
18112     * affordances) so that smooth transitions between hiding and showing them
18113     * can be done.
18114     *
18115     * <p>Two representative examples of the use of system UI visibility is
18116     * implementing a content browsing application (like a magazine reader)
18117     * and a video playing application.
18118     *
18119     * <p>The first code shows a typical implementation of a View in a content
18120     * browsing application.  In this implementation, the application goes
18121     * into a content-oriented mode by hiding the status bar and action bar,
18122     * and putting the navigation elements into lights out mode.  The user can
18123     * then interact with content while in this mode.  Such an application should
18124     * provide an easy way for the user to toggle out of the mode (such as to
18125     * check information in the status bar or access notifications).  In the
18126     * implementation here, this is done simply by tapping on the content.
18127     *
18128     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
18129     *      content}
18130     *
18131     * <p>This second code sample shows a typical implementation of a View
18132     * in a video playing application.  In this situation, while the video is
18133     * playing the application would like to go into a complete full-screen mode,
18134     * to use as much of the display as possible for the video.  When in this state
18135     * the user can not interact with the application; the system intercepts
18136     * touching on the screen to pop the UI out of full screen mode.  See
18137     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
18138     *
18139     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
18140     *      content}
18141     *
18142     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18143     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18144     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18145     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18146     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18147     */
18148    public void setSystemUiVisibility(int visibility) {
18149        if (visibility != mSystemUiVisibility) {
18150            mSystemUiVisibility = visibility;
18151            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18152                mParent.recomputeViewAttributes(this);
18153            }
18154        }
18155    }
18156
18157    /**
18158     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
18159     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18160     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18161     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18162     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18163     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18164     */
18165    public int getSystemUiVisibility() {
18166        return mSystemUiVisibility;
18167    }
18168
18169    /**
18170     * Returns the current system UI visibility that is currently set for
18171     * the entire window.  This is the combination of the
18172     * {@link #setSystemUiVisibility(int)} values supplied by all of the
18173     * views in the window.
18174     */
18175    public int getWindowSystemUiVisibility() {
18176        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18177    }
18178
18179    /**
18180     * Override to find out when the window's requested system UI visibility
18181     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18182     * This is different from the callbacks received through
18183     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18184     * in that this is only telling you about the local request of the window,
18185     * not the actual values applied by the system.
18186     */
18187    public void onWindowSystemUiVisibilityChanged(int visible) {
18188    }
18189
18190    /**
18191     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18192     * the view hierarchy.
18193     */
18194    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18195        onWindowSystemUiVisibilityChanged(visible);
18196    }
18197
18198    /**
18199     * Set a listener to receive callbacks when the visibility of the system bar changes.
18200     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18201     */
18202    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18203        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18204        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18205            mParent.recomputeViewAttributes(this);
18206        }
18207    }
18208
18209    /**
18210     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18211     * the view hierarchy.
18212     */
18213    public void dispatchSystemUiVisibilityChanged(int visibility) {
18214        ListenerInfo li = mListenerInfo;
18215        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18216            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18217                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18218        }
18219    }
18220
18221    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18222        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18223        if (val != mSystemUiVisibility) {
18224            setSystemUiVisibility(val);
18225            return true;
18226        }
18227        return false;
18228    }
18229
18230    /** @hide */
18231    public void setDisabledSystemUiVisibility(int flags) {
18232        if (mAttachInfo != null) {
18233            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18234                mAttachInfo.mDisabledSystemUiVisibility = flags;
18235                if (mParent != null) {
18236                    mParent.recomputeViewAttributes(this);
18237                }
18238            }
18239        }
18240    }
18241
18242    /**
18243     * Creates an image that the system displays during the drag and drop
18244     * operation. This is called a &quot;drag shadow&quot;. The default implementation
18245     * for a DragShadowBuilder based on a View returns an image that has exactly the same
18246     * appearance as the given View. The default also positions the center of the drag shadow
18247     * directly under the touch point. If no View is provided (the constructor with no parameters
18248     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18249     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
18250     * default is an invisible drag shadow.
18251     * <p>
18252     * You are not required to use the View you provide to the constructor as the basis of the
18253     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18254     * anything you want as the drag shadow.
18255     * </p>
18256     * <p>
18257     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
18258     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18259     *  size and position of the drag shadow. It uses this data to construct a
18260     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18261     *  so that your application can draw the shadow image in the Canvas.
18262     * </p>
18263     *
18264     * <div class="special reference">
18265     * <h3>Developer Guides</h3>
18266     * <p>For a guide to implementing drag and drop features, read the
18267     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18268     * </div>
18269     */
18270    public static class DragShadowBuilder {
18271        private final WeakReference<View> mView;
18272
18273        /**
18274         * Constructs a shadow image builder based on a View. By default, the resulting drag
18275         * shadow will have the same appearance and dimensions as the View, with the touch point
18276         * over the center of the View.
18277         * @param view A View. Any View in scope can be used.
18278         */
18279        public DragShadowBuilder(View view) {
18280            mView = new WeakReference<View>(view);
18281        }
18282
18283        /**
18284         * Construct a shadow builder object with no associated View.  This
18285         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18286         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18287         * to supply the drag shadow's dimensions and appearance without
18288         * reference to any View object. If they are not overridden, then the result is an
18289         * invisible drag shadow.
18290         */
18291        public DragShadowBuilder() {
18292            mView = new WeakReference<View>(null);
18293        }
18294
18295        /**
18296         * Returns the View object that had been passed to the
18297         * {@link #View.DragShadowBuilder(View)}
18298         * constructor.  If that View parameter was {@code null} or if the
18299         * {@link #View.DragShadowBuilder()}
18300         * constructor was used to instantiate the builder object, this method will return
18301         * null.
18302         *
18303         * @return The View object associate with this builder object.
18304         */
18305        @SuppressWarnings({"JavadocReference"})
18306        final public View getView() {
18307            return mView.get();
18308        }
18309
18310        /**
18311         * Provides the metrics for the shadow image. These include the dimensions of
18312         * the shadow image, and the point within that shadow that should
18313         * be centered under the touch location while dragging.
18314         * <p>
18315         * The default implementation sets the dimensions of the shadow to be the
18316         * same as the dimensions of the View itself and centers the shadow under
18317         * the touch point.
18318         * </p>
18319         *
18320         * @param shadowSize A {@link android.graphics.Point} containing the width and height
18321         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18322         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18323         * image.
18324         *
18325         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18326         * shadow image that should be underneath the touch point during the drag and drop
18327         * operation. Your application must set {@link android.graphics.Point#x} to the
18328         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18329         */
18330        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18331            final View view = mView.get();
18332            if (view != null) {
18333                shadowSize.set(view.getWidth(), view.getHeight());
18334                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18335            } else {
18336                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18337            }
18338        }
18339
18340        /**
18341         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18342         * based on the dimensions it received from the
18343         * {@link #onProvideShadowMetrics(Point, Point)} callback.
18344         *
18345         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18346         */
18347        public void onDrawShadow(Canvas canvas) {
18348            final View view = mView.get();
18349            if (view != null) {
18350                view.draw(canvas);
18351            } else {
18352                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18353            }
18354        }
18355    }
18356
18357    /**
18358     * Starts a drag and drop operation. When your application calls this method, it passes a
18359     * {@link android.view.View.DragShadowBuilder} object to the system. The
18360     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18361     * to get metrics for the drag shadow, and then calls the object's
18362     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18363     * <p>
18364     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
18365     *  drag events to all the View objects in your application that are currently visible. It does
18366     *  this either by calling the View object's drag listener (an implementation of
18367     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18368     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18369     *  Both are passed a {@link android.view.DragEvent} object that has a
18370     *  {@link android.view.DragEvent#getAction()} value of
18371     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
18372     * </p>
18373     * <p>
18374     * Your application can invoke startDrag() on any attached View object. The View object does not
18375     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
18376     * be related to the View the user selected for dragging.
18377     * </p>
18378     * @param data A {@link android.content.ClipData} object pointing to the data to be
18379     * transferred by the drag and drop operation.
18380     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
18381     * drag shadow.
18382     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
18383     * drop operation. This Object is put into every DragEvent object sent by the system during the
18384     * current drag.
18385     * <p>
18386     * myLocalState is a lightweight mechanism for the sending information from the dragged View
18387     * to the target Views. For example, it can contain flags that differentiate between a
18388     * a copy operation and a move operation.
18389     * </p>
18390     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
18391     * so the parameter should be set to 0.
18392     * @return {@code true} if the method completes successfully, or
18393     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
18394     * do a drag, and so no drag operation is in progress.
18395     */
18396    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
18397            Object myLocalState, int flags) {
18398        if (ViewDebug.DEBUG_DRAG) {
18399            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
18400        }
18401        boolean okay = false;
18402
18403        Point shadowSize = new Point();
18404        Point shadowTouchPoint = new Point();
18405        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
18406
18407        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
18408                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
18409            throw new IllegalStateException("Drag shadow dimensions must not be negative");
18410        }
18411
18412        if (ViewDebug.DEBUG_DRAG) {
18413            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
18414                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
18415        }
18416        Surface surface = new Surface();
18417        try {
18418            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
18419                    flags, shadowSize.x, shadowSize.y, surface);
18420            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
18421                    + " surface=" + surface);
18422            if (token != null) {
18423                Canvas canvas = surface.lockCanvas(null);
18424                try {
18425                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
18426                    shadowBuilder.onDrawShadow(canvas);
18427                } finally {
18428                    surface.unlockCanvasAndPost(canvas);
18429                }
18430
18431                final ViewRootImpl root = getViewRootImpl();
18432
18433                // Cache the local state object for delivery with DragEvents
18434                root.setLocalDragState(myLocalState);
18435
18436                // repurpose 'shadowSize' for the last touch point
18437                root.getLastTouchPoint(shadowSize);
18438
18439                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
18440                        shadowSize.x, shadowSize.y,
18441                        shadowTouchPoint.x, shadowTouchPoint.y, data);
18442                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
18443
18444                // Off and running!  Release our local surface instance; the drag
18445                // shadow surface is now managed by the system process.
18446                surface.release();
18447            }
18448        } catch (Exception e) {
18449            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
18450            surface.destroy();
18451        }
18452
18453        return okay;
18454    }
18455
18456    /**
18457     * Handles drag events sent by the system following a call to
18458     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
18459     *<p>
18460     * When the system calls this method, it passes a
18461     * {@link android.view.DragEvent} object. A call to
18462     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
18463     * in DragEvent. The method uses these to determine what is happening in the drag and drop
18464     * operation.
18465     * @param event The {@link android.view.DragEvent} sent by the system.
18466     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
18467     * in DragEvent, indicating the type of drag event represented by this object.
18468     * @return {@code true} if the method was successful, otherwise {@code false}.
18469     * <p>
18470     *  The method should return {@code true} in response to an action type of
18471     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
18472     *  operation.
18473     * </p>
18474     * <p>
18475     *  The method should also return {@code true} in response to an action type of
18476     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
18477     *  {@code false} if it didn't.
18478     * </p>
18479     */
18480    public boolean onDragEvent(DragEvent event) {
18481        return false;
18482    }
18483
18484    /**
18485     * Detects if this View is enabled and has a drag event listener.
18486     * If both are true, then it calls the drag event listener with the
18487     * {@link android.view.DragEvent} it received. If the drag event listener returns
18488     * {@code true}, then dispatchDragEvent() returns {@code true}.
18489     * <p>
18490     * For all other cases, the method calls the
18491     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
18492     * method and returns its result.
18493     * </p>
18494     * <p>
18495     * This ensures that a drag event is always consumed, even if the View does not have a drag
18496     * event listener. However, if the View has a listener and the listener returns true, then
18497     * onDragEvent() is not called.
18498     * </p>
18499     */
18500    public boolean dispatchDragEvent(DragEvent event) {
18501        ListenerInfo li = mListenerInfo;
18502        //noinspection SimplifiableIfStatement
18503        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
18504                && li.mOnDragListener.onDrag(this, event)) {
18505            return true;
18506        }
18507        return onDragEvent(event);
18508    }
18509
18510    boolean canAcceptDrag() {
18511        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
18512    }
18513
18514    /**
18515     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
18516     * it is ever exposed at all.
18517     * @hide
18518     */
18519    public void onCloseSystemDialogs(String reason) {
18520    }
18521
18522    /**
18523     * Given a Drawable whose bounds have been set to draw into this view,
18524     * update a Region being computed for
18525     * {@link #gatherTransparentRegion(android.graphics.Region)} so
18526     * that any non-transparent parts of the Drawable are removed from the
18527     * given transparent region.
18528     *
18529     * @param dr The Drawable whose transparency is to be applied to the region.
18530     * @param region A Region holding the current transparency information,
18531     * where any parts of the region that are set are considered to be
18532     * transparent.  On return, this region will be modified to have the
18533     * transparency information reduced by the corresponding parts of the
18534     * Drawable that are not transparent.
18535     * {@hide}
18536     */
18537    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
18538        if (DBG) {
18539            Log.i("View", "Getting transparent region for: " + this);
18540        }
18541        final Region r = dr.getTransparentRegion();
18542        final Rect db = dr.getBounds();
18543        final AttachInfo attachInfo = mAttachInfo;
18544        if (r != null && attachInfo != null) {
18545            final int w = getRight()-getLeft();
18546            final int h = getBottom()-getTop();
18547            if (db.left > 0) {
18548                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
18549                r.op(0, 0, db.left, h, Region.Op.UNION);
18550            }
18551            if (db.right < w) {
18552                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
18553                r.op(db.right, 0, w, h, Region.Op.UNION);
18554            }
18555            if (db.top > 0) {
18556                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
18557                r.op(0, 0, w, db.top, Region.Op.UNION);
18558            }
18559            if (db.bottom < h) {
18560                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
18561                r.op(0, db.bottom, w, h, Region.Op.UNION);
18562            }
18563            final int[] location = attachInfo.mTransparentLocation;
18564            getLocationInWindow(location);
18565            r.translate(location[0], location[1]);
18566            region.op(r, Region.Op.INTERSECT);
18567        } else {
18568            region.op(db, Region.Op.DIFFERENCE);
18569        }
18570    }
18571
18572    private void checkForLongClick(int delayOffset) {
18573        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
18574            mHasPerformedLongPress = false;
18575
18576            if (mPendingCheckForLongPress == null) {
18577                mPendingCheckForLongPress = new CheckForLongPress();
18578            }
18579            mPendingCheckForLongPress.rememberWindowAttachCount();
18580            postDelayed(mPendingCheckForLongPress,
18581                    ViewConfiguration.getLongPressTimeout() - delayOffset);
18582        }
18583    }
18584
18585    /**
18586     * Inflate a view from an XML resource.  This convenience method wraps the {@link
18587     * LayoutInflater} class, which provides a full range of options for view inflation.
18588     *
18589     * @param context The Context object for your activity or application.
18590     * @param resource The resource ID to inflate
18591     * @param root A view group that will be the parent.  Used to properly inflate the
18592     * layout_* parameters.
18593     * @see LayoutInflater
18594     */
18595    public static View inflate(Context context, int resource, ViewGroup root) {
18596        LayoutInflater factory = LayoutInflater.from(context);
18597        return factory.inflate(resource, root);
18598    }
18599
18600    /**
18601     * Scroll the view with standard behavior for scrolling beyond the normal
18602     * content boundaries. Views that call this method should override
18603     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
18604     * results of an over-scroll operation.
18605     *
18606     * Views can use this method to handle any touch or fling-based scrolling.
18607     *
18608     * @param deltaX Change in X in pixels
18609     * @param deltaY Change in Y in pixels
18610     * @param scrollX Current X scroll value in pixels before applying deltaX
18611     * @param scrollY Current Y scroll value in pixels before applying deltaY
18612     * @param scrollRangeX Maximum content scroll range along the X axis
18613     * @param scrollRangeY Maximum content scroll range along the Y axis
18614     * @param maxOverScrollX Number of pixels to overscroll by in either direction
18615     *          along the X axis.
18616     * @param maxOverScrollY Number of pixels to overscroll by in either direction
18617     *          along the Y axis.
18618     * @param isTouchEvent true if this scroll operation is the result of a touch event.
18619     * @return true if scrolling was clamped to an over-scroll boundary along either
18620     *          axis, false otherwise.
18621     */
18622    @SuppressWarnings({"UnusedParameters"})
18623    protected boolean overScrollBy(int deltaX, int deltaY,
18624            int scrollX, int scrollY,
18625            int scrollRangeX, int scrollRangeY,
18626            int maxOverScrollX, int maxOverScrollY,
18627            boolean isTouchEvent) {
18628        final int overScrollMode = mOverScrollMode;
18629        final boolean canScrollHorizontal =
18630                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
18631        final boolean canScrollVertical =
18632                computeVerticalScrollRange() > computeVerticalScrollExtent();
18633        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
18634                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
18635        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
18636                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
18637
18638        int newScrollX = scrollX + deltaX;
18639        if (!overScrollHorizontal) {
18640            maxOverScrollX = 0;
18641        }
18642
18643        int newScrollY = scrollY + deltaY;
18644        if (!overScrollVertical) {
18645            maxOverScrollY = 0;
18646        }
18647
18648        // Clamp values if at the limits and record
18649        final int left = -maxOverScrollX;
18650        final int right = maxOverScrollX + scrollRangeX;
18651        final int top = -maxOverScrollY;
18652        final int bottom = maxOverScrollY + scrollRangeY;
18653
18654        boolean clampedX = false;
18655        if (newScrollX > right) {
18656            newScrollX = right;
18657            clampedX = true;
18658        } else if (newScrollX < left) {
18659            newScrollX = left;
18660            clampedX = true;
18661        }
18662
18663        boolean clampedY = false;
18664        if (newScrollY > bottom) {
18665            newScrollY = bottom;
18666            clampedY = true;
18667        } else if (newScrollY < top) {
18668            newScrollY = top;
18669            clampedY = true;
18670        }
18671
18672        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
18673
18674        return clampedX || clampedY;
18675    }
18676
18677    /**
18678     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
18679     * respond to the results of an over-scroll operation.
18680     *
18681     * @param scrollX New X scroll value in pixels
18682     * @param scrollY New Y scroll value in pixels
18683     * @param clampedX True if scrollX was clamped to an over-scroll boundary
18684     * @param clampedY True if scrollY was clamped to an over-scroll boundary
18685     */
18686    protected void onOverScrolled(int scrollX, int scrollY,
18687            boolean clampedX, boolean clampedY) {
18688        // Intentionally empty.
18689    }
18690
18691    /**
18692     * Returns the over-scroll mode for this view. The result will be
18693     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18694     * (allow over-scrolling only if the view content is larger than the container),
18695     * or {@link #OVER_SCROLL_NEVER}.
18696     *
18697     * @return This view's over-scroll mode.
18698     */
18699    public int getOverScrollMode() {
18700        return mOverScrollMode;
18701    }
18702
18703    /**
18704     * Set the over-scroll mode for this view. Valid over-scroll modes are
18705     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18706     * (allow over-scrolling only if the view content is larger than the container),
18707     * or {@link #OVER_SCROLL_NEVER}.
18708     *
18709     * Setting the over-scroll mode of a view will have an effect only if the
18710     * view is capable of scrolling.
18711     *
18712     * @param overScrollMode The new over-scroll mode for this view.
18713     */
18714    public void setOverScrollMode(int overScrollMode) {
18715        if (overScrollMode != OVER_SCROLL_ALWAYS &&
18716                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
18717                overScrollMode != OVER_SCROLL_NEVER) {
18718            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
18719        }
18720        mOverScrollMode = overScrollMode;
18721    }
18722
18723    /**
18724     * Enable or disable nested scrolling for this view.
18725     *
18726     * <p>If this property is set to true the view will be permitted to initiate nested
18727     * scrolling operations with a compatible parent view in the current hierarchy. If this
18728     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
18729     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
18730     * the nested scroll.</p>
18731     *
18732     * @param enabled true to enable nested scrolling, false to disable
18733     *
18734     * @see #isNestedScrollingEnabled()
18735     */
18736    public void setNestedScrollingEnabled(boolean enabled) {
18737        if (enabled) {
18738            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
18739        } else {
18740            stopNestedScroll();
18741            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
18742        }
18743    }
18744
18745    /**
18746     * Returns true if nested scrolling is enabled for this view.
18747     *
18748     * <p>If nested scrolling is enabled and this View class implementation supports it,
18749     * this view will act as a nested scrolling child view when applicable, forwarding data
18750     * about the scroll operation in progress to a compatible and cooperating nested scrolling
18751     * parent.</p>
18752     *
18753     * @return true if nested scrolling is enabled
18754     *
18755     * @see #setNestedScrollingEnabled(boolean)
18756     */
18757    public boolean isNestedScrollingEnabled() {
18758        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
18759                PFLAG3_NESTED_SCROLLING_ENABLED;
18760    }
18761
18762    /**
18763     * Begin a nestable scroll operation along the given axes.
18764     *
18765     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
18766     *
18767     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
18768     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
18769     * In the case of touch scrolling the nested scroll will be terminated automatically in
18770     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
18771     * In the event of programmatic scrolling the caller must explicitly call
18772     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
18773     *
18774     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
18775     * If it returns false the caller may ignore the rest of this contract until the next scroll.
18776     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
18777     *
18778     * <p>At each incremental step of the scroll the caller should invoke
18779     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
18780     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
18781     * parent at least partially consumed the scroll and the caller should adjust the amount it
18782     * scrolls by.</p>
18783     *
18784     * <p>After applying the remainder of the scroll delta the caller should invoke
18785     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
18786     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
18787     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18788     * </p>
18789     *
18790     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18791     *             {@link #SCROLL_AXIS_VERTICAL}.
18792     * @return true if a cooperative parent was found and nested scrolling has been enabled for
18793     *         the current gesture.
18794     *
18795     * @see #stopNestedScroll()
18796     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18797     * @see #dispatchNestedScroll(int, int, int, int, int[])
18798     */
18799    public boolean startNestedScroll(int axes) {
18800        if (hasNestedScrollingParent()) {
18801            // Already in progress
18802            return true;
18803        }
18804        if (isNestedScrollingEnabled()) {
18805            ViewParent p = getParent();
18806            View child = this;
18807            while (p != null) {
18808                try {
18809                    if (p.onStartNestedScroll(child, this, axes)) {
18810                        mNestedScrollingParent = p;
18811                        p.onNestedScrollAccepted(child, this, axes);
18812                        return true;
18813                    }
18814                } catch (AbstractMethodError e) {
18815                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18816                            "method onStartNestedScroll", e);
18817                    // Allow the search upward to continue
18818                }
18819                if (p instanceof View) {
18820                    child = (View) p;
18821                }
18822                p = p.getParent();
18823            }
18824        }
18825        return false;
18826    }
18827
18828    /**
18829     * Stop a nested scroll in progress.
18830     *
18831     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18832     *
18833     * @see #startNestedScroll(int)
18834     */
18835    public void stopNestedScroll() {
18836        if (mNestedScrollingParent != null) {
18837            mNestedScrollingParent.onStopNestedScroll(this);
18838            mNestedScrollingParent = null;
18839        }
18840    }
18841
18842    /**
18843     * Returns true if this view has a nested scrolling parent.
18844     *
18845     * <p>The presence of a nested scrolling parent indicates that this view has initiated
18846     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18847     *
18848     * @return whether this view has a nested scrolling parent
18849     */
18850    public boolean hasNestedScrollingParent() {
18851        return mNestedScrollingParent != null;
18852    }
18853
18854    /**
18855     * Dispatch one step of a nested scroll in progress.
18856     *
18857     * <p>Implementations of views that support nested scrolling should call this to report
18858     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18859     * is not currently in progress or nested scrolling is not
18860     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18861     *
18862     * <p>Compatible View implementations should also call
18863     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18864     * consuming a component of the scroll event themselves.</p>
18865     *
18866     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18867     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18868     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18869     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18870     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18871     *                       in local view coordinates of this view from before this operation
18872     *                       to after it completes. View implementations may use this to adjust
18873     *                       expected input coordinate tracking.
18874     * @return true if the event was dispatched, false if it could not be dispatched.
18875     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18876     */
18877    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18878            int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18879        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18880            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
18881                int startX = 0;
18882                int startY = 0;
18883                if (offsetInWindow != null) {
18884                    getLocationInWindow(offsetInWindow);
18885                    startX = offsetInWindow[0];
18886                    startY = offsetInWindow[1];
18887                }
18888
18889                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18890                        dxUnconsumed, dyUnconsumed);
18891
18892                if (offsetInWindow != null) {
18893                    getLocationInWindow(offsetInWindow);
18894                    offsetInWindow[0] -= startX;
18895                    offsetInWindow[1] -= startY;
18896                }
18897                return true;
18898            } else if (offsetInWindow != null) {
18899                // No motion, no dispatch. Keep offsetInWindow up to date.
18900                offsetInWindow[0] = 0;
18901                offsetInWindow[1] = 0;
18902            }
18903        }
18904        return false;
18905    }
18906
18907    /**
18908     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18909     *
18910     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18911     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18912     * scrolling operation to consume some or all of the scroll operation before the child view
18913     * consumes it.</p>
18914     *
18915     * @param dx Horizontal scroll distance in pixels
18916     * @param dy Vertical scroll distance in pixels
18917     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18918     *                 and consumed[1] the consumed dy.
18919     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18920     *                       in local view coordinates of this view from before this operation
18921     *                       to after it completes. View implementations may use this to adjust
18922     *                       expected input coordinate tracking.
18923     * @return true if the parent consumed some or all of the scroll delta
18924     * @see #dispatchNestedScroll(int, int, int, int, int[])
18925     */
18926    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18927        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18928            if (dx != 0 || dy != 0) {
18929                int startX = 0;
18930                int startY = 0;
18931                if (offsetInWindow != null) {
18932                    getLocationInWindow(offsetInWindow);
18933                    startX = offsetInWindow[0];
18934                    startY = offsetInWindow[1];
18935                }
18936
18937                if (consumed == null) {
18938                    if (mTempNestedScrollConsumed == null) {
18939                        mTempNestedScrollConsumed = new int[2];
18940                    }
18941                    consumed = mTempNestedScrollConsumed;
18942                }
18943                consumed[0] = 0;
18944                consumed[1] = 0;
18945                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18946
18947                if (offsetInWindow != null) {
18948                    getLocationInWindow(offsetInWindow);
18949                    offsetInWindow[0] -= startX;
18950                    offsetInWindow[1] -= startY;
18951                }
18952                return consumed[0] != 0 || consumed[1] != 0;
18953            } else if (offsetInWindow != null) {
18954                offsetInWindow[0] = 0;
18955                offsetInWindow[1] = 0;
18956            }
18957        }
18958        return false;
18959    }
18960
18961    /**
18962     * Dispatch a fling to a nested scrolling parent.
18963     *
18964     * <p>This method should be used to indicate that a nested scrolling child has detected
18965     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
18966     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
18967     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
18968     * along a scrollable axis.</p>
18969     *
18970     * <p>If a nested scrolling child view would normally fling but it is at the edge of
18971     * its own content, it can use this method to delegate the fling to its nested scrolling
18972     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
18973     *
18974     * @param velocityX Horizontal fling velocity in pixels per second
18975     * @param velocityY Vertical fling velocity in pixels per second
18976     * @param consumed true if the child consumed the fling, false otherwise
18977     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
18978     */
18979    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
18980        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18981            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
18982        }
18983        return false;
18984    }
18985
18986    /**
18987     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
18988     *
18989     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
18990     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
18991     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
18992     * before the child view consumes it. If this method returns <code>true</code>, a nested
18993     * parent view consumed the fling and this view should not scroll as a result.</p>
18994     *
18995     * <p>For a better user experience, only one view in a nested scrolling chain should consume
18996     * the fling at a time. If a parent view consumed the fling this method will return false.
18997     * Custom view implementations should account for this in two ways:</p>
18998     *
18999     * <ul>
19000     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
19001     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
19002     *     position regardless.</li>
19003     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
19004     *     even to settle back to a valid idle position.</li>
19005     * </ul>
19006     *
19007     * <p>Views should also not offer fling velocities to nested parent views along an axis
19008     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
19009     * should not offer a horizontal fling velocity to its parents since scrolling along that
19010     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
19011     *
19012     * @param velocityX Horizontal fling velocity in pixels per second
19013     * @param velocityY Vertical fling velocity in pixels per second
19014     * @return true if a nested scrolling parent consumed the fling
19015     */
19016    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
19017        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19018            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
19019        }
19020        return false;
19021    }
19022
19023    /**
19024     * Gets a scale factor that determines the distance the view should scroll
19025     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
19026     * @return The vertical scroll scale factor.
19027     * @hide
19028     */
19029    protected float getVerticalScrollFactor() {
19030        if (mVerticalScrollFactor == 0) {
19031            TypedValue outValue = new TypedValue();
19032            if (!mContext.getTheme().resolveAttribute(
19033                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
19034                throw new IllegalStateException(
19035                        "Expected theme to define listPreferredItemHeight.");
19036            }
19037            mVerticalScrollFactor = outValue.getDimension(
19038                    mContext.getResources().getDisplayMetrics());
19039        }
19040        return mVerticalScrollFactor;
19041    }
19042
19043    /**
19044     * Gets a scale factor that determines the distance the view should scroll
19045     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
19046     * @return The horizontal scroll scale factor.
19047     * @hide
19048     */
19049    protected float getHorizontalScrollFactor() {
19050        // TODO: Should use something else.
19051        return getVerticalScrollFactor();
19052    }
19053
19054    /**
19055     * Return the value specifying the text direction or policy that was set with
19056     * {@link #setTextDirection(int)}.
19057     *
19058     * @return the defined text direction. It can be one of:
19059     *
19060     * {@link #TEXT_DIRECTION_INHERIT},
19061     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19062     * {@link #TEXT_DIRECTION_ANY_RTL},
19063     * {@link #TEXT_DIRECTION_LTR},
19064     * {@link #TEXT_DIRECTION_RTL},
19065     * {@link #TEXT_DIRECTION_LOCALE}
19066     *
19067     * @attr ref android.R.styleable#View_textDirection
19068     *
19069     * @hide
19070     */
19071    @ViewDebug.ExportedProperty(category = "text", mapping = {
19072            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19073            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19074            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19075            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19076            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19077            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19078    })
19079    public int getRawTextDirection() {
19080        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
19081    }
19082
19083    /**
19084     * Set the text direction.
19085     *
19086     * @param textDirection the direction to set. Should be one of:
19087     *
19088     * {@link #TEXT_DIRECTION_INHERIT},
19089     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19090     * {@link #TEXT_DIRECTION_ANY_RTL},
19091     * {@link #TEXT_DIRECTION_LTR},
19092     * {@link #TEXT_DIRECTION_RTL},
19093     * {@link #TEXT_DIRECTION_LOCALE}
19094     *
19095     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
19096     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
19097     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
19098     *
19099     * @attr ref android.R.styleable#View_textDirection
19100     */
19101    public void setTextDirection(int textDirection) {
19102        if (getRawTextDirection() != textDirection) {
19103            // Reset the current text direction and the resolved one
19104            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
19105            resetResolvedTextDirection();
19106            // Set the new text direction
19107            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
19108            // Do resolution
19109            resolveTextDirection();
19110            // Notify change
19111            onRtlPropertiesChanged(getLayoutDirection());
19112            // Refresh
19113            requestLayout();
19114            invalidate(true);
19115        }
19116    }
19117
19118    /**
19119     * Return the resolved text direction.
19120     *
19121     * @return the resolved text direction. Returns one of:
19122     *
19123     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19124     * {@link #TEXT_DIRECTION_ANY_RTL},
19125     * {@link #TEXT_DIRECTION_LTR},
19126     * {@link #TEXT_DIRECTION_RTL},
19127     * {@link #TEXT_DIRECTION_LOCALE}
19128     *
19129     * @attr ref android.R.styleable#View_textDirection
19130     */
19131    @ViewDebug.ExportedProperty(category = "text", mapping = {
19132            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19133            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19134            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19135            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19136            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19137            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19138    })
19139    public int getTextDirection() {
19140        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
19141    }
19142
19143    /**
19144     * Resolve the text direction.
19145     *
19146     * @return true if resolution has been done, false otherwise.
19147     *
19148     * @hide
19149     */
19150    public boolean resolveTextDirection() {
19151        // Reset any previous text direction resolution
19152        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19153
19154        if (hasRtlSupport()) {
19155            // Set resolved text direction flag depending on text direction flag
19156            final int textDirection = getRawTextDirection();
19157            switch(textDirection) {
19158                case TEXT_DIRECTION_INHERIT:
19159                    if (!canResolveTextDirection()) {
19160                        // We cannot do the resolution if there is no parent, so use the default one
19161                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19162                        // Resolution will need to happen again later
19163                        return false;
19164                    }
19165
19166                    // Parent has not yet resolved, so we still return the default
19167                    try {
19168                        if (!mParent.isTextDirectionResolved()) {
19169                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19170                            // Resolution will need to happen again later
19171                            return false;
19172                        }
19173                    } catch (AbstractMethodError e) {
19174                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19175                                " does not fully implement ViewParent", e);
19176                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19177                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19178                        return true;
19179                    }
19180
19181                    // Set current resolved direction to the same value as the parent's one
19182                    int parentResolvedDirection;
19183                    try {
19184                        parentResolvedDirection = mParent.getTextDirection();
19185                    } catch (AbstractMethodError e) {
19186                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19187                                " does not fully implement ViewParent", e);
19188                        parentResolvedDirection = TEXT_DIRECTION_LTR;
19189                    }
19190                    switch (parentResolvedDirection) {
19191                        case TEXT_DIRECTION_FIRST_STRONG:
19192                        case TEXT_DIRECTION_ANY_RTL:
19193                        case TEXT_DIRECTION_LTR:
19194                        case TEXT_DIRECTION_RTL:
19195                        case TEXT_DIRECTION_LOCALE:
19196                            mPrivateFlags2 |=
19197                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19198                            break;
19199                        default:
19200                            // Default resolved direction is "first strong" heuristic
19201                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19202                    }
19203                    break;
19204                case TEXT_DIRECTION_FIRST_STRONG:
19205                case TEXT_DIRECTION_ANY_RTL:
19206                case TEXT_DIRECTION_LTR:
19207                case TEXT_DIRECTION_RTL:
19208                case TEXT_DIRECTION_LOCALE:
19209                    // Resolved direction is the same as text direction
19210                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19211                    break;
19212                default:
19213                    // Default resolved direction is "first strong" heuristic
19214                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19215            }
19216        } else {
19217            // Default resolved direction is "first strong" heuristic
19218            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19219        }
19220
19221        // Set to resolved
19222        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19223        return true;
19224    }
19225
19226    /**
19227     * Check if text direction resolution can be done.
19228     *
19229     * @return true if text direction resolution can be done otherwise return false.
19230     */
19231    public boolean canResolveTextDirection() {
19232        switch (getRawTextDirection()) {
19233            case TEXT_DIRECTION_INHERIT:
19234                if (mParent != null) {
19235                    try {
19236                        return mParent.canResolveTextDirection();
19237                    } catch (AbstractMethodError e) {
19238                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19239                                " does not fully implement ViewParent", e);
19240                    }
19241                }
19242                return false;
19243
19244            default:
19245                return true;
19246        }
19247    }
19248
19249    /**
19250     * Reset resolved text direction. Text direction will be resolved during a call to
19251     * {@link #onMeasure(int, int)}.
19252     *
19253     * @hide
19254     */
19255    public void resetResolvedTextDirection() {
19256        // Reset any previous text direction resolution
19257        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19258        // Set to default value
19259        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19260    }
19261
19262    /**
19263     * @return true if text direction is inherited.
19264     *
19265     * @hide
19266     */
19267    public boolean isTextDirectionInherited() {
19268        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19269    }
19270
19271    /**
19272     * @return true if text direction is resolved.
19273     */
19274    public boolean isTextDirectionResolved() {
19275        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19276    }
19277
19278    /**
19279     * Return the value specifying the text alignment or policy that was set with
19280     * {@link #setTextAlignment(int)}.
19281     *
19282     * @return the defined text alignment. It can be one of:
19283     *
19284     * {@link #TEXT_ALIGNMENT_INHERIT},
19285     * {@link #TEXT_ALIGNMENT_GRAVITY},
19286     * {@link #TEXT_ALIGNMENT_CENTER},
19287     * {@link #TEXT_ALIGNMENT_TEXT_START},
19288     * {@link #TEXT_ALIGNMENT_TEXT_END},
19289     * {@link #TEXT_ALIGNMENT_VIEW_START},
19290     * {@link #TEXT_ALIGNMENT_VIEW_END}
19291     *
19292     * @attr ref android.R.styleable#View_textAlignment
19293     *
19294     * @hide
19295     */
19296    @ViewDebug.ExportedProperty(category = "text", mapping = {
19297            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19298            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19299            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19300            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19301            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19302            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19303            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19304    })
19305    @TextAlignment
19306    public int getRawTextAlignment() {
19307        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19308    }
19309
19310    /**
19311     * Set the text alignment.
19312     *
19313     * @param textAlignment The text alignment to set. Should be one of
19314     *
19315     * {@link #TEXT_ALIGNMENT_INHERIT},
19316     * {@link #TEXT_ALIGNMENT_GRAVITY},
19317     * {@link #TEXT_ALIGNMENT_CENTER},
19318     * {@link #TEXT_ALIGNMENT_TEXT_START},
19319     * {@link #TEXT_ALIGNMENT_TEXT_END},
19320     * {@link #TEXT_ALIGNMENT_VIEW_START},
19321     * {@link #TEXT_ALIGNMENT_VIEW_END}
19322     *
19323     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19324     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19325     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19326     *
19327     * @attr ref android.R.styleable#View_textAlignment
19328     */
19329    public void setTextAlignment(@TextAlignment int textAlignment) {
19330        if (textAlignment != getRawTextAlignment()) {
19331            // Reset the current and resolved text alignment
19332            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19333            resetResolvedTextAlignment();
19334            // Set the new text alignment
19335            mPrivateFlags2 |=
19336                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19337            // Do resolution
19338            resolveTextAlignment();
19339            // Notify change
19340            onRtlPropertiesChanged(getLayoutDirection());
19341            // Refresh
19342            requestLayout();
19343            invalidate(true);
19344        }
19345    }
19346
19347    /**
19348     * Return the resolved text alignment.
19349     *
19350     * @return the resolved text alignment. Returns one of:
19351     *
19352     * {@link #TEXT_ALIGNMENT_GRAVITY},
19353     * {@link #TEXT_ALIGNMENT_CENTER},
19354     * {@link #TEXT_ALIGNMENT_TEXT_START},
19355     * {@link #TEXT_ALIGNMENT_TEXT_END},
19356     * {@link #TEXT_ALIGNMENT_VIEW_START},
19357     * {@link #TEXT_ALIGNMENT_VIEW_END}
19358     *
19359     * @attr ref android.R.styleable#View_textAlignment
19360     */
19361    @ViewDebug.ExportedProperty(category = "text", mapping = {
19362            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19363            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19364            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19365            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19366            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19367            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19368            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19369    })
19370    @TextAlignment
19371    public int getTextAlignment() {
19372        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
19373                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
19374    }
19375
19376    /**
19377     * Resolve the text alignment.
19378     *
19379     * @return true if resolution has been done, false otherwise.
19380     *
19381     * @hide
19382     */
19383    public boolean resolveTextAlignment() {
19384        // Reset any previous text alignment resolution
19385        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19386
19387        if (hasRtlSupport()) {
19388            // Set resolved text alignment flag depending on text alignment flag
19389            final int textAlignment = getRawTextAlignment();
19390            switch (textAlignment) {
19391                case TEXT_ALIGNMENT_INHERIT:
19392                    // Check if we can resolve the text alignment
19393                    if (!canResolveTextAlignment()) {
19394                        // We cannot do the resolution if there is no parent so use the default
19395                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19396                        // Resolution will need to happen again later
19397                        return false;
19398                    }
19399
19400                    // Parent has not yet resolved, so we still return the default
19401                    try {
19402                        if (!mParent.isTextAlignmentResolved()) {
19403                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19404                            // Resolution will need to happen again later
19405                            return false;
19406                        }
19407                    } catch (AbstractMethodError e) {
19408                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19409                                " does not fully implement ViewParent", e);
19410                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
19411                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19412                        return true;
19413                    }
19414
19415                    int parentResolvedTextAlignment;
19416                    try {
19417                        parentResolvedTextAlignment = mParent.getTextAlignment();
19418                    } catch (AbstractMethodError e) {
19419                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19420                                " does not fully implement ViewParent", e);
19421                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
19422                    }
19423                    switch (parentResolvedTextAlignment) {
19424                        case TEXT_ALIGNMENT_GRAVITY:
19425                        case TEXT_ALIGNMENT_TEXT_START:
19426                        case TEXT_ALIGNMENT_TEXT_END:
19427                        case TEXT_ALIGNMENT_CENTER:
19428                        case TEXT_ALIGNMENT_VIEW_START:
19429                        case TEXT_ALIGNMENT_VIEW_END:
19430                            // Resolved text alignment is the same as the parent resolved
19431                            // text alignment
19432                            mPrivateFlags2 |=
19433                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19434                            break;
19435                        default:
19436                            // Use default resolved text alignment
19437                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19438                    }
19439                    break;
19440                case TEXT_ALIGNMENT_GRAVITY:
19441                case TEXT_ALIGNMENT_TEXT_START:
19442                case TEXT_ALIGNMENT_TEXT_END:
19443                case TEXT_ALIGNMENT_CENTER:
19444                case TEXT_ALIGNMENT_VIEW_START:
19445                case TEXT_ALIGNMENT_VIEW_END:
19446                    // Resolved text alignment is the same as text alignment
19447                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19448                    break;
19449                default:
19450                    // Use default resolved text alignment
19451                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19452            }
19453        } else {
19454            // Use default resolved text alignment
19455            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19456        }
19457
19458        // Set the resolved
19459        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19460        return true;
19461    }
19462
19463    /**
19464     * Check if text alignment resolution can be done.
19465     *
19466     * @return true if text alignment resolution can be done otherwise return false.
19467     */
19468    public boolean canResolveTextAlignment() {
19469        switch (getRawTextAlignment()) {
19470            case TEXT_DIRECTION_INHERIT:
19471                if (mParent != null) {
19472                    try {
19473                        return mParent.canResolveTextAlignment();
19474                    } catch (AbstractMethodError e) {
19475                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19476                                " does not fully implement ViewParent", e);
19477                    }
19478                }
19479                return false;
19480
19481            default:
19482                return true;
19483        }
19484    }
19485
19486    /**
19487     * Reset resolved text alignment. Text alignment will be resolved during a call to
19488     * {@link #onMeasure(int, int)}.
19489     *
19490     * @hide
19491     */
19492    public void resetResolvedTextAlignment() {
19493        // Reset any previous text alignment resolution
19494        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19495        // Set to default
19496        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19497    }
19498
19499    /**
19500     * @return true if text alignment is inherited.
19501     *
19502     * @hide
19503     */
19504    public boolean isTextAlignmentInherited() {
19505        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
19506    }
19507
19508    /**
19509     * @return true if text alignment is resolved.
19510     */
19511    public boolean isTextAlignmentResolved() {
19512        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19513    }
19514
19515    /**
19516     * Generate a value suitable for use in {@link #setId(int)}.
19517     * This value will not collide with ID values generated at build time by aapt for R.id.
19518     *
19519     * @return a generated ID value
19520     */
19521    public static int generateViewId() {
19522        for (;;) {
19523            final int result = sNextGeneratedId.get();
19524            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
19525            int newValue = result + 1;
19526            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
19527            if (sNextGeneratedId.compareAndSet(result, newValue)) {
19528                return result;
19529            }
19530        }
19531    }
19532
19533    /**
19534     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
19535     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
19536     *                           a normal View or a ViewGroup with
19537     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
19538     * @hide
19539     */
19540    public void captureTransitioningViews(List<View> transitioningViews) {
19541        if (getVisibility() == View.VISIBLE) {
19542            transitioningViews.add(this);
19543        }
19544    }
19545
19546    /**
19547     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
19548     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
19549     * @hide
19550     */
19551    public void findNamedViews(Map<String, View> namedElements) {
19552        if (getVisibility() == VISIBLE || mGhostView != null) {
19553            String transitionName = getTransitionName();
19554            if (transitionName != null) {
19555                namedElements.put(transitionName, this);
19556            }
19557        }
19558    }
19559
19560    //
19561    // Properties
19562    //
19563    /**
19564     * A Property wrapper around the <code>alpha</code> functionality handled by the
19565     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
19566     */
19567    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
19568        @Override
19569        public void setValue(View object, float value) {
19570            object.setAlpha(value);
19571        }
19572
19573        @Override
19574        public Float get(View object) {
19575            return object.getAlpha();
19576        }
19577    };
19578
19579    /**
19580     * A Property wrapper around the <code>translationX</code> functionality handled by the
19581     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
19582     */
19583    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
19584        @Override
19585        public void setValue(View object, float value) {
19586            object.setTranslationX(value);
19587        }
19588
19589                @Override
19590        public Float get(View object) {
19591            return object.getTranslationX();
19592        }
19593    };
19594
19595    /**
19596     * A Property wrapper around the <code>translationY</code> functionality handled by the
19597     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
19598     */
19599    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
19600        @Override
19601        public void setValue(View object, float value) {
19602            object.setTranslationY(value);
19603        }
19604
19605        @Override
19606        public Float get(View object) {
19607            return object.getTranslationY();
19608        }
19609    };
19610
19611    /**
19612     * A Property wrapper around the <code>translationZ</code> functionality handled by the
19613     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
19614     */
19615    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
19616        @Override
19617        public void setValue(View object, float value) {
19618            object.setTranslationZ(value);
19619        }
19620
19621        @Override
19622        public Float get(View object) {
19623            return object.getTranslationZ();
19624        }
19625    };
19626
19627    /**
19628     * A Property wrapper around the <code>x</code> functionality handled by the
19629     * {@link View#setX(float)} and {@link View#getX()} methods.
19630     */
19631    public static final Property<View, Float> X = new FloatProperty<View>("x") {
19632        @Override
19633        public void setValue(View object, float value) {
19634            object.setX(value);
19635        }
19636
19637        @Override
19638        public Float get(View object) {
19639            return object.getX();
19640        }
19641    };
19642
19643    /**
19644     * A Property wrapper around the <code>y</code> functionality handled by the
19645     * {@link View#setY(float)} and {@link View#getY()} methods.
19646     */
19647    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
19648        @Override
19649        public void setValue(View object, float value) {
19650            object.setY(value);
19651        }
19652
19653        @Override
19654        public Float get(View object) {
19655            return object.getY();
19656        }
19657    };
19658
19659    /**
19660     * A Property wrapper around the <code>z</code> functionality handled by the
19661     * {@link View#setZ(float)} and {@link View#getZ()} methods.
19662     */
19663    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
19664        @Override
19665        public void setValue(View object, float value) {
19666            object.setZ(value);
19667        }
19668
19669        @Override
19670        public Float get(View object) {
19671            return object.getZ();
19672        }
19673    };
19674
19675    /**
19676     * A Property wrapper around the <code>rotation</code> functionality handled by the
19677     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
19678     */
19679    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
19680        @Override
19681        public void setValue(View object, float value) {
19682            object.setRotation(value);
19683        }
19684
19685        @Override
19686        public Float get(View object) {
19687            return object.getRotation();
19688        }
19689    };
19690
19691    /**
19692     * A Property wrapper around the <code>rotationX</code> functionality handled by the
19693     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
19694     */
19695    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
19696        @Override
19697        public void setValue(View object, float value) {
19698            object.setRotationX(value);
19699        }
19700
19701        @Override
19702        public Float get(View object) {
19703            return object.getRotationX();
19704        }
19705    };
19706
19707    /**
19708     * A Property wrapper around the <code>rotationY</code> functionality handled by the
19709     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
19710     */
19711    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
19712        @Override
19713        public void setValue(View object, float value) {
19714            object.setRotationY(value);
19715        }
19716
19717        @Override
19718        public Float get(View object) {
19719            return object.getRotationY();
19720        }
19721    };
19722
19723    /**
19724     * A Property wrapper around the <code>scaleX</code> functionality handled by the
19725     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
19726     */
19727    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
19728        @Override
19729        public void setValue(View object, float value) {
19730            object.setScaleX(value);
19731        }
19732
19733        @Override
19734        public Float get(View object) {
19735            return object.getScaleX();
19736        }
19737    };
19738
19739    /**
19740     * A Property wrapper around the <code>scaleY</code> functionality handled by the
19741     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
19742     */
19743    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
19744        @Override
19745        public void setValue(View object, float value) {
19746            object.setScaleY(value);
19747        }
19748
19749        @Override
19750        public Float get(View object) {
19751            return object.getScaleY();
19752        }
19753    };
19754
19755    /**
19756     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
19757     * Each MeasureSpec represents a requirement for either the width or the height.
19758     * A MeasureSpec is comprised of a size and a mode. There are three possible
19759     * modes:
19760     * <dl>
19761     * <dt>UNSPECIFIED</dt>
19762     * <dd>
19763     * The parent has not imposed any constraint on the child. It can be whatever size
19764     * it wants.
19765     * </dd>
19766     *
19767     * <dt>EXACTLY</dt>
19768     * <dd>
19769     * The parent has determined an exact size for the child. The child is going to be
19770     * given those bounds regardless of how big it wants to be.
19771     * </dd>
19772     *
19773     * <dt>AT_MOST</dt>
19774     * <dd>
19775     * The child can be as large as it wants up to the specified size.
19776     * </dd>
19777     * </dl>
19778     *
19779     * MeasureSpecs are implemented as ints to reduce object allocation. This class
19780     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
19781     */
19782    public static class MeasureSpec {
19783        private static final int MODE_SHIFT = 30;
19784        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
19785
19786        /**
19787         * Measure specification mode: The parent has not imposed any constraint
19788         * on the child. It can be whatever size it wants.
19789         */
19790        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
19791
19792        /**
19793         * Measure specification mode: The parent has determined an exact size
19794         * for the child. The child is going to be given those bounds regardless
19795         * of how big it wants to be.
19796         */
19797        public static final int EXACTLY     = 1 << MODE_SHIFT;
19798
19799        /**
19800         * Measure specification mode: The child can be as large as it wants up
19801         * to the specified size.
19802         */
19803        public static final int AT_MOST     = 2 << MODE_SHIFT;
19804
19805        /**
19806         * Creates a measure specification based on the supplied size and mode.
19807         *
19808         * The mode must always be one of the following:
19809         * <ul>
19810         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
19811         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
19812         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
19813         * </ul>
19814         *
19815         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
19816         * implementation was such that the order of arguments did not matter
19817         * and overflow in either value could impact the resulting MeasureSpec.
19818         * {@link android.widget.RelativeLayout} was affected by this bug.
19819         * Apps targeting API levels greater than 17 will get the fixed, more strict
19820         * behavior.</p>
19821         *
19822         * @param size the size of the measure specification
19823         * @param mode the mode of the measure specification
19824         * @return the measure specification based on size and mode
19825         */
19826        public static int makeMeasureSpec(int size, int mode) {
19827            if (sUseBrokenMakeMeasureSpec) {
19828                return size + mode;
19829            } else {
19830                return (size & ~MODE_MASK) | (mode & MODE_MASK);
19831            }
19832        }
19833
19834        /**
19835         * Extracts the mode from the supplied measure specification.
19836         *
19837         * @param measureSpec the measure specification to extract the mode from
19838         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
19839         *         {@link android.view.View.MeasureSpec#AT_MOST} or
19840         *         {@link android.view.View.MeasureSpec#EXACTLY}
19841         */
19842        public static int getMode(int measureSpec) {
19843            return (measureSpec & MODE_MASK);
19844        }
19845
19846        /**
19847         * Extracts the size from the supplied measure specification.
19848         *
19849         * @param measureSpec the measure specification to extract the size from
19850         * @return the size in pixels defined in the supplied measure specification
19851         */
19852        public static int getSize(int measureSpec) {
19853            return (measureSpec & ~MODE_MASK);
19854        }
19855
19856        static int adjust(int measureSpec, int delta) {
19857            final int mode = getMode(measureSpec);
19858            if (mode == UNSPECIFIED) {
19859                // No need to adjust size for UNSPECIFIED mode.
19860                return makeMeasureSpec(0, UNSPECIFIED);
19861            }
19862            int size = getSize(measureSpec) + delta;
19863            if (size < 0) {
19864                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19865                        ") spec: " + toString(measureSpec) + " delta: " + delta);
19866                size = 0;
19867            }
19868            return makeMeasureSpec(size, mode);
19869        }
19870
19871        /**
19872         * Returns a String representation of the specified measure
19873         * specification.
19874         *
19875         * @param measureSpec the measure specification to convert to a String
19876         * @return a String with the following format: "MeasureSpec: MODE SIZE"
19877         */
19878        public static String toString(int measureSpec) {
19879            int mode = getMode(measureSpec);
19880            int size = getSize(measureSpec);
19881
19882            StringBuilder sb = new StringBuilder("MeasureSpec: ");
19883
19884            if (mode == UNSPECIFIED)
19885                sb.append("UNSPECIFIED ");
19886            else if (mode == EXACTLY)
19887                sb.append("EXACTLY ");
19888            else if (mode == AT_MOST)
19889                sb.append("AT_MOST ");
19890            else
19891                sb.append(mode).append(" ");
19892
19893            sb.append(size);
19894            return sb.toString();
19895        }
19896    }
19897
19898    private final class CheckForLongPress implements Runnable {
19899        private int mOriginalWindowAttachCount;
19900
19901        @Override
19902        public void run() {
19903            if (isPressed() && (mParent != null)
19904                    && mOriginalWindowAttachCount == mWindowAttachCount) {
19905                if (performLongClick()) {
19906                    mHasPerformedLongPress = true;
19907                }
19908            }
19909        }
19910
19911        public void rememberWindowAttachCount() {
19912            mOriginalWindowAttachCount = mWindowAttachCount;
19913        }
19914    }
19915
19916    private final class CheckForTap implements Runnable {
19917        public float x;
19918        public float y;
19919
19920        @Override
19921        public void run() {
19922            mPrivateFlags &= ~PFLAG_PREPRESSED;
19923            setPressed(true, x, y);
19924            checkForLongClick(ViewConfiguration.getTapTimeout());
19925        }
19926    }
19927
19928    private final class PerformClick implements Runnable {
19929        @Override
19930        public void run() {
19931            performClick();
19932        }
19933    }
19934
19935    /** @hide */
19936    public void hackTurnOffWindowResizeAnim(boolean off) {
19937        mAttachInfo.mTurnOffWindowResizeAnim = off;
19938    }
19939
19940    /**
19941     * This method returns a ViewPropertyAnimator object, which can be used to animate
19942     * specific properties on this View.
19943     *
19944     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19945     */
19946    public ViewPropertyAnimator animate() {
19947        if (mAnimator == null) {
19948            mAnimator = new ViewPropertyAnimator(this);
19949        }
19950        return mAnimator;
19951    }
19952
19953    /**
19954     * Sets the name of the View to be used to identify Views in Transitions.
19955     * Names should be unique in the View hierarchy.
19956     *
19957     * @param transitionName The name of the View to uniquely identify it for Transitions.
19958     */
19959    public final void setTransitionName(String transitionName) {
19960        mTransitionName = transitionName;
19961    }
19962
19963    /**
19964     * Returns the name of the View to be used to identify Views in Transitions.
19965     * Names should be unique in the View hierarchy.
19966     *
19967     * <p>This returns null if the View has not been given a name.</p>
19968     *
19969     * @return The name used of the View to be used to identify Views in Transitions or null
19970     * if no name has been given.
19971     */
19972    @ViewDebug.ExportedProperty
19973    public String getTransitionName() {
19974        return mTransitionName;
19975    }
19976
19977    /**
19978     * Interface definition for a callback to be invoked when a hardware key event is
19979     * dispatched to this view. The callback will be invoked before the key event is
19980     * given to the view. This is only useful for hardware keyboards; a software input
19981     * method has no obligation to trigger this listener.
19982     */
19983    public interface OnKeyListener {
19984        /**
19985         * Called when a hardware key is dispatched to a view. This allows listeners to
19986         * get a chance to respond before the target view.
19987         * <p>Key presses in software keyboards will generally NOT trigger this method,
19988         * although some may elect to do so in some situations. Do not assume a
19989         * software input method has to be key-based; even if it is, it may use key presses
19990         * in a different way than you expect, so there is no way to reliably catch soft
19991         * input key presses.
19992         *
19993         * @param v The view the key has been dispatched to.
19994         * @param keyCode The code for the physical key that was pressed
19995         * @param event The KeyEvent object containing full information about
19996         *        the event.
19997         * @return True if the listener has consumed the event, false otherwise.
19998         */
19999        boolean onKey(View v, int keyCode, KeyEvent event);
20000    }
20001
20002    /**
20003     * Interface definition for a callback to be invoked when a touch event is
20004     * dispatched to this view. The callback will be invoked before the touch
20005     * event is given to the view.
20006     */
20007    public interface OnTouchListener {
20008        /**
20009         * Called when a touch event is dispatched to a view. This allows listeners to
20010         * get a chance to respond before the target view.
20011         *
20012         * @param v The view the touch event has been dispatched to.
20013         * @param event The MotionEvent object containing full information about
20014         *        the event.
20015         * @return True if the listener has consumed the event, false otherwise.
20016         */
20017        boolean onTouch(View v, MotionEvent event);
20018    }
20019
20020    /**
20021     * Interface definition for a callback to be invoked when a hover event is
20022     * dispatched to this view. The callback will be invoked before the hover
20023     * event is given to the view.
20024     */
20025    public interface OnHoverListener {
20026        /**
20027         * Called when a hover event is dispatched to a view. This allows listeners to
20028         * get a chance to respond before the target view.
20029         *
20030         * @param v The view the hover event has been dispatched to.
20031         * @param event The MotionEvent object containing full information about
20032         *        the event.
20033         * @return True if the listener has consumed the event, false otherwise.
20034         */
20035        boolean onHover(View v, MotionEvent event);
20036    }
20037
20038    /**
20039     * Interface definition for a callback to be invoked when a generic motion event is
20040     * dispatched to this view. The callback will be invoked before the generic motion
20041     * event is given to the view.
20042     */
20043    public interface OnGenericMotionListener {
20044        /**
20045         * Called when a generic motion event is dispatched to a view. This allows listeners to
20046         * get a chance to respond before the target view.
20047         *
20048         * @param v The view the generic motion event has been dispatched to.
20049         * @param event The MotionEvent object containing full information about
20050         *        the event.
20051         * @return True if the listener has consumed the event, false otherwise.
20052         */
20053        boolean onGenericMotion(View v, MotionEvent event);
20054    }
20055
20056    /**
20057     * Interface definition for a callback to be invoked when a view has been clicked and held.
20058     */
20059    public interface OnLongClickListener {
20060        /**
20061         * Called when a view has been clicked and held.
20062         *
20063         * @param v The view that was clicked and held.
20064         *
20065         * @return true if the callback consumed the long click, false otherwise.
20066         */
20067        boolean onLongClick(View v);
20068    }
20069
20070    /**
20071     * Interface definition for a callback to be invoked when a drag is being dispatched
20072     * to this view.  The callback will be invoked before the hosting view's own
20073     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
20074     * onDrag(event) behavior, it should return 'false' from this callback.
20075     *
20076     * <div class="special reference">
20077     * <h3>Developer Guides</h3>
20078     * <p>For a guide to implementing drag and drop features, read the
20079     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20080     * </div>
20081     */
20082    public interface OnDragListener {
20083        /**
20084         * Called when a drag event is dispatched to a view. This allows listeners
20085         * to get a chance to override base View behavior.
20086         *
20087         * @param v The View that received the drag event.
20088         * @param event The {@link android.view.DragEvent} object for the drag event.
20089         * @return {@code true} if the drag event was handled successfully, or {@code false}
20090         * if the drag event was not handled. Note that {@code false} will trigger the View
20091         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
20092         */
20093        boolean onDrag(View v, DragEvent event);
20094    }
20095
20096    /**
20097     * Interface definition for a callback to be invoked when the focus state of
20098     * a view changed.
20099     */
20100    public interface OnFocusChangeListener {
20101        /**
20102         * Called when the focus state of a view has changed.
20103         *
20104         * @param v The view whose state has changed.
20105         * @param hasFocus The new focus state of v.
20106         */
20107        void onFocusChange(View v, boolean hasFocus);
20108    }
20109
20110    /**
20111     * Interface definition for a callback to be invoked when a view is clicked.
20112     */
20113    public interface OnClickListener {
20114        /**
20115         * Called when a view has been clicked.
20116         *
20117         * @param v The view that was clicked.
20118         */
20119        void onClick(View v);
20120    }
20121
20122    /**
20123     * Interface definition for a callback to be invoked when the context menu
20124     * for this view is being built.
20125     */
20126    public interface OnCreateContextMenuListener {
20127        /**
20128         * Called when the context menu for this view is being built. It is not
20129         * safe to hold onto the menu after this method returns.
20130         *
20131         * @param menu The context menu that is being built
20132         * @param v The view for which the context menu is being built
20133         * @param menuInfo Extra information about the item for which the
20134         *            context menu should be shown. This information will vary
20135         *            depending on the class of v.
20136         */
20137        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
20138    }
20139
20140    /**
20141     * Interface definition for a callback to be invoked when the status bar changes
20142     * visibility.  This reports <strong>global</strong> changes to the system UI
20143     * state, not what the application is requesting.
20144     *
20145     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
20146     */
20147    public interface OnSystemUiVisibilityChangeListener {
20148        /**
20149         * Called when the status bar changes visibility because of a call to
20150         * {@link View#setSystemUiVisibility(int)}.
20151         *
20152         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20153         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
20154         * This tells you the <strong>global</strong> state of these UI visibility
20155         * flags, not what your app is currently applying.
20156         */
20157        public void onSystemUiVisibilityChange(int visibility);
20158    }
20159
20160    /**
20161     * Interface definition for a callback to be invoked when this view is attached
20162     * or detached from its window.
20163     */
20164    public interface OnAttachStateChangeListener {
20165        /**
20166         * Called when the view is attached to a window.
20167         * @param v The view that was attached
20168         */
20169        public void onViewAttachedToWindow(View v);
20170        /**
20171         * Called when the view is detached from a window.
20172         * @param v The view that was detached
20173         */
20174        public void onViewDetachedFromWindow(View v);
20175    }
20176
20177    /**
20178     * Listener for applying window insets on a view in a custom way.
20179     *
20180     * <p>Apps may choose to implement this interface if they want to apply custom policy
20181     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20182     * is set, its
20183     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20184     * method will be called instead of the View's own
20185     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20186     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20187     * the View's normal behavior as part of its own.</p>
20188     */
20189    public interface OnApplyWindowInsetsListener {
20190        /**
20191         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20192         * on a View, this listener method will be called instead of the view's own
20193         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20194         *
20195         * @param v The view applying window insets
20196         * @param insets The insets to apply
20197         * @return The insets supplied, minus any insets that were consumed
20198         */
20199        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20200    }
20201
20202    private final class UnsetPressedState implements Runnable {
20203        @Override
20204        public void run() {
20205            setPressed(false);
20206        }
20207    }
20208
20209    /**
20210     * Base class for derived classes that want to save and restore their own
20211     * state in {@link android.view.View#onSaveInstanceState()}.
20212     */
20213    public static class BaseSavedState extends AbsSavedState {
20214        /**
20215         * Constructor used when reading from a parcel. Reads the state of the superclass.
20216         *
20217         * @param source
20218         */
20219        public BaseSavedState(Parcel source) {
20220            super(source);
20221        }
20222
20223        /**
20224         * Constructor called by derived classes when creating their SavedState objects
20225         *
20226         * @param superState The state of the superclass of this view
20227         */
20228        public BaseSavedState(Parcelable superState) {
20229            super(superState);
20230        }
20231
20232        public static final Parcelable.Creator<BaseSavedState> CREATOR =
20233                new Parcelable.Creator<BaseSavedState>() {
20234            public BaseSavedState createFromParcel(Parcel in) {
20235                return new BaseSavedState(in);
20236            }
20237
20238            public BaseSavedState[] newArray(int size) {
20239                return new BaseSavedState[size];
20240            }
20241        };
20242    }
20243
20244    /**
20245     * A set of information given to a view when it is attached to its parent
20246     * window.
20247     */
20248    final static class AttachInfo {
20249        interface Callbacks {
20250            void playSoundEffect(int effectId);
20251            boolean performHapticFeedback(int effectId, boolean always);
20252        }
20253
20254        /**
20255         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20256         * to a Handler. This class contains the target (View) to invalidate and
20257         * the coordinates of the dirty rectangle.
20258         *
20259         * For performance purposes, this class also implements a pool of up to
20260         * POOL_LIMIT objects that get reused. This reduces memory allocations
20261         * whenever possible.
20262         */
20263        static class InvalidateInfo {
20264            private static final int POOL_LIMIT = 10;
20265
20266            private static final SynchronizedPool<InvalidateInfo> sPool =
20267                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20268
20269            View target;
20270
20271            int left;
20272            int top;
20273            int right;
20274            int bottom;
20275
20276            public static InvalidateInfo obtain() {
20277                InvalidateInfo instance = sPool.acquire();
20278                return (instance != null) ? instance : new InvalidateInfo();
20279            }
20280
20281            public void recycle() {
20282                target = null;
20283                sPool.release(this);
20284            }
20285        }
20286
20287        final IWindowSession mSession;
20288
20289        final IWindow mWindow;
20290
20291        final IBinder mWindowToken;
20292
20293        final Display mDisplay;
20294
20295        final Callbacks mRootCallbacks;
20296
20297        IWindowId mIWindowId;
20298        WindowId mWindowId;
20299
20300        /**
20301         * The top view of the hierarchy.
20302         */
20303        View mRootView;
20304
20305        IBinder mPanelParentWindowToken;
20306
20307        boolean mHardwareAccelerated;
20308        boolean mHardwareAccelerationRequested;
20309        HardwareRenderer mHardwareRenderer;
20310        List<RenderNode> mPendingAnimatingRenderNodes;
20311
20312        /**
20313         * The state of the display to which the window is attached, as reported
20314         * by {@link Display#getState()}.  Note that the display state constants
20315         * declared by {@link Display} do not exactly line up with the screen state
20316         * constants declared by {@link View} (there are more display states than
20317         * screen states).
20318         */
20319        int mDisplayState = Display.STATE_UNKNOWN;
20320
20321        /**
20322         * Scale factor used by the compatibility mode
20323         */
20324        float mApplicationScale;
20325
20326        /**
20327         * Indicates whether the application is in compatibility mode
20328         */
20329        boolean mScalingRequired;
20330
20331        /**
20332         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20333         */
20334        boolean mTurnOffWindowResizeAnim;
20335
20336        /**
20337         * Left position of this view's window
20338         */
20339        int mWindowLeft;
20340
20341        /**
20342         * Top position of this view's window
20343         */
20344        int mWindowTop;
20345
20346        /**
20347         * Indicates whether views need to use 32-bit drawing caches
20348         */
20349        boolean mUse32BitDrawingCache;
20350
20351        /**
20352         * For windows that are full-screen but using insets to layout inside
20353         * of the screen areas, these are the current insets to appear inside
20354         * the overscan area of the display.
20355         */
20356        final Rect mOverscanInsets = new Rect();
20357
20358        /**
20359         * For windows that are full-screen but using insets to layout inside
20360         * of the screen decorations, these are the current insets for the
20361         * content of the window.
20362         */
20363        final Rect mContentInsets = new Rect();
20364
20365        /**
20366         * For windows that are full-screen but using insets to layout inside
20367         * of the screen decorations, these are the current insets for the
20368         * actual visible parts of the window.
20369         */
20370        final Rect mVisibleInsets = new Rect();
20371
20372        /**
20373         * For windows that are full-screen but using insets to layout inside
20374         * of the screen decorations, these are the current insets for the
20375         * stable system windows.
20376         */
20377        final Rect mStableInsets = new Rect();
20378
20379        /**
20380         * The internal insets given by this window.  This value is
20381         * supplied by the client (through
20382         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
20383         * be given to the window manager when changed to be used in laying
20384         * out windows behind it.
20385         */
20386        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
20387                = new ViewTreeObserver.InternalInsetsInfo();
20388
20389        /**
20390         * Set to true when mGivenInternalInsets is non-empty.
20391         */
20392        boolean mHasNonEmptyGivenInternalInsets;
20393
20394        /**
20395         * All views in the window's hierarchy that serve as scroll containers,
20396         * used to determine if the window can be resized or must be panned
20397         * to adjust for a soft input area.
20398         */
20399        final ArrayList<View> mScrollContainers = new ArrayList<View>();
20400
20401        final KeyEvent.DispatcherState mKeyDispatchState
20402                = new KeyEvent.DispatcherState();
20403
20404        /**
20405         * Indicates whether the view's window currently has the focus.
20406         */
20407        boolean mHasWindowFocus;
20408
20409        /**
20410         * The current visibility of the window.
20411         */
20412        int mWindowVisibility;
20413
20414        /**
20415         * Indicates the time at which drawing started to occur.
20416         */
20417        long mDrawingTime;
20418
20419        /**
20420         * Indicates whether or not ignoring the DIRTY_MASK flags.
20421         */
20422        boolean mIgnoreDirtyState;
20423
20424        /**
20425         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
20426         * to avoid clearing that flag prematurely.
20427         */
20428        boolean mSetIgnoreDirtyState = false;
20429
20430        /**
20431         * Indicates whether the view's window is currently in touch mode.
20432         */
20433        boolean mInTouchMode;
20434
20435        /**
20436         * Indicates whether the view has requested unbuffered input dispatching for the current
20437         * event stream.
20438         */
20439        boolean mUnbufferedDispatchRequested;
20440
20441        /**
20442         * Indicates that ViewAncestor should trigger a global layout change
20443         * the next time it performs a traversal
20444         */
20445        boolean mRecomputeGlobalAttributes;
20446
20447        /**
20448         * Always report new attributes at next traversal.
20449         */
20450        boolean mForceReportNewAttributes;
20451
20452        /**
20453         * Set during a traveral if any views want to keep the screen on.
20454         */
20455        boolean mKeepScreenOn;
20456
20457        /**
20458         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
20459         */
20460        int mSystemUiVisibility;
20461
20462        /**
20463         * Hack to force certain system UI visibility flags to be cleared.
20464         */
20465        int mDisabledSystemUiVisibility;
20466
20467        /**
20468         * Last global system UI visibility reported by the window manager.
20469         */
20470        int mGlobalSystemUiVisibility;
20471
20472        /**
20473         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
20474         * attached.
20475         */
20476        boolean mHasSystemUiListeners;
20477
20478        /**
20479         * Set if the window has requested to extend into the overscan region
20480         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
20481         */
20482        boolean mOverscanRequested;
20483
20484        /**
20485         * Set if the visibility of any views has changed.
20486         */
20487        boolean mViewVisibilityChanged;
20488
20489        /**
20490         * Set to true if a view has been scrolled.
20491         */
20492        boolean mViewScrollChanged;
20493
20494        /**
20495         * Set to true if high contrast mode enabled
20496         */
20497        boolean mHighContrastText;
20498
20499        /**
20500         * Global to the view hierarchy used as a temporary for dealing with
20501         * x/y points in the transparent region computations.
20502         */
20503        final int[] mTransparentLocation = new int[2];
20504
20505        /**
20506         * Global to the view hierarchy used as a temporary for dealing with
20507         * x/y points in the ViewGroup.invalidateChild implementation.
20508         */
20509        final int[] mInvalidateChildLocation = new int[2];
20510
20511        /**
20512         * Global to the view hierarchy used as a temporary for dealng with
20513         * computing absolute on-screen location.
20514         */
20515        final int[] mTmpLocation = new int[2];
20516
20517        /**
20518         * Global to the view hierarchy used as a temporary for dealing with
20519         * x/y location when view is transformed.
20520         */
20521        final float[] mTmpTransformLocation = new float[2];
20522
20523        /**
20524         * The view tree observer used to dispatch global events like
20525         * layout, pre-draw, touch mode change, etc.
20526         */
20527        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
20528
20529        /**
20530         * A Canvas used by the view hierarchy to perform bitmap caching.
20531         */
20532        Canvas mCanvas;
20533
20534        /**
20535         * The view root impl.
20536         */
20537        final ViewRootImpl mViewRootImpl;
20538
20539        /**
20540         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
20541         * handler can be used to pump events in the UI events queue.
20542         */
20543        final Handler mHandler;
20544
20545        /**
20546         * Temporary for use in computing invalidate rectangles while
20547         * calling up the hierarchy.
20548         */
20549        final Rect mTmpInvalRect = new Rect();
20550
20551        /**
20552         * Temporary for use in computing hit areas with transformed views
20553         */
20554        final RectF mTmpTransformRect = new RectF();
20555
20556        /**
20557         * Temporary for use in computing hit areas with transformed views
20558         */
20559        final RectF mTmpTransformRect1 = new RectF();
20560
20561        /**
20562         * Temporary list of rectanges.
20563         */
20564        final List<RectF> mTmpRectList = new ArrayList<>();
20565
20566        /**
20567         * Temporary for use in transforming invalidation rect
20568         */
20569        final Matrix mTmpMatrix = new Matrix();
20570
20571        /**
20572         * Temporary for use in transforming invalidation rect
20573         */
20574        final Transformation mTmpTransformation = new Transformation();
20575
20576        /**
20577         * Temporary for use in querying outlines from OutlineProviders
20578         */
20579        final Outline mTmpOutline = new Outline();
20580
20581        /**
20582         * Temporary list for use in collecting focusable descendents of a view.
20583         */
20584        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
20585
20586        /**
20587         * The id of the window for accessibility purposes.
20588         */
20589        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
20590
20591        /**
20592         * Flags related to accessibility processing.
20593         *
20594         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
20595         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
20596         */
20597        int mAccessibilityFetchFlags;
20598
20599        /**
20600         * The drawable for highlighting accessibility focus.
20601         */
20602        Drawable mAccessibilityFocusDrawable;
20603
20604        /**
20605         * Show where the margins, bounds and layout bounds are for each view.
20606         */
20607        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
20608
20609        /**
20610         * Point used to compute visible regions.
20611         */
20612        final Point mPoint = new Point();
20613
20614        /**
20615         * Used to track which View originated a requestLayout() call, used when
20616         * requestLayout() is called during layout.
20617         */
20618        View mViewRequestingLayout;
20619
20620        /**
20621         * Creates a new set of attachment information with the specified
20622         * events handler and thread.
20623         *
20624         * @param handler the events handler the view must use
20625         */
20626        AttachInfo(IWindowSession session, IWindow window, Display display,
20627                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
20628            mSession = session;
20629            mWindow = window;
20630            mWindowToken = window.asBinder();
20631            mDisplay = display;
20632            mViewRootImpl = viewRootImpl;
20633            mHandler = handler;
20634            mRootCallbacks = effectPlayer;
20635        }
20636    }
20637
20638    /**
20639     * <p>ScrollabilityCache holds various fields used by a View when scrolling
20640     * is supported. This avoids keeping too many unused fields in most
20641     * instances of View.</p>
20642     */
20643    private static class ScrollabilityCache implements Runnable {
20644
20645        /**
20646         * Scrollbars are not visible
20647         */
20648        public static final int OFF = 0;
20649
20650        /**
20651         * Scrollbars are visible
20652         */
20653        public static final int ON = 1;
20654
20655        /**
20656         * Scrollbars are fading away
20657         */
20658        public static final int FADING = 2;
20659
20660        public boolean fadeScrollBars;
20661
20662        public int fadingEdgeLength;
20663        public int scrollBarDefaultDelayBeforeFade;
20664        public int scrollBarFadeDuration;
20665
20666        public int scrollBarSize;
20667        public ScrollBarDrawable scrollBar;
20668        public float[] interpolatorValues;
20669        public View host;
20670
20671        public final Paint paint;
20672        public final Matrix matrix;
20673        public Shader shader;
20674
20675        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
20676
20677        private static final float[] OPAQUE = { 255 };
20678        private static final float[] TRANSPARENT = { 0.0f };
20679
20680        /**
20681         * When fading should start. This time moves into the future every time
20682         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
20683         */
20684        public long fadeStartTime;
20685
20686
20687        /**
20688         * The current state of the scrollbars: ON, OFF, or FADING
20689         */
20690        public int state = OFF;
20691
20692        private int mLastColor;
20693
20694        public ScrollabilityCache(ViewConfiguration configuration, View host) {
20695            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
20696            scrollBarSize = configuration.getScaledScrollBarSize();
20697            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
20698            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
20699
20700            paint = new Paint();
20701            matrix = new Matrix();
20702            // use use a height of 1, and then wack the matrix each time we
20703            // actually use it.
20704            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20705            paint.setShader(shader);
20706            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20707
20708            this.host = host;
20709        }
20710
20711        public void setFadeColor(int color) {
20712            if (color != mLastColor) {
20713                mLastColor = color;
20714
20715                if (color != 0) {
20716                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
20717                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
20718                    paint.setShader(shader);
20719                    // Restore the default transfer mode (src_over)
20720                    paint.setXfermode(null);
20721                } else {
20722                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20723                    paint.setShader(shader);
20724                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20725                }
20726            }
20727        }
20728
20729        public void run() {
20730            long now = AnimationUtils.currentAnimationTimeMillis();
20731            if (now >= fadeStartTime) {
20732
20733                // the animation fades the scrollbars out by changing
20734                // the opacity (alpha) from fully opaque to fully
20735                // transparent
20736                int nextFrame = (int) now;
20737                int framesCount = 0;
20738
20739                Interpolator interpolator = scrollBarInterpolator;
20740
20741                // Start opaque
20742                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
20743
20744                // End transparent
20745                nextFrame += scrollBarFadeDuration;
20746                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
20747
20748                state = FADING;
20749
20750                // Kick off the fade animation
20751                host.invalidate(true);
20752            }
20753        }
20754    }
20755
20756    /**
20757     * Resuable callback for sending
20758     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
20759     */
20760    private class SendViewScrolledAccessibilityEvent implements Runnable {
20761        public volatile boolean mIsPending;
20762
20763        public void run() {
20764            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20765            mIsPending = false;
20766        }
20767    }
20768
20769    /**
20770     * <p>
20771     * This class represents a delegate that can be registered in a {@link View}
20772     * to enhance accessibility support via composition rather via inheritance.
20773     * It is specifically targeted to widget developers that extend basic View
20774     * classes i.e. classes in package android.view, that would like their
20775     * applications to be backwards compatible.
20776     * </p>
20777     * <div class="special reference">
20778     * <h3>Developer Guides</h3>
20779     * <p>For more information about making applications accessible, read the
20780     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
20781     * developer guide.</p>
20782     * </div>
20783     * <p>
20784     * A scenario in which a developer would like to use an accessibility delegate
20785     * is overriding a method introduced in a later API version then the minimal API
20786     * version supported by the application. For example, the method
20787     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
20788     * in API version 4 when the accessibility APIs were first introduced. If a
20789     * developer would like his application to run on API version 4 devices (assuming
20790     * all other APIs used by the application are version 4 or lower) and take advantage
20791     * of this method, instead of overriding the method which would break the application's
20792     * backwards compatibility, he can override the corresponding method in this
20793     * delegate and register the delegate in the target View if the API version of
20794     * the system is high enough i.e. the API version is same or higher to the API
20795     * version that introduced
20796     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
20797     * </p>
20798     * <p>
20799     * Here is an example implementation:
20800     * </p>
20801     * <code><pre><p>
20802     * if (Build.VERSION.SDK_INT >= 14) {
20803     *     // If the API version is equal of higher than the version in
20804     *     // which onInitializeAccessibilityNodeInfo was introduced we
20805     *     // register a delegate with a customized implementation.
20806     *     View view = findViewById(R.id.view_id);
20807     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
20808     *         public void onInitializeAccessibilityNodeInfo(View host,
20809     *                 AccessibilityNodeInfo info) {
20810     *             // Let the default implementation populate the info.
20811     *             super.onInitializeAccessibilityNodeInfo(host, info);
20812     *             // Set some other information.
20813     *             info.setEnabled(host.isEnabled());
20814     *         }
20815     *     });
20816     * }
20817     * </code></pre></p>
20818     * <p>
20819     * This delegate contains methods that correspond to the accessibility methods
20820     * in View. If a delegate has been specified the implementation in View hands
20821     * off handling to the corresponding method in this delegate. The default
20822     * implementation the delegate methods behaves exactly as the corresponding
20823     * method in View for the case of no accessibility delegate been set. Hence,
20824     * to customize the behavior of a View method, clients can override only the
20825     * corresponding delegate method without altering the behavior of the rest
20826     * accessibility related methods of the host view.
20827     * </p>
20828     */
20829    public static class AccessibilityDelegate {
20830
20831        /**
20832         * Sends an accessibility event of the given type. If accessibility is not
20833         * enabled this method has no effect.
20834         * <p>
20835         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
20836         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
20837         * been set.
20838         * </p>
20839         *
20840         * @param host The View hosting the delegate.
20841         * @param eventType The type of the event to send.
20842         *
20843         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
20844         */
20845        public void sendAccessibilityEvent(View host, int eventType) {
20846            host.sendAccessibilityEventInternal(eventType);
20847        }
20848
20849        /**
20850         * Performs the specified accessibility action on the view. For
20851         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
20852         * <p>
20853         * The default implementation behaves as
20854         * {@link View#performAccessibilityAction(int, Bundle)
20855         *  View#performAccessibilityAction(int, Bundle)} for the case of
20856         *  no accessibility delegate been set.
20857         * </p>
20858         *
20859         * @param action The action to perform.
20860         * @return Whether the action was performed.
20861         *
20862         * @see View#performAccessibilityAction(int, Bundle)
20863         *      View#performAccessibilityAction(int, Bundle)
20864         */
20865        public boolean performAccessibilityAction(View host, int action, Bundle args) {
20866            return host.performAccessibilityActionInternal(action, args);
20867        }
20868
20869        /**
20870         * Sends an accessibility event. This method behaves exactly as
20871         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
20872         * empty {@link AccessibilityEvent} and does not perform a check whether
20873         * accessibility is enabled.
20874         * <p>
20875         * The default implementation behaves as
20876         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20877         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
20878         * the case of no accessibility delegate been set.
20879         * </p>
20880         *
20881         * @param host The View hosting the delegate.
20882         * @param event The event to send.
20883         *
20884         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20885         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20886         */
20887        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
20888            host.sendAccessibilityEventUncheckedInternal(event);
20889        }
20890
20891        /**
20892         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20893         * to its children for adding their text content to the event.
20894         * <p>
20895         * The default implementation behaves as
20896         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20897         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20898         * the case of no accessibility delegate been set.
20899         * </p>
20900         *
20901         * @param host The View hosting the delegate.
20902         * @param event The event.
20903         * @return True if the event population was completed.
20904         *
20905         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20906         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20907         */
20908        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20909            return host.dispatchPopulateAccessibilityEventInternal(event);
20910        }
20911
20912        /**
20913         * Gives a chance to the host View to populate the accessibility event with its
20914         * text content.
20915         * <p>
20916         * The default implementation behaves as
20917         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20918         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20919         * the case of no accessibility delegate been set.
20920         * </p>
20921         *
20922         * @param host The View hosting the delegate.
20923         * @param event The accessibility event which to populate.
20924         *
20925         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20926         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
20927         */
20928        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20929            host.onPopulateAccessibilityEventInternal(event);
20930        }
20931
20932        /**
20933         * Initializes an {@link AccessibilityEvent} with information about the
20934         * the host View which is the event source.
20935         * <p>
20936         * The default implementation behaves as
20937         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20938         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20939         * the case of no accessibility delegate been set.
20940         * </p>
20941         *
20942         * @param host The View hosting the delegate.
20943         * @param event The event to initialize.
20944         *
20945         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20946         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
20947         */
20948        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20949            host.onInitializeAccessibilityEventInternal(event);
20950        }
20951
20952        /**
20953         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20954         * <p>
20955         * The default implementation behaves as
20956         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20957         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20958         * the case of no accessibility delegate been set.
20959         * </p>
20960         *
20961         * @param host The View hosting the delegate.
20962         * @param info The instance to initialize.
20963         *
20964         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20965         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20966         */
20967        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20968            host.onInitializeAccessibilityNodeInfoInternal(info);
20969        }
20970
20971        /**
20972         * Called when a child of the host View has requested sending an
20973         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20974         * to augment the event.
20975         * <p>
20976         * The default implementation behaves as
20977         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20978         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20979         * the case of no accessibility delegate been set.
20980         * </p>
20981         *
20982         * @param host The View hosting the delegate.
20983         * @param child The child which requests sending the event.
20984         * @param event The event to be sent.
20985         * @return True if the event should be sent
20986         *
20987         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20988         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20989         */
20990        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20991                AccessibilityEvent event) {
20992            return host.onRequestSendAccessibilityEventInternal(child, event);
20993        }
20994
20995        /**
20996         * Gets the provider for managing a virtual view hierarchy rooted at this View
20997         * and reported to {@link android.accessibilityservice.AccessibilityService}s
20998         * that explore the window content.
20999         * <p>
21000         * The default implementation behaves as
21001         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
21002         * the case of no accessibility delegate been set.
21003         * </p>
21004         *
21005         * @return The provider.
21006         *
21007         * @see AccessibilityNodeProvider
21008         */
21009        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
21010            return null;
21011        }
21012
21013        /**
21014         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
21015         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
21016         * This method is responsible for obtaining an accessibility node info from a
21017         * pool of reusable instances and calling
21018         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
21019         * view to initialize the former.
21020         * <p>
21021         * <strong>Note:</strong> The client is responsible for recycling the obtained
21022         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
21023         * creation.
21024         * </p>
21025         * <p>
21026         * The default implementation behaves as
21027         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
21028         * the case of no accessibility delegate been set.
21029         * </p>
21030         * @return A populated {@link AccessibilityNodeInfo}.
21031         *
21032         * @see AccessibilityNodeInfo
21033         *
21034         * @hide
21035         */
21036        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
21037            return host.createAccessibilityNodeInfoInternal();
21038        }
21039    }
21040
21041    private class MatchIdPredicate implements Predicate<View> {
21042        public int mId;
21043
21044        @Override
21045        public boolean apply(View view) {
21046            return (view.mID == mId);
21047        }
21048    }
21049
21050    private class MatchLabelForPredicate implements Predicate<View> {
21051        private int mLabeledId;
21052
21053        @Override
21054        public boolean apply(View view) {
21055            return (view.mLabelForId == mLabeledId);
21056        }
21057    }
21058
21059    private class SendViewStateChangedAccessibilityEvent implements Runnable {
21060        private int mChangeTypes = 0;
21061        private boolean mPosted;
21062        private boolean mPostedWithDelay;
21063        private long mLastEventTimeMillis;
21064
21065        @Override
21066        public void run() {
21067            mPosted = false;
21068            mPostedWithDelay = false;
21069            mLastEventTimeMillis = SystemClock.uptimeMillis();
21070            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21071                final AccessibilityEvent event = AccessibilityEvent.obtain();
21072                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
21073                event.setContentChangeTypes(mChangeTypes);
21074                sendAccessibilityEventUnchecked(event);
21075            }
21076            mChangeTypes = 0;
21077        }
21078
21079        public void runOrPost(int changeType) {
21080            mChangeTypes |= changeType;
21081
21082            // If this is a live region or the child of a live region, collect
21083            // all events from this frame and send them on the next frame.
21084            if (inLiveRegion()) {
21085                // If we're already posted with a delay, remove that.
21086                if (mPostedWithDelay) {
21087                    removeCallbacks(this);
21088                    mPostedWithDelay = false;
21089                }
21090                // Only post if we're not already posted.
21091                if (!mPosted) {
21092                    post(this);
21093                    mPosted = true;
21094                }
21095                return;
21096            }
21097
21098            if (mPosted) {
21099                return;
21100            }
21101
21102            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
21103            final long minEventIntevalMillis =
21104                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
21105            if (timeSinceLastMillis >= minEventIntevalMillis) {
21106                removeCallbacks(this);
21107                run();
21108            } else {
21109                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
21110                mPostedWithDelay = true;
21111            }
21112        }
21113    }
21114
21115    private boolean inLiveRegion() {
21116        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21117            return true;
21118        }
21119
21120        ViewParent parent = getParent();
21121        while (parent instanceof View) {
21122            if (((View) parent).getAccessibilityLiveRegion()
21123                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21124                return true;
21125            }
21126            parent = parent.getParent();
21127        }
21128
21129        return false;
21130    }
21131
21132    /**
21133     * Dump all private flags in readable format, useful for documentation and
21134     * sanity checking.
21135     */
21136    private static void dumpFlags() {
21137        final HashMap<String, String> found = Maps.newHashMap();
21138        try {
21139            for (Field field : View.class.getDeclaredFields()) {
21140                final int modifiers = field.getModifiers();
21141                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
21142                    if (field.getType().equals(int.class)) {
21143                        final int value = field.getInt(null);
21144                        dumpFlag(found, field.getName(), value);
21145                    } else if (field.getType().equals(int[].class)) {
21146                        final int[] values = (int[]) field.get(null);
21147                        for (int i = 0; i < values.length; i++) {
21148                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
21149                        }
21150                    }
21151                }
21152            }
21153        } catch (IllegalAccessException e) {
21154            throw new RuntimeException(e);
21155        }
21156
21157        final ArrayList<String> keys = Lists.newArrayList();
21158        keys.addAll(found.keySet());
21159        Collections.sort(keys);
21160        for (String key : keys) {
21161            Log.d(VIEW_LOG_TAG, found.get(key));
21162        }
21163    }
21164
21165    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21166        // Sort flags by prefix, then by bits, always keeping unique keys
21167        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21168        final int prefix = name.indexOf('_');
21169        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21170        final String output = bits + " " + name;
21171        found.put(key, output);
21172    }
21173}
21174