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.IntDef;
22import android.annotation.NonNull;
23import android.annotation.Nullable;
24import android.content.ClipData;
25import android.content.Context;
26import android.content.res.ColorStateList;
27import android.content.res.Configuration;
28import android.content.res.Resources;
29import android.content.res.TypedArray;
30import android.graphics.Bitmap;
31import android.graphics.Canvas;
32import android.graphics.Insets;
33import android.graphics.Interpolator;
34import android.graphics.LinearGradient;
35import android.graphics.Matrix;
36import android.graphics.Outline;
37import android.graphics.Paint;
38import android.graphics.Path;
39import android.graphics.PathMeasure;
40import android.graphics.PixelFormat;
41import android.graphics.Point;
42import android.graphics.PorterDuff;
43import android.graphics.PorterDuffXfermode;
44import android.graphics.Rect;
45import android.graphics.RectF;
46import android.graphics.Region;
47import android.graphics.Shader;
48import android.graphics.drawable.ColorDrawable;
49import android.graphics.drawable.Drawable;
50import android.hardware.display.DisplayManagerGlobal;
51import android.os.Bundle;
52import android.os.Handler;
53import android.os.IBinder;
54import android.os.Parcel;
55import android.os.Parcelable;
56import android.os.RemoteException;
57import android.os.SystemClock;
58import android.os.SystemProperties;
59import android.os.Trace;
60import android.text.TextUtils;
61import android.util.AttributeSet;
62import android.util.FloatProperty;
63import android.util.LayoutDirection;
64import android.util.Log;
65import android.util.LongSparseLongArray;
66import android.util.Pools.SynchronizedPool;
67import android.util.Property;
68import android.util.SparseArray;
69import android.util.SuperNotCalledException;
70import android.util.TypedValue;
71import android.view.ContextMenu.ContextMenuInfo;
72import android.view.AccessibilityIterators.TextSegmentIterator;
73import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
74import android.view.AccessibilityIterators.WordTextSegmentIterator;
75import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
76import android.view.accessibility.AccessibilityEvent;
77import android.view.accessibility.AccessibilityEventSource;
78import android.view.accessibility.AccessibilityManager;
79import android.view.accessibility.AccessibilityNodeInfo;
80import android.view.accessibility.AccessibilityNodeProvider;
81import android.view.animation.Animation;
82import android.view.animation.AnimationUtils;
83import android.view.animation.Transformation;
84import android.view.inputmethod.EditorInfo;
85import android.view.inputmethod.InputConnection;
86import android.view.inputmethod.InputMethodManager;
87import android.widget.ScrollBarDrawable;
88
89import static android.os.Build.VERSION_CODES.*;
90import static java.lang.Math.max;
91
92import com.android.internal.R;
93import com.android.internal.util.Predicate;
94import com.android.internal.view.menu.MenuBuilder;
95import com.google.android.collect.Lists;
96import com.google.android.collect.Maps;
97
98import java.lang.annotation.Retention;
99import java.lang.annotation.RetentionPolicy;
100import java.lang.ref.WeakReference;
101import java.lang.reflect.Field;
102import java.lang.reflect.InvocationTargetException;
103import java.lang.reflect.Method;
104import java.lang.reflect.Modifier;
105import java.util.ArrayList;
106import java.util.Arrays;
107import java.util.Collections;
108import java.util.HashMap;
109import java.util.List;
110import java.util.Locale;
111import java.util.Map;
112import java.util.concurrent.CopyOnWriteArrayList;
113import java.util.concurrent.atomic.AtomicInteger;
114
115/**
116 * <p>
117 * This class represents the basic building block for user interface components. A View
118 * occupies a rectangular area on the screen and is responsible for drawing and
119 * event handling. View is the base class for <em>widgets</em>, which are
120 * used to create interactive UI components (buttons, text fields, etc.). The
121 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
122 * are invisible containers that hold other Views (or other ViewGroups) and define
123 * their layout properties.
124 * </p>
125 *
126 * <div class="special reference">
127 * <h3>Developer Guides</h3>
128 * <p>For information about using this class to develop your application's user interface,
129 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
130 * </div>
131 *
132 * <a name="Using"></a>
133 * <h3>Using Views</h3>
134 * <p>
135 * All of the views in a window are arranged in a single tree. You can add views
136 * either from code or by specifying a tree of views in one or more XML layout
137 * files. There are many specialized subclasses of views that act as controls or
138 * are capable of displaying text, images, or other content.
139 * </p>
140 * <p>
141 * Once you have created a tree of views, there are typically a few types of
142 * common operations you may wish to perform:
143 * <ul>
144 * <li><strong>Set properties:</strong> for example setting the text of a
145 * {@link android.widget.TextView}. The available properties and the methods
146 * that set them will vary among the different subclasses of views. Note that
147 * properties that are known at build time can be set in the XML layout
148 * files.</li>
149 * <li><strong>Set focus:</strong> The framework will handled moving focus in
150 * response to user input. To force focus to a specific view, call
151 * {@link #requestFocus}.</li>
152 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
153 * that will be notified when something interesting happens to the view. For
154 * example, all views will let you set a listener to be notified when the view
155 * gains or loses focus. You can register such a listener using
156 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
157 * Other view subclasses offer more specialized listeners. For example, a Button
158 * exposes a listener to notify clients when the button is clicked.</li>
159 * <li><strong>Set visibility:</strong> You can hide or show views using
160 * {@link #setVisibility(int)}.</li>
161 * </ul>
162 * </p>
163 * <p><em>
164 * Note: The Android framework is responsible for measuring, laying out and
165 * drawing views. You should not call methods that perform these actions on
166 * views yourself unless you are actually implementing a
167 * {@link android.view.ViewGroup}.
168 * </em></p>
169 *
170 * <a name="Lifecycle"></a>
171 * <h3>Implementing a Custom View</h3>
172 *
173 * <p>
174 * To implement a custom view, you will usually begin by providing overrides for
175 * some of the standard methods that the framework calls on all views. You do
176 * not need to override all of these methods. In fact, you can start by just
177 * overriding {@link #onDraw(android.graphics.Canvas)}.
178 * <table border="2" width="85%" align="center" cellpadding="5">
179 *     <thead>
180 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
181 *     </thead>
182 *
183 *     <tbody>
184 *     <tr>
185 *         <td rowspan="2">Creation</td>
186 *         <td>Constructors</td>
187 *         <td>There is a form of the constructor that are called when the view
188 *         is created from code and a form that is called when the view is
189 *         inflated from a layout file. The second form should parse and apply
190 *         any attributes defined in the layout file.
191 *         </td>
192 *     </tr>
193 *     <tr>
194 *         <td><code>{@link #onFinishInflate()}</code></td>
195 *         <td>Called after a view and all of its children has been inflated
196 *         from XML.</td>
197 *     </tr>
198 *
199 *     <tr>
200 *         <td rowspan="3">Layout</td>
201 *         <td><code>{@link #onMeasure(int, int)}</code></td>
202 *         <td>Called to determine the size requirements for this view and all
203 *         of its children.
204 *         </td>
205 *     </tr>
206 *     <tr>
207 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
208 *         <td>Called when this view should assign a size and position to all
209 *         of its children.
210 *         </td>
211 *     </tr>
212 *     <tr>
213 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
214 *         <td>Called when the size of this view has changed.
215 *         </td>
216 *     </tr>
217 *
218 *     <tr>
219 *         <td>Drawing</td>
220 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
221 *         <td>Called when the view should render its content.
222 *         </td>
223 *     </tr>
224 *
225 *     <tr>
226 *         <td rowspan="4">Event processing</td>
227 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
228 *         <td>Called when a new hardware key event occurs.
229 *         </td>
230 *     </tr>
231 *     <tr>
232 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
233 *         <td>Called when a hardware key up event occurs.
234 *         </td>
235 *     </tr>
236 *     <tr>
237 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
238 *         <td>Called when a trackball motion event occurs.
239 *         </td>
240 *     </tr>
241 *     <tr>
242 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
243 *         <td>Called when a touch screen motion event occurs.
244 *         </td>
245 *     </tr>
246 *
247 *     <tr>
248 *         <td rowspan="2">Focus</td>
249 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
250 *         <td>Called when the view gains or loses focus.
251 *         </td>
252 *     </tr>
253 *
254 *     <tr>
255 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
256 *         <td>Called when the window containing the view gains or loses focus.
257 *         </td>
258 *     </tr>
259 *
260 *     <tr>
261 *         <td rowspan="3">Attaching</td>
262 *         <td><code>{@link #onAttachedToWindow()}</code></td>
263 *         <td>Called when the view is attached to a window.
264 *         </td>
265 *     </tr>
266 *
267 *     <tr>
268 *         <td><code>{@link #onDetachedFromWindow}</code></td>
269 *         <td>Called when the view is detached from its window.
270 *         </td>
271 *     </tr>
272 *
273 *     <tr>
274 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
275 *         <td>Called when the visibility of the window containing the view
276 *         has changed.
277 *         </td>
278 *     </tr>
279 *     </tbody>
280 *
281 * </table>
282 * </p>
283 *
284 * <a name="IDs"></a>
285 * <h3>IDs</h3>
286 * Views may have an integer id associated with them. These ids are typically
287 * assigned in the layout XML files, and are used to find specific views within
288 * the view tree. A common pattern is to:
289 * <ul>
290 * <li>Define a Button in the layout file and assign it a unique ID.
291 * <pre>
292 * &lt;Button
293 *     android:id="@+id/my_button"
294 *     android:layout_width="wrap_content"
295 *     android:layout_height="wrap_content"
296 *     android:text="@string/my_button_text"/&gt;
297 * </pre></li>
298 * <li>From the onCreate method of an Activity, find the Button
299 * <pre class="prettyprint">
300 *      Button myButton = (Button) findViewById(R.id.my_button);
301 * </pre></li>
302 * </ul>
303 * <p>
304 * View IDs need not be unique throughout the tree, but it is good practice to
305 * ensure that they are at least unique within the part of the tree you are
306 * searching.
307 * </p>
308 *
309 * <a name="Position"></a>
310 * <h3>Position</h3>
311 * <p>
312 * The geometry of a view is that of a rectangle. A view has a location,
313 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
314 * two dimensions, expressed as a width and a height. The unit for location
315 * and dimensions is the pixel.
316 * </p>
317 *
318 * <p>
319 * It is possible to retrieve the location of a view by invoking the methods
320 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
321 * coordinate of the rectangle representing the view. The latter returns the
322 * top, or Y, coordinate of the rectangle representing the view. These methods
323 * both return the location of the view relative to its parent. For instance,
324 * when getLeft() returns 20, that means the view is located 20 pixels to the
325 * right of the left edge of its direct parent.
326 * </p>
327 *
328 * <p>
329 * In addition, several convenience methods are offered to avoid unnecessary
330 * computations, namely {@link #getRight()} and {@link #getBottom()}.
331 * These methods return the coordinates of the right and bottom edges of the
332 * rectangle representing the view. For instance, calling {@link #getRight()}
333 * is similar to the following computation: <code>getLeft() + getWidth()</code>
334 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
335 * </p>
336 *
337 * <a name="SizePaddingMargins"></a>
338 * <h3>Size, padding and margins</h3>
339 * <p>
340 * The size of a view is expressed with a width and a height. A view actually
341 * possess two pairs of width and height values.
342 * </p>
343 *
344 * <p>
345 * The first pair is known as <em>measured width</em> and
346 * <em>measured height</em>. These dimensions define how big a view wants to be
347 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
348 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
349 * and {@link #getMeasuredHeight()}.
350 * </p>
351 *
352 * <p>
353 * The second pair is simply known as <em>width</em> and <em>height</em>, or
354 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
355 * dimensions define the actual size of the view on screen, at drawing time and
356 * after layout. These values may, but do not have to, be different from the
357 * measured width and height. The width and height can be obtained by calling
358 * {@link #getWidth()} and {@link #getHeight()}.
359 * </p>
360 *
361 * <p>
362 * To measure its dimensions, a view takes into account its padding. The padding
363 * is expressed in pixels for the left, top, right and bottom parts of the view.
364 * Padding can be used to offset the content of the view by a specific amount of
365 * pixels. For instance, a left padding of 2 will push the view's content by
366 * 2 pixels to the right of the left edge. Padding can be set using the
367 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
368 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
369 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
370 * {@link #getPaddingEnd()}.
371 * </p>
372 *
373 * <p>
374 * Even though a view can define a padding, it does not provide any support for
375 * margins. However, view groups provide such a support. Refer to
376 * {@link android.view.ViewGroup} and
377 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
378 * </p>
379 *
380 * <a name="Layout"></a>
381 * <h3>Layout</h3>
382 * <p>
383 * Layout is a two pass process: a measure pass and a layout pass. The measuring
384 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
385 * of the view tree. Each view pushes dimension specifications down the tree
386 * during the recursion. At the end of the measure pass, every view has stored
387 * its measurements. The second pass happens in
388 * {@link #layout(int,int,int,int)} and is also top-down. During
389 * this pass each parent is responsible for positioning all of its children
390 * using the sizes computed in the measure pass.
391 * </p>
392 *
393 * <p>
394 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
395 * {@link #getMeasuredHeight()} values must be set, along with those for all of
396 * that view's descendants. A view's measured width and measured height values
397 * must respect the constraints imposed by the view's parents. This guarantees
398 * that at the end of the measure pass, all parents accept all of their
399 * children's measurements. A parent view may call measure() more than once on
400 * its children. For example, the parent may measure each child once with
401 * unspecified dimensions to find out how big they want to be, then call
402 * measure() on them again with actual numbers if the sum of all the children's
403 * unconstrained sizes is too big or too small.
404 * </p>
405 *
406 * <p>
407 * The measure pass uses two classes to communicate dimensions. The
408 * {@link MeasureSpec} class is used by views to tell their parents how they
409 * want to be measured and positioned. The base LayoutParams class just
410 * describes how big the view wants to be for both width and height. For each
411 * dimension, it can specify one of:
412 * <ul>
413 * <li> an exact number
414 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
415 * (minus padding)
416 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
417 * enclose its content (plus padding).
418 * </ul>
419 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
420 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
421 * an X and Y value.
422 * </p>
423 *
424 * <p>
425 * MeasureSpecs are used to push requirements down the tree from parent to
426 * child. A MeasureSpec can be in one of three modes:
427 * <ul>
428 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
429 * of a child view. For example, a LinearLayout may call measure() on its child
430 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
431 * tall the child view wants to be given a width of 240 pixels.
432 * <li>EXACTLY: This is used by the parent to impose an exact size on the
433 * child. The child must use this size, and guarantee that all of its
434 * descendants will fit within this size.
435 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
436 * child. The child must guarantee that it and all of its descendants will fit
437 * within this size.
438 * </ul>
439 * </p>
440 *
441 * <p>
442 * To intiate a layout, call {@link #requestLayout}. This method is typically
443 * called by a view on itself when it believes that is can no longer fit within
444 * its current bounds.
445 * </p>
446 *
447 * <a name="Drawing"></a>
448 * <h3>Drawing</h3>
449 * <p>
450 * Drawing is handled by walking the tree and recording the drawing commands of
451 * any View that needs to update. After this, the drawing commands of the
452 * entire tree are issued to screen, clipped to the newly damaged area.
453 * </p>
454 *
455 * <p>
456 * The tree is largely recorded and drawn in order, with parents drawn before
457 * (i.e., behind) their children, with siblings drawn in the order they appear
458 * in the tree. If you set a background drawable for a View, then the View will
459 * draw it before calling back to its <code>onDraw()</code> method. The child
460 * drawing order can be overridden with
461 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
462 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
463 * </p>
464 *
465 * <p>
466 * To force a view to draw, call {@link #invalidate()}.
467 * </p>
468 *
469 * <a name="EventHandlingThreading"></a>
470 * <h3>Event Handling and Threading</h3>
471 * <p>
472 * The basic cycle of a view is as follows:
473 * <ol>
474 * <li>An event comes in and is dispatched to the appropriate view. The view
475 * handles the event and notifies any listeners.</li>
476 * <li>If in the course of processing the event, the view's bounds may need
477 * to be changed, the view will call {@link #requestLayout()}.</li>
478 * <li>Similarly, if in the course of processing the event the view's appearance
479 * may need to be changed, the view will call {@link #invalidate()}.</li>
480 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
481 * the framework will take care of measuring, laying out, and drawing the tree
482 * as appropriate.</li>
483 * </ol>
484 * </p>
485 *
486 * <p><em>Note: The entire view tree is single threaded. You must always be on
487 * the UI thread when calling any method on any view.</em>
488 * If you are doing work on other threads and want to update the state of a view
489 * from that thread, you should use a {@link Handler}.
490 * </p>
491 *
492 * <a name="FocusHandling"></a>
493 * <h3>Focus Handling</h3>
494 * <p>
495 * The framework will handle routine focus movement in response to user input.
496 * This includes changing the focus as views are removed or hidden, or as new
497 * views become available. Views indicate their willingness to take focus
498 * through the {@link #isFocusable} method. To change whether a view can take
499 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
500 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
501 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
502 * </p>
503 * <p>
504 * Focus movement is based on an algorithm which finds the nearest neighbor in a
505 * given direction. In rare cases, the default algorithm may not match the
506 * intended behavior of the developer. In these situations, you can provide
507 * explicit overrides by using these XML attributes in the layout file:
508 * <pre>
509 * nextFocusDown
510 * nextFocusLeft
511 * nextFocusRight
512 * nextFocusUp
513 * </pre>
514 * </p>
515 *
516 *
517 * <p>
518 * To get a particular view to take focus, call {@link #requestFocus()}.
519 * </p>
520 *
521 * <a name="TouchMode"></a>
522 * <h3>Touch Mode</h3>
523 * <p>
524 * When a user is navigating a user interface via directional keys such as a D-pad, it is
525 * necessary to give focus to actionable items such as buttons so the user can see
526 * what will take input.  If the device has touch capabilities, however, and the user
527 * begins interacting with the interface by touching it, it is no longer necessary to
528 * always highlight, or give focus to, a particular view.  This motivates a mode
529 * for interaction named 'touch mode'.
530 * </p>
531 * <p>
532 * For a touch capable device, once the user touches the screen, the device
533 * will enter touch mode.  From this point onward, only views for which
534 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
535 * Other views that are touchable, like buttons, will not take focus when touched; they will
536 * only fire the on click listeners.
537 * </p>
538 * <p>
539 * Any time a user hits a directional key, such as a D-pad direction, the view device will
540 * exit touch mode, and find a view to take focus, so that the user may resume interacting
541 * with the user interface without touching the screen again.
542 * </p>
543 * <p>
544 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
545 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
546 * </p>
547 *
548 * <a name="Scrolling"></a>
549 * <h3>Scrolling</h3>
550 * <p>
551 * The framework provides basic support for views that wish to internally
552 * scroll their content. This includes keeping track of the X and Y scroll
553 * offset as well as mechanisms for drawing scrollbars. See
554 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
555 * {@link #awakenScrollBars()} for more details.
556 * </p>
557 *
558 * <a name="Tags"></a>
559 * <h3>Tags</h3>
560 * <p>
561 * Unlike IDs, tags are not used to identify views. Tags are essentially an
562 * extra piece of information that can be associated with a view. They are most
563 * often used as a convenience to store data related to views in the views
564 * themselves rather than by putting them in a separate structure.
565 * </p>
566 *
567 * <a name="Properties"></a>
568 * <h3>Properties</h3>
569 * <p>
570 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
571 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
572 * available both in the {@link Property} form as well as in similarly-named setter/getter
573 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
574 * be used to set persistent state associated with these rendering-related properties on the view.
575 * The properties and methods can also be used in conjunction with
576 * {@link android.animation.Animator Animator}-based animations, described more in the
577 * <a href="#Animation">Animation</a> section.
578 * </p>
579 *
580 * <a name="Animation"></a>
581 * <h3>Animation</h3>
582 * <p>
583 * Starting with Android 3.0, the preferred way of animating views is to use the
584 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
585 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
586 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
587 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
588 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
589 * makes animating these View properties particularly easy and efficient.
590 * </p>
591 * <p>
592 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
593 * You can attach an {@link Animation} object to a view using
594 * {@link #setAnimation(Animation)} or
595 * {@link #startAnimation(Animation)}. The animation can alter the scale,
596 * rotation, translation and alpha of a view over time. If the animation is
597 * attached to a view that has children, the animation will affect the entire
598 * subtree rooted by that node. When an animation is started, the framework will
599 * take care of redrawing the appropriate views until the animation completes.
600 * </p>
601 *
602 * <a name="Security"></a>
603 * <h3>Security</h3>
604 * <p>
605 * Sometimes it is essential that an application be able to verify that an action
606 * is being performed with the full knowledge and consent of the user, such as
607 * granting a permission request, making a purchase or clicking on an advertisement.
608 * Unfortunately, a malicious application could try to spoof the user into
609 * performing these actions, unaware, by concealing the intended purpose of the view.
610 * As a remedy, the framework offers a touch filtering mechanism that can be used to
611 * improve the security of views that provide access to sensitive functionality.
612 * </p><p>
613 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
614 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
615 * will discard touches that are received whenever the view's window is obscured by
616 * another visible window.  As a result, the view will not receive touches whenever a
617 * toast, dialog or other window appears above the view's window.
618 * </p><p>
619 * For more fine-grained control over security, consider overriding the
620 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
621 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
622 * </p>
623 *
624 * @attr ref android.R.styleable#View_alpha
625 * @attr ref android.R.styleable#View_background
626 * @attr ref android.R.styleable#View_clickable
627 * @attr ref android.R.styleable#View_contentDescription
628 * @attr ref android.R.styleable#View_drawingCacheQuality
629 * @attr ref android.R.styleable#View_duplicateParentState
630 * @attr ref android.R.styleable#View_id
631 * @attr ref android.R.styleable#View_requiresFadingEdge
632 * @attr ref android.R.styleable#View_fadeScrollbars
633 * @attr ref android.R.styleable#View_fadingEdgeLength
634 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
635 * @attr ref android.R.styleable#View_fitsSystemWindows
636 * @attr ref android.R.styleable#View_isScrollContainer
637 * @attr ref android.R.styleable#View_focusable
638 * @attr ref android.R.styleable#View_focusableInTouchMode
639 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
640 * @attr ref android.R.styleable#View_keepScreenOn
641 * @attr ref android.R.styleable#View_layerType
642 * @attr ref android.R.styleable#View_layoutDirection
643 * @attr ref android.R.styleable#View_longClickable
644 * @attr ref android.R.styleable#View_minHeight
645 * @attr ref android.R.styleable#View_minWidth
646 * @attr ref android.R.styleable#View_nextFocusDown
647 * @attr ref android.R.styleable#View_nextFocusLeft
648 * @attr ref android.R.styleable#View_nextFocusRight
649 * @attr ref android.R.styleable#View_nextFocusUp
650 * @attr ref android.R.styleable#View_onClick
651 * @attr ref android.R.styleable#View_padding
652 * @attr ref android.R.styleable#View_paddingBottom
653 * @attr ref android.R.styleable#View_paddingLeft
654 * @attr ref android.R.styleable#View_paddingRight
655 * @attr ref android.R.styleable#View_paddingTop
656 * @attr ref android.R.styleable#View_paddingStart
657 * @attr ref android.R.styleable#View_paddingEnd
658 * @attr ref android.R.styleable#View_saveEnabled
659 * @attr ref android.R.styleable#View_rotation
660 * @attr ref android.R.styleable#View_rotationX
661 * @attr ref android.R.styleable#View_rotationY
662 * @attr ref android.R.styleable#View_scaleX
663 * @attr ref android.R.styleable#View_scaleY
664 * @attr ref android.R.styleable#View_scrollX
665 * @attr ref android.R.styleable#View_scrollY
666 * @attr ref android.R.styleable#View_scrollbarSize
667 * @attr ref android.R.styleable#View_scrollbarStyle
668 * @attr ref android.R.styleable#View_scrollbars
669 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
670 * @attr ref android.R.styleable#View_scrollbarFadeDuration
671 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
672 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
673 * @attr ref android.R.styleable#View_scrollbarThumbVertical
674 * @attr ref android.R.styleable#View_scrollbarTrackVertical
675 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
676 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
677 * @attr ref android.R.styleable#View_stateListAnimator
678 * @attr ref android.R.styleable#View_transitionName
679 * @attr ref android.R.styleable#View_soundEffectsEnabled
680 * @attr ref android.R.styleable#View_tag
681 * @attr ref android.R.styleable#View_textAlignment
682 * @attr ref android.R.styleable#View_textDirection
683 * @attr ref android.R.styleable#View_transformPivotX
684 * @attr ref android.R.styleable#View_transformPivotY
685 * @attr ref android.R.styleable#View_translationX
686 * @attr ref android.R.styleable#View_translationY
687 * @attr ref android.R.styleable#View_translationZ
688 * @attr ref android.R.styleable#View_visibility
689 *
690 * @see android.view.ViewGroup
691 */
692public class View implements Drawable.Callback, KeyEvent.Callback,
693        AccessibilityEventSource {
694    private static final boolean DBG = false;
695
696    /**
697     * The logging tag used by this class with android.util.Log.
698     */
699    protected static final String VIEW_LOG_TAG = "View";
700
701    /**
702     * When set to true, apps will draw debugging information about their layouts.
703     *
704     * @hide
705     */
706    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
707
708    /**
709     * When set to true, this view will save its attribute data.
710     *
711     * @hide
712     */
713    public static boolean mDebugViewAttributes = false;
714
715    /**
716     * Used to mark a View that has no ID.
717     */
718    public static final int NO_ID = -1;
719
720    /**
721     * Signals that compatibility booleans have been initialized according to
722     * target SDK versions.
723     */
724    private static boolean sCompatibilityDone = false;
725
726    /**
727     * Use the old (broken) way of building MeasureSpecs.
728     */
729    private static boolean sUseBrokenMakeMeasureSpec = false;
730
731    /**
732     * Ignore any optimizations using the measure cache.
733     */
734    private static boolean sIgnoreMeasureCache = false;
735
736    /**
737     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
738     * calling setFlags.
739     */
740    private static final int NOT_FOCUSABLE = 0x00000000;
741
742    /**
743     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
744     * setFlags.
745     */
746    private static final int FOCUSABLE = 0x00000001;
747
748    /**
749     * Mask for use with setFlags indicating bits used for focus.
750     */
751    private static final int FOCUSABLE_MASK = 0x00000001;
752
753    /**
754     * This view will adjust its padding to fit sytem windows (e.g. status bar)
755     */
756    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
757
758    /** @hide */
759    @IntDef({VISIBLE, INVISIBLE, GONE})
760    @Retention(RetentionPolicy.SOURCE)
761    public @interface Visibility {}
762
763    /**
764     * This view is visible.
765     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
766     * android:visibility}.
767     */
768    public static final int VISIBLE = 0x00000000;
769
770    /**
771     * This view is invisible, but it still takes up space for layout purposes.
772     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
773     * android:visibility}.
774     */
775    public static final int INVISIBLE = 0x00000004;
776
777    /**
778     * This view is invisible, and it doesn't take any space for layout
779     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
780     * android:visibility}.
781     */
782    public static final int GONE = 0x00000008;
783
784    /**
785     * Mask for use with setFlags indicating bits used for visibility.
786     * {@hide}
787     */
788    static final int VISIBILITY_MASK = 0x0000000C;
789
790    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
791
792    /**
793     * This view is enabled. Interpretation varies by subclass.
794     * Use with ENABLED_MASK when calling setFlags.
795     * {@hide}
796     */
797    static final int ENABLED = 0x00000000;
798
799    /**
800     * This view is disabled. Interpretation varies by subclass.
801     * Use with ENABLED_MASK when calling setFlags.
802     * {@hide}
803     */
804    static final int DISABLED = 0x00000020;
805
806   /**
807    * Mask for use with setFlags indicating bits used for indicating whether
808    * this view is enabled
809    * {@hide}
810    */
811    static final int ENABLED_MASK = 0x00000020;
812
813    /**
814     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
815     * called and further optimizations will be performed. It is okay to have
816     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
817     * {@hide}
818     */
819    static final int WILL_NOT_DRAW = 0x00000080;
820
821    /**
822     * Mask for use with setFlags indicating bits used for indicating whether
823     * this view is will draw
824     * {@hide}
825     */
826    static final int DRAW_MASK = 0x00000080;
827
828    /**
829     * <p>This view doesn't show scrollbars.</p>
830     * {@hide}
831     */
832    static final int SCROLLBARS_NONE = 0x00000000;
833
834    /**
835     * <p>This view shows horizontal scrollbars.</p>
836     * {@hide}
837     */
838    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
839
840    /**
841     * <p>This view shows vertical scrollbars.</p>
842     * {@hide}
843     */
844    static final int SCROLLBARS_VERTICAL = 0x00000200;
845
846    /**
847     * <p>Mask for use with setFlags indicating bits used for indicating which
848     * scrollbars are enabled.</p>
849     * {@hide}
850     */
851    static final int SCROLLBARS_MASK = 0x00000300;
852
853    /**
854     * Indicates that the view should filter touches when its window is obscured.
855     * Refer to the class comments for more information about this security feature.
856     * {@hide}
857     */
858    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
859
860    /**
861     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
862     * that they are optional and should be skipped if the window has
863     * requested system UI flags that ignore those insets for layout.
864     */
865    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
866
867    /**
868     * <p>This view doesn't show fading edges.</p>
869     * {@hide}
870     */
871    static final int FADING_EDGE_NONE = 0x00000000;
872
873    /**
874     * <p>This view shows horizontal fading edges.</p>
875     * {@hide}
876     */
877    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
878
879    /**
880     * <p>This view shows vertical fading edges.</p>
881     * {@hide}
882     */
883    static final int FADING_EDGE_VERTICAL = 0x00002000;
884
885    /**
886     * <p>Mask for use with setFlags indicating bits used for indicating which
887     * fading edges are enabled.</p>
888     * {@hide}
889     */
890    static final int FADING_EDGE_MASK = 0x00003000;
891
892    /**
893     * <p>Indicates this view can be clicked. When clickable, a View reacts
894     * to clicks by notifying the OnClickListener.<p>
895     * {@hide}
896     */
897    static final int CLICKABLE = 0x00004000;
898
899    /**
900     * <p>Indicates this view is caching its drawing into a bitmap.</p>
901     * {@hide}
902     */
903    static final int DRAWING_CACHE_ENABLED = 0x00008000;
904
905    /**
906     * <p>Indicates that no icicle should be saved for this view.<p>
907     * {@hide}
908     */
909    static final int SAVE_DISABLED = 0x000010000;
910
911    /**
912     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
913     * property.</p>
914     * {@hide}
915     */
916    static final int SAVE_DISABLED_MASK = 0x000010000;
917
918    /**
919     * <p>Indicates that no drawing cache should ever be created for this view.<p>
920     * {@hide}
921     */
922    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
923
924    /**
925     * <p>Indicates this view can take / keep focus when int touch mode.</p>
926     * {@hide}
927     */
928    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
929
930    /** @hide */
931    @Retention(RetentionPolicy.SOURCE)
932    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
933    public @interface DrawingCacheQuality {}
934
935    /**
936     * <p>Enables low quality mode for the drawing cache.</p>
937     */
938    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
939
940    /**
941     * <p>Enables high quality mode for the drawing cache.</p>
942     */
943    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
944
945    /**
946     * <p>Enables automatic quality mode for the drawing cache.</p>
947     */
948    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
949
950    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
951            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
952    };
953
954    /**
955     * <p>Mask for use with setFlags indicating bits used for the cache
956     * quality property.</p>
957     * {@hide}
958     */
959    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
960
961    /**
962     * <p>
963     * Indicates this view can be long clicked. When long clickable, a View
964     * reacts to long clicks by notifying the OnLongClickListener or showing a
965     * context menu.
966     * </p>
967     * {@hide}
968     */
969    static final int LONG_CLICKABLE = 0x00200000;
970
971    /**
972     * <p>Indicates that this view gets its drawable states from its direct parent
973     * and ignores its original internal states.</p>
974     *
975     * @hide
976     */
977    static final int DUPLICATE_PARENT_STATE = 0x00400000;
978
979    /** @hide */
980    @IntDef({
981        SCROLLBARS_INSIDE_OVERLAY,
982        SCROLLBARS_INSIDE_INSET,
983        SCROLLBARS_OUTSIDE_OVERLAY,
984        SCROLLBARS_OUTSIDE_INSET
985    })
986    @Retention(RetentionPolicy.SOURCE)
987    public @interface ScrollBarStyle {}
988
989    /**
990     * The scrollbar style to display the scrollbars inside the content area,
991     * without increasing the padding. The scrollbars will be overlaid with
992     * translucency on the view's content.
993     */
994    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
995
996    /**
997     * The scrollbar style to display the scrollbars inside the padded area,
998     * increasing the padding of the view. The scrollbars will not overlap the
999     * content area of the view.
1000     */
1001    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1002
1003    /**
1004     * The scrollbar style to display the scrollbars at the edge of the view,
1005     * without increasing the padding. The scrollbars will be overlaid with
1006     * translucency.
1007     */
1008    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1009
1010    /**
1011     * The scrollbar style to display the scrollbars at the edge of the view,
1012     * increasing the padding of the view. The scrollbars will only overlap the
1013     * background, if any.
1014     */
1015    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1016
1017    /**
1018     * Mask to check if the scrollbar style is overlay or inset.
1019     * {@hide}
1020     */
1021    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1022
1023    /**
1024     * Mask to check if the scrollbar style is inside or outside.
1025     * {@hide}
1026     */
1027    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1028
1029    /**
1030     * Mask for scrollbar style.
1031     * {@hide}
1032     */
1033    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1034
1035    /**
1036     * View flag indicating that the screen should remain on while the
1037     * window containing this view is visible to the user.  This effectively
1038     * takes care of automatically setting the WindowManager's
1039     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1040     */
1041    public static final int KEEP_SCREEN_ON = 0x04000000;
1042
1043    /**
1044     * View flag indicating whether this view should have sound effects enabled
1045     * for events such as clicking and touching.
1046     */
1047    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1048
1049    /**
1050     * View flag indicating whether this view should have haptic feedback
1051     * enabled for events such as long presses.
1052     */
1053    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1054
1055    /**
1056     * <p>Indicates that the view hierarchy should stop saving state when
1057     * it reaches this view.  If state saving is initiated immediately at
1058     * the view, it will be allowed.
1059     * {@hide}
1060     */
1061    static final int PARENT_SAVE_DISABLED = 0x20000000;
1062
1063    /**
1064     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1065     * {@hide}
1066     */
1067    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1068
1069    /** @hide */
1070    @IntDef(flag = true,
1071            value = {
1072                FOCUSABLES_ALL,
1073                FOCUSABLES_TOUCH_MODE
1074            })
1075    @Retention(RetentionPolicy.SOURCE)
1076    public @interface FocusableMode {}
1077
1078    /**
1079     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1080     * should add all focusable Views regardless if they are focusable in touch mode.
1081     */
1082    public static final int FOCUSABLES_ALL = 0x00000000;
1083
1084    /**
1085     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1086     * should add only Views focusable in touch mode.
1087     */
1088    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1089
1090    /** @hide */
1091    @IntDef({
1092            FOCUS_BACKWARD,
1093            FOCUS_FORWARD,
1094            FOCUS_LEFT,
1095            FOCUS_UP,
1096            FOCUS_RIGHT,
1097            FOCUS_DOWN
1098    })
1099    @Retention(RetentionPolicy.SOURCE)
1100    public @interface FocusDirection {}
1101
1102    /** @hide */
1103    @IntDef({
1104            FOCUS_LEFT,
1105            FOCUS_UP,
1106            FOCUS_RIGHT,
1107            FOCUS_DOWN
1108    })
1109    @Retention(RetentionPolicy.SOURCE)
1110    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1111
1112    /**
1113     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1114     * item.
1115     */
1116    public static final int FOCUS_BACKWARD = 0x00000001;
1117
1118    /**
1119     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1120     * item.
1121     */
1122    public static final int FOCUS_FORWARD = 0x00000002;
1123
1124    /**
1125     * Use with {@link #focusSearch(int)}. Move focus to the left.
1126     */
1127    public static final int FOCUS_LEFT = 0x00000011;
1128
1129    /**
1130     * Use with {@link #focusSearch(int)}. Move focus up.
1131     */
1132    public static final int FOCUS_UP = 0x00000021;
1133
1134    /**
1135     * Use with {@link #focusSearch(int)}. Move focus to the right.
1136     */
1137    public static final int FOCUS_RIGHT = 0x00000042;
1138
1139    /**
1140     * Use with {@link #focusSearch(int)}. Move focus down.
1141     */
1142    public static final int FOCUS_DOWN = 0x00000082;
1143
1144    /**
1145     * Bits of {@link #getMeasuredWidthAndState()} and
1146     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1147     */
1148    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1149
1150    /**
1151     * Bits of {@link #getMeasuredWidthAndState()} and
1152     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1153     */
1154    public static final int MEASURED_STATE_MASK = 0xff000000;
1155
1156    /**
1157     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1158     * for functions that combine both width and height into a single int,
1159     * such as {@link #getMeasuredState()} and the childState argument of
1160     * {@link #resolveSizeAndState(int, int, int)}.
1161     */
1162    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1163
1164    /**
1165     * Bit of {@link #getMeasuredWidthAndState()} and
1166     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1167     * is smaller that the space the view would like to have.
1168     */
1169    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1170
1171    /**
1172     * Base View state sets
1173     */
1174    // Singles
1175    /**
1176     * Indicates the view has no states set. States are used with
1177     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1178     * view depending on its state.
1179     *
1180     * @see android.graphics.drawable.Drawable
1181     * @see #getDrawableState()
1182     */
1183    protected static final int[] EMPTY_STATE_SET;
1184    /**
1185     * Indicates the view is enabled. States are used with
1186     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1187     * view depending on its state.
1188     *
1189     * @see android.graphics.drawable.Drawable
1190     * @see #getDrawableState()
1191     */
1192    protected static final int[] ENABLED_STATE_SET;
1193    /**
1194     * Indicates the view is focused. States are used with
1195     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1196     * view depending on its state.
1197     *
1198     * @see android.graphics.drawable.Drawable
1199     * @see #getDrawableState()
1200     */
1201    protected static final int[] FOCUSED_STATE_SET;
1202    /**
1203     * Indicates the view is selected. States are used with
1204     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1205     * view depending on its state.
1206     *
1207     * @see android.graphics.drawable.Drawable
1208     * @see #getDrawableState()
1209     */
1210    protected static final int[] SELECTED_STATE_SET;
1211    /**
1212     * Indicates the view is pressed. States are used with
1213     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1214     * view depending on its state.
1215     *
1216     * @see android.graphics.drawable.Drawable
1217     * @see #getDrawableState()
1218     */
1219    protected static final int[] PRESSED_STATE_SET;
1220    /**
1221     * Indicates the view's window has focus. States are used with
1222     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1223     * view depending on its state.
1224     *
1225     * @see android.graphics.drawable.Drawable
1226     * @see #getDrawableState()
1227     */
1228    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1229    // Doubles
1230    /**
1231     * Indicates the view is enabled and has the focus.
1232     *
1233     * @see #ENABLED_STATE_SET
1234     * @see #FOCUSED_STATE_SET
1235     */
1236    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1237    /**
1238     * Indicates the view is enabled and selected.
1239     *
1240     * @see #ENABLED_STATE_SET
1241     * @see #SELECTED_STATE_SET
1242     */
1243    protected static final int[] ENABLED_SELECTED_STATE_SET;
1244    /**
1245     * Indicates the view is enabled and that its window has focus.
1246     *
1247     * @see #ENABLED_STATE_SET
1248     * @see #WINDOW_FOCUSED_STATE_SET
1249     */
1250    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1251    /**
1252     * Indicates the view is focused and selected.
1253     *
1254     * @see #FOCUSED_STATE_SET
1255     * @see #SELECTED_STATE_SET
1256     */
1257    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1258    /**
1259     * Indicates the view has the focus and that its window has the focus.
1260     *
1261     * @see #FOCUSED_STATE_SET
1262     * @see #WINDOW_FOCUSED_STATE_SET
1263     */
1264    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1265    /**
1266     * Indicates the view is selected and that its window has the focus.
1267     *
1268     * @see #SELECTED_STATE_SET
1269     * @see #WINDOW_FOCUSED_STATE_SET
1270     */
1271    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1272    // Triples
1273    /**
1274     * Indicates the view is enabled, focused and selected.
1275     *
1276     * @see #ENABLED_STATE_SET
1277     * @see #FOCUSED_STATE_SET
1278     * @see #SELECTED_STATE_SET
1279     */
1280    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1281    /**
1282     * Indicates the view is enabled, focused and its window has the focus.
1283     *
1284     * @see #ENABLED_STATE_SET
1285     * @see #FOCUSED_STATE_SET
1286     * @see #WINDOW_FOCUSED_STATE_SET
1287     */
1288    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1289    /**
1290     * Indicates the view is enabled, selected and its window has the focus.
1291     *
1292     * @see #ENABLED_STATE_SET
1293     * @see #SELECTED_STATE_SET
1294     * @see #WINDOW_FOCUSED_STATE_SET
1295     */
1296    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1297    /**
1298     * Indicates the view is focused, selected and its window has the focus.
1299     *
1300     * @see #FOCUSED_STATE_SET
1301     * @see #SELECTED_STATE_SET
1302     * @see #WINDOW_FOCUSED_STATE_SET
1303     */
1304    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1305    /**
1306     * Indicates the view is enabled, focused, selected and its window
1307     * has the focus.
1308     *
1309     * @see #ENABLED_STATE_SET
1310     * @see #FOCUSED_STATE_SET
1311     * @see #SELECTED_STATE_SET
1312     * @see #WINDOW_FOCUSED_STATE_SET
1313     */
1314    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1315    /**
1316     * Indicates the view is pressed and its window has the focus.
1317     *
1318     * @see #PRESSED_STATE_SET
1319     * @see #WINDOW_FOCUSED_STATE_SET
1320     */
1321    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1322    /**
1323     * Indicates the view is pressed and selected.
1324     *
1325     * @see #PRESSED_STATE_SET
1326     * @see #SELECTED_STATE_SET
1327     */
1328    protected static final int[] PRESSED_SELECTED_STATE_SET;
1329    /**
1330     * Indicates the view is pressed, selected and its window has the focus.
1331     *
1332     * @see #PRESSED_STATE_SET
1333     * @see #SELECTED_STATE_SET
1334     * @see #WINDOW_FOCUSED_STATE_SET
1335     */
1336    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1337    /**
1338     * Indicates the view is pressed and focused.
1339     *
1340     * @see #PRESSED_STATE_SET
1341     * @see #FOCUSED_STATE_SET
1342     */
1343    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1344    /**
1345     * Indicates the view is pressed, focused and its window has the focus.
1346     *
1347     * @see #PRESSED_STATE_SET
1348     * @see #FOCUSED_STATE_SET
1349     * @see #WINDOW_FOCUSED_STATE_SET
1350     */
1351    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1352    /**
1353     * Indicates the view is pressed, focused and selected.
1354     *
1355     * @see #PRESSED_STATE_SET
1356     * @see #SELECTED_STATE_SET
1357     * @see #FOCUSED_STATE_SET
1358     */
1359    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1360    /**
1361     * Indicates the view is pressed, focused, selected and its window has the focus.
1362     *
1363     * @see #PRESSED_STATE_SET
1364     * @see #FOCUSED_STATE_SET
1365     * @see #SELECTED_STATE_SET
1366     * @see #WINDOW_FOCUSED_STATE_SET
1367     */
1368    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1369    /**
1370     * Indicates the view is pressed and enabled.
1371     *
1372     * @see #PRESSED_STATE_SET
1373     * @see #ENABLED_STATE_SET
1374     */
1375    protected static final int[] PRESSED_ENABLED_STATE_SET;
1376    /**
1377     * Indicates the view is pressed, enabled and its window has the focus.
1378     *
1379     * @see #PRESSED_STATE_SET
1380     * @see #ENABLED_STATE_SET
1381     * @see #WINDOW_FOCUSED_STATE_SET
1382     */
1383    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1384    /**
1385     * Indicates the view is pressed, enabled and selected.
1386     *
1387     * @see #PRESSED_STATE_SET
1388     * @see #ENABLED_STATE_SET
1389     * @see #SELECTED_STATE_SET
1390     */
1391    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1392    /**
1393     * Indicates the view is pressed, enabled, selected and its window has the
1394     * focus.
1395     *
1396     * @see #PRESSED_STATE_SET
1397     * @see #ENABLED_STATE_SET
1398     * @see #SELECTED_STATE_SET
1399     * @see #WINDOW_FOCUSED_STATE_SET
1400     */
1401    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1402    /**
1403     * Indicates the view is pressed, enabled and focused.
1404     *
1405     * @see #PRESSED_STATE_SET
1406     * @see #ENABLED_STATE_SET
1407     * @see #FOCUSED_STATE_SET
1408     */
1409    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1410    /**
1411     * Indicates the view is pressed, enabled, focused and its window has the
1412     * focus.
1413     *
1414     * @see #PRESSED_STATE_SET
1415     * @see #ENABLED_STATE_SET
1416     * @see #FOCUSED_STATE_SET
1417     * @see #WINDOW_FOCUSED_STATE_SET
1418     */
1419    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1420    /**
1421     * Indicates the view is pressed, enabled, focused and selected.
1422     *
1423     * @see #PRESSED_STATE_SET
1424     * @see #ENABLED_STATE_SET
1425     * @see #SELECTED_STATE_SET
1426     * @see #FOCUSED_STATE_SET
1427     */
1428    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1429    /**
1430     * Indicates the view is pressed, enabled, focused, selected and its window
1431     * has the focus.
1432     *
1433     * @see #PRESSED_STATE_SET
1434     * @see #ENABLED_STATE_SET
1435     * @see #SELECTED_STATE_SET
1436     * @see #FOCUSED_STATE_SET
1437     * @see #WINDOW_FOCUSED_STATE_SET
1438     */
1439    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1440
1441    /**
1442     * The order here is very important to {@link #getDrawableState()}
1443     */
1444    private static final int[][] VIEW_STATE_SETS;
1445
1446    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1447    static final int VIEW_STATE_SELECTED = 1 << 1;
1448    static final int VIEW_STATE_FOCUSED = 1 << 2;
1449    static final int VIEW_STATE_ENABLED = 1 << 3;
1450    static final int VIEW_STATE_PRESSED = 1 << 4;
1451    static final int VIEW_STATE_ACTIVATED = 1 << 5;
1452    static final int VIEW_STATE_ACCELERATED = 1 << 6;
1453    static final int VIEW_STATE_HOVERED = 1 << 7;
1454    static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1455    static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
1456
1457    static final int[] VIEW_STATE_IDS = new int[] {
1458        R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
1459        R.attr.state_selected,          VIEW_STATE_SELECTED,
1460        R.attr.state_focused,           VIEW_STATE_FOCUSED,
1461        R.attr.state_enabled,           VIEW_STATE_ENABLED,
1462        R.attr.state_pressed,           VIEW_STATE_PRESSED,
1463        R.attr.state_activated,         VIEW_STATE_ACTIVATED,
1464        R.attr.state_accelerated,       VIEW_STATE_ACCELERATED,
1465        R.attr.state_hovered,           VIEW_STATE_HOVERED,
1466        R.attr.state_drag_can_accept,   VIEW_STATE_DRAG_CAN_ACCEPT,
1467        R.attr.state_drag_hovered,      VIEW_STATE_DRAG_HOVERED
1468    };
1469
1470    static {
1471        if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1472            throw new IllegalStateException(
1473                    "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1474        }
1475        int[] orderedIds = new int[VIEW_STATE_IDS.length];
1476        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
1477            int viewState = R.styleable.ViewDrawableStates[i];
1478            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
1479                if (VIEW_STATE_IDS[j] == viewState) {
1480                    orderedIds[i * 2] = viewState;
1481                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
1482                }
1483            }
1484        }
1485        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1486        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1487        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
1488            int numBits = Integer.bitCount(i);
1489            int[] set = new int[numBits];
1490            int pos = 0;
1491            for (int j = 0; j < orderedIds.length; j += 2) {
1492                if ((i & orderedIds[j+1]) != 0) {
1493                    set[pos++] = orderedIds[j];
1494                }
1495            }
1496            VIEW_STATE_SETS[i] = set;
1497        }
1498
1499        EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1500        WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1501        SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1502        SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1503                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1504        FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1505        FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1506                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1507        FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1508                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1509        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1510                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1511                | VIEW_STATE_FOCUSED];
1512        ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1513        ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1514                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1515        ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1516                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1517        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1518                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1519                | VIEW_STATE_ENABLED];
1520        ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1521                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1522        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1523                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1524                | VIEW_STATE_ENABLED];
1525        ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1526                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1527                | VIEW_STATE_ENABLED];
1528        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1529                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1530                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1531
1532        PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1533        PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1534                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1535        PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1536                VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1537        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1538                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1539                | VIEW_STATE_PRESSED];
1540        PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1541                VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1542        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1543                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1544                | VIEW_STATE_PRESSED];
1545        PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1546                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1547                | VIEW_STATE_PRESSED];
1548        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1549                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1550                | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1551        PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1552                VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1553        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1554                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1555                | VIEW_STATE_PRESSED];
1556        PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1557                VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1558                | VIEW_STATE_PRESSED];
1559        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1560                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1561                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1562        PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1563                VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1564                | VIEW_STATE_PRESSED];
1565        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1566                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1567                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1568        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1569                VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1570                | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1571        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1572                VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1573                | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1574                | VIEW_STATE_PRESSED];
1575    }
1576
1577    /**
1578     * Accessibility event types that are dispatched for text population.
1579     */
1580    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1581            AccessibilityEvent.TYPE_VIEW_CLICKED
1582            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1583            | AccessibilityEvent.TYPE_VIEW_SELECTED
1584            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1585            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1586            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1587            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1588            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1589            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1590            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1591            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1592
1593    /**
1594     * Temporary Rect currently for use in setBackground().  This will probably
1595     * be extended in the future to hold our own class with more than just
1596     * a Rect. :)
1597     */
1598    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1599
1600    /**
1601     * Map used to store views' tags.
1602     */
1603    private SparseArray<Object> mKeyedTags;
1604
1605    /**
1606     * The next available accessibility id.
1607     */
1608    private static int sNextAccessibilityViewId;
1609
1610    /**
1611     * The animation currently associated with this view.
1612     * @hide
1613     */
1614    protected Animation mCurrentAnimation = null;
1615
1616    /**
1617     * Width as measured during measure pass.
1618     * {@hide}
1619     */
1620    @ViewDebug.ExportedProperty(category = "measurement")
1621    int mMeasuredWidth;
1622
1623    /**
1624     * Height as measured during measure pass.
1625     * {@hide}
1626     */
1627    @ViewDebug.ExportedProperty(category = "measurement")
1628    int mMeasuredHeight;
1629
1630    /**
1631     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1632     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1633     * its display list. This flag, used only when hw accelerated, allows us to clear the
1634     * flag while retaining this information until it's needed (at getDisplayList() time and
1635     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1636     *
1637     * {@hide}
1638     */
1639    boolean mRecreateDisplayList = false;
1640
1641    /**
1642     * The view's identifier.
1643     * {@hide}
1644     *
1645     * @see #setId(int)
1646     * @see #getId()
1647     */
1648    @ViewDebug.ExportedProperty(resolveId = true)
1649    int mID = NO_ID;
1650
1651    /**
1652     * The stable ID of this view for accessibility purposes.
1653     */
1654    int mAccessibilityViewId = NO_ID;
1655
1656    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1657
1658    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1659
1660    /**
1661     * The view's tag.
1662     * {@hide}
1663     *
1664     * @see #setTag(Object)
1665     * @see #getTag()
1666     */
1667    protected Object mTag = null;
1668
1669    // for mPrivateFlags:
1670    /** {@hide} */
1671    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1672    /** {@hide} */
1673    static final int PFLAG_FOCUSED                     = 0x00000002;
1674    /** {@hide} */
1675    static final int PFLAG_SELECTED                    = 0x00000004;
1676    /** {@hide} */
1677    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1678    /** {@hide} */
1679    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1680    /** {@hide} */
1681    static final int PFLAG_DRAWN                       = 0x00000020;
1682    /**
1683     * When this flag is set, this view is running an animation on behalf of its
1684     * children and should therefore not cancel invalidate requests, even if they
1685     * lie outside of this view's bounds.
1686     *
1687     * {@hide}
1688     */
1689    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1690    /** {@hide} */
1691    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1692    /** {@hide} */
1693    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1694    /** {@hide} */
1695    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1696    /** {@hide} */
1697    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1698    /** {@hide} */
1699    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1700    /** {@hide} */
1701    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1702    /** {@hide} */
1703    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1704
1705    private static final int PFLAG_PRESSED             = 0x00004000;
1706
1707    /** {@hide} */
1708    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1709    /**
1710     * Flag used to indicate that this view should be drawn once more (and only once
1711     * more) after its animation has completed.
1712     * {@hide}
1713     */
1714    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1715
1716    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1717
1718    /**
1719     * Indicates that the View returned true when onSetAlpha() was called and that
1720     * the alpha must be restored.
1721     * {@hide}
1722     */
1723    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1724
1725    /**
1726     * Set by {@link #setScrollContainer(boolean)}.
1727     */
1728    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1729
1730    /**
1731     * Set by {@link #setScrollContainer(boolean)}.
1732     */
1733    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1734
1735    /**
1736     * View flag indicating whether this view was invalidated (fully or partially.)
1737     *
1738     * @hide
1739     */
1740    static final int PFLAG_DIRTY                       = 0x00200000;
1741
1742    /**
1743     * View flag indicating whether this view was invalidated by an opaque
1744     * invalidate request.
1745     *
1746     * @hide
1747     */
1748    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1749
1750    /**
1751     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1752     *
1753     * @hide
1754     */
1755    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1756
1757    /**
1758     * Indicates whether the background is opaque.
1759     *
1760     * @hide
1761     */
1762    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1763
1764    /**
1765     * Indicates whether the scrollbars are opaque.
1766     *
1767     * @hide
1768     */
1769    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1770
1771    /**
1772     * Indicates whether the view is opaque.
1773     *
1774     * @hide
1775     */
1776    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1777
1778    /**
1779     * Indicates a prepressed state;
1780     * the short time between ACTION_DOWN and recognizing
1781     * a 'real' press. Prepressed is used to recognize quick taps
1782     * even when they are shorter than ViewConfiguration.getTapTimeout().
1783     *
1784     * @hide
1785     */
1786    private static final int PFLAG_PREPRESSED          = 0x02000000;
1787
1788    /**
1789     * Indicates whether the view is temporarily detached.
1790     *
1791     * @hide
1792     */
1793    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1794
1795    /**
1796     * Indicates that we should awaken scroll bars once attached
1797     *
1798     * @hide
1799     */
1800    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1801
1802    /**
1803     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1804     * @hide
1805     */
1806    private static final int PFLAG_HOVERED             = 0x10000000;
1807
1808    /**
1809     * no longer needed, should be reused
1810     */
1811    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1812
1813    /** {@hide} */
1814    static final int PFLAG_ACTIVATED                   = 0x40000000;
1815
1816    /**
1817     * Indicates that this view was specifically invalidated, not just dirtied because some
1818     * child view was invalidated. The flag is used to determine when we need to recreate
1819     * a view's display list (as opposed to just returning a reference to its existing
1820     * display list).
1821     *
1822     * @hide
1823     */
1824    static final int PFLAG_INVALIDATED                 = 0x80000000;
1825
1826    /**
1827     * Masks for mPrivateFlags2, as generated by dumpFlags():
1828     *
1829     * |-------|-------|-------|-------|
1830     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1831     *                                1  PFLAG2_DRAG_HOVERED
1832     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1833     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1834     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1835     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1836     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1837     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1838     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1839     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1840     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1841     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1842     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1843     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1844     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1845     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1846     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1847     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1848     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1849     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1850     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1851     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1852     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1853     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1854     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1855     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1856     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1857     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1858     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1859     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1860     *    1                              PFLAG2_PADDING_RESOLVED
1861     *   1                               PFLAG2_DRAWABLE_RESOLVED
1862     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1863     * |-------|-------|-------|-------|
1864     */
1865
1866    /**
1867     * Indicates that this view has reported that it can accept the current drag's content.
1868     * Cleared when the drag operation concludes.
1869     * @hide
1870     */
1871    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1872
1873    /**
1874     * Indicates that this view is currently directly under the drag location in a
1875     * drag-and-drop operation involving content that it can accept.  Cleared when
1876     * the drag exits the view, or when the drag operation concludes.
1877     * @hide
1878     */
1879    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1880
1881    /** @hide */
1882    @IntDef({
1883        LAYOUT_DIRECTION_LTR,
1884        LAYOUT_DIRECTION_RTL,
1885        LAYOUT_DIRECTION_INHERIT,
1886        LAYOUT_DIRECTION_LOCALE
1887    })
1888    @Retention(RetentionPolicy.SOURCE)
1889    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1890    public @interface LayoutDir {}
1891
1892    /** @hide */
1893    @IntDef({
1894        LAYOUT_DIRECTION_LTR,
1895        LAYOUT_DIRECTION_RTL
1896    })
1897    @Retention(RetentionPolicy.SOURCE)
1898    public @interface ResolvedLayoutDir {}
1899
1900    /**
1901     * Horizontal layout direction of this view is from Left to Right.
1902     * Use with {@link #setLayoutDirection}.
1903     */
1904    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1905
1906    /**
1907     * Horizontal layout direction of this view is from Right to Left.
1908     * Use with {@link #setLayoutDirection}.
1909     */
1910    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1911
1912    /**
1913     * Horizontal layout direction of this view is inherited from its parent.
1914     * Use with {@link #setLayoutDirection}.
1915     */
1916    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1917
1918    /**
1919     * Horizontal layout direction of this view is from deduced from the default language
1920     * script for the locale. Use with {@link #setLayoutDirection}.
1921     */
1922    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1923
1924    /**
1925     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1926     * @hide
1927     */
1928    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1929
1930    /**
1931     * Mask for use with private flags indicating bits used for horizontal layout direction.
1932     * @hide
1933     */
1934    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1935
1936    /**
1937     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1938     * right-to-left direction.
1939     * @hide
1940     */
1941    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1942
1943    /**
1944     * Indicates whether the view horizontal layout direction has been resolved.
1945     * @hide
1946     */
1947    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1948
1949    /**
1950     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1951     * @hide
1952     */
1953    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1954            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1955
1956    /*
1957     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1958     * flag value.
1959     * @hide
1960     */
1961    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1962            LAYOUT_DIRECTION_LTR,
1963            LAYOUT_DIRECTION_RTL,
1964            LAYOUT_DIRECTION_INHERIT,
1965            LAYOUT_DIRECTION_LOCALE
1966    };
1967
1968    /**
1969     * Default horizontal layout direction.
1970     */
1971    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1972
1973    /**
1974     * Default horizontal layout direction.
1975     * @hide
1976     */
1977    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1978
1979    /**
1980     * Text direction is inherited thru {@link ViewGroup}
1981     */
1982    public static final int TEXT_DIRECTION_INHERIT = 0;
1983
1984    /**
1985     * Text direction is using "first strong algorithm". The first strong directional character
1986     * determines the paragraph direction. If there is no strong directional character, the
1987     * paragraph direction is the view's resolved layout direction.
1988     */
1989    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1990
1991    /**
1992     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1993     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1994     * If there are neither, the paragraph direction is the view's resolved layout direction.
1995     */
1996    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1997
1998    /**
1999     * Text direction is forced to LTR.
2000     */
2001    public static final int TEXT_DIRECTION_LTR = 3;
2002
2003    /**
2004     * Text direction is forced to RTL.
2005     */
2006    public static final int TEXT_DIRECTION_RTL = 4;
2007
2008    /**
2009     * Text direction is coming from the system Locale.
2010     */
2011    public static final int TEXT_DIRECTION_LOCALE = 5;
2012
2013    /**
2014     * Default text direction is inherited
2015     */
2016    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2017
2018    /**
2019     * Default resolved text direction
2020     * @hide
2021     */
2022    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2023
2024    /**
2025     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2026     * @hide
2027     */
2028    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2029
2030    /**
2031     * Mask for use with private flags indicating bits used for text direction.
2032     * @hide
2033     */
2034    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2035            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2036
2037    /**
2038     * Array of text direction flags for mapping attribute "textDirection" to correct
2039     * flag value.
2040     * @hide
2041     */
2042    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2043            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2044            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2048            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2049    };
2050
2051    /**
2052     * Indicates whether the view text direction has been resolved.
2053     * @hide
2054     */
2055    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2056            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2057
2058    /**
2059     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2060     * @hide
2061     */
2062    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2063
2064    /**
2065     * Mask for use with private flags indicating bits used for resolved text direction.
2066     * @hide
2067     */
2068    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2069            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2070
2071    /**
2072     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2073     * @hide
2074     */
2075    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2076            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2077
2078    /** @hide */
2079    @IntDef({
2080        TEXT_ALIGNMENT_INHERIT,
2081        TEXT_ALIGNMENT_GRAVITY,
2082        TEXT_ALIGNMENT_CENTER,
2083        TEXT_ALIGNMENT_TEXT_START,
2084        TEXT_ALIGNMENT_TEXT_END,
2085        TEXT_ALIGNMENT_VIEW_START,
2086        TEXT_ALIGNMENT_VIEW_END
2087    })
2088    @Retention(RetentionPolicy.SOURCE)
2089    public @interface TextAlignment {}
2090
2091    /**
2092     * Default text alignment. The text alignment of this View is inherited from its parent.
2093     * Use with {@link #setTextAlignment(int)}
2094     */
2095    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2096
2097    /**
2098     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2099     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2100     *
2101     * Use with {@link #setTextAlignment(int)}
2102     */
2103    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2104
2105    /**
2106     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2107     *
2108     * Use with {@link #setTextAlignment(int)}
2109     */
2110    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2111
2112    /**
2113     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2114     *
2115     * Use with {@link #setTextAlignment(int)}
2116     */
2117    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2118
2119    /**
2120     * Center the paragraph, e.g. ALIGN_CENTER.
2121     *
2122     * Use with {@link #setTextAlignment(int)}
2123     */
2124    public static final int TEXT_ALIGNMENT_CENTER = 4;
2125
2126    /**
2127     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2128     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2129     *
2130     * Use with {@link #setTextAlignment(int)}
2131     */
2132    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2133
2134    /**
2135     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2136     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2137     *
2138     * Use with {@link #setTextAlignment(int)}
2139     */
2140    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2141
2142    /**
2143     * Default text alignment is inherited
2144     */
2145    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2146
2147    /**
2148     * Default resolved text alignment
2149     * @hide
2150     */
2151    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2152
2153    /**
2154      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2155      * @hide
2156      */
2157    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2158
2159    /**
2160      * Mask for use with private flags indicating bits used for text alignment.
2161      * @hide
2162      */
2163    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2164
2165    /**
2166     * Array of text direction flags for mapping attribute "textAlignment" to correct
2167     * flag value.
2168     * @hide
2169     */
2170    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2171            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2172            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2173            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2174            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2177            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2178    };
2179
2180    /**
2181     * Indicates whether the view text alignment has been resolved.
2182     * @hide
2183     */
2184    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2185
2186    /**
2187     * Bit shift to get the resolved text alignment.
2188     * @hide
2189     */
2190    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2191
2192    /**
2193     * Mask for use with private flags indicating bits used for text alignment.
2194     * @hide
2195     */
2196    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2197            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2198
2199    /**
2200     * Indicates whether if the view text alignment has been resolved to gravity
2201     */
2202    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2203            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2204
2205    // Accessiblity constants for mPrivateFlags2
2206
2207    /**
2208     * Shift for the bits in {@link #mPrivateFlags2} related to the
2209     * "importantForAccessibility" attribute.
2210     */
2211    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2212
2213    /**
2214     * Automatically determine whether a view is important for accessibility.
2215     */
2216    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2217
2218    /**
2219     * The view is important for accessibility.
2220     */
2221    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2222
2223    /**
2224     * The view is not important for accessibility.
2225     */
2226    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2227
2228    /**
2229     * The view is not important for accessibility, nor are any of its
2230     * descendant views.
2231     */
2232    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2233
2234    /**
2235     * The default whether the view is important for accessibility.
2236     */
2237    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2238
2239    /**
2240     * Mask for obtainig the bits which specify how to determine
2241     * whether a view is important for accessibility.
2242     */
2243    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2244        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2245        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2246        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2247
2248    /**
2249     * Shift for the bits in {@link #mPrivateFlags2} related to the
2250     * "accessibilityLiveRegion" attribute.
2251     */
2252    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2253
2254    /**
2255     * Live region mode specifying that accessibility services should not
2256     * automatically announce changes to this view. This is the default live
2257     * region mode for most views.
2258     * <p>
2259     * Use with {@link #setAccessibilityLiveRegion(int)}.
2260     */
2261    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2262
2263    /**
2264     * Live region mode specifying that accessibility services should announce
2265     * changes to this view.
2266     * <p>
2267     * Use with {@link #setAccessibilityLiveRegion(int)}.
2268     */
2269    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2270
2271    /**
2272     * Live region mode specifying that accessibility services should interrupt
2273     * ongoing speech to immediately announce changes to this view.
2274     * <p>
2275     * Use with {@link #setAccessibilityLiveRegion(int)}.
2276     */
2277    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2278
2279    /**
2280     * The default whether the view is important for accessibility.
2281     */
2282    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2283
2284    /**
2285     * Mask for obtaining the bits which specify a view's accessibility live
2286     * region mode.
2287     */
2288    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2289            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2290            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2291
2292    /**
2293     * Flag indicating whether a view has accessibility focus.
2294     */
2295    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2296
2297    /**
2298     * Flag whether the accessibility state of the subtree rooted at this view changed.
2299     */
2300    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2301
2302    /**
2303     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2304     * is used to check whether later changes to the view's transform should invalidate the
2305     * view to force the quickReject test to run again.
2306     */
2307    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2308
2309    /**
2310     * Flag indicating that start/end padding has been resolved into left/right padding
2311     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2312     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2313     * during measurement. In some special cases this is required such as when an adapter-based
2314     * view measures prospective children without attaching them to a window.
2315     */
2316    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2317
2318    /**
2319     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2320     */
2321    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2322
2323    /**
2324     * Indicates that the view is tracking some sort of transient state
2325     * that the app should not need to be aware of, but that the framework
2326     * should take special care to preserve.
2327     */
2328    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2329
2330    /**
2331     * Group of bits indicating that RTL properties resolution is done.
2332     */
2333    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2334            PFLAG2_TEXT_DIRECTION_RESOLVED |
2335            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2336            PFLAG2_PADDING_RESOLVED |
2337            PFLAG2_DRAWABLE_RESOLVED;
2338
2339    // There are a couple of flags left in mPrivateFlags2
2340
2341    /* End of masks for mPrivateFlags2 */
2342
2343    /**
2344     * Masks for mPrivateFlags3, as generated by dumpFlags():
2345     *
2346     * |-------|-------|-------|-------|
2347     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2348     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2349     *                               1   PFLAG3_IS_LAID_OUT
2350     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2351     *                             1     PFLAG3_CALLED_SUPER
2352     * |-------|-------|-------|-------|
2353     */
2354
2355    /**
2356     * Flag indicating that view has a transform animation set on it. This is used to track whether
2357     * an animation is cleared between successive frames, in order to tell the associated
2358     * DisplayList to clear its animation matrix.
2359     */
2360    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2361
2362    /**
2363     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2364     * animation is cleared between successive frames, in order to tell the associated
2365     * DisplayList to restore its alpha value.
2366     */
2367    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2368
2369    /**
2370     * Flag indicating that the view has been through at least one layout since it
2371     * was last attached to a window.
2372     */
2373    static final int PFLAG3_IS_LAID_OUT = 0x4;
2374
2375    /**
2376     * Flag indicating that a call to measure() was skipped and should be done
2377     * instead when layout() is invoked.
2378     */
2379    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2380
2381    /**
2382     * Flag indicating that an overridden method correctly called down to
2383     * the superclass implementation as required by the API spec.
2384     */
2385    static final int PFLAG3_CALLED_SUPER = 0x10;
2386
2387    /**
2388     * Flag indicating that we're in the process of applying window insets.
2389     */
2390    static final int PFLAG3_APPLYING_INSETS = 0x20;
2391
2392    /**
2393     * Flag indicating that we're in the process of fitting system windows using the old method.
2394     */
2395    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2396
2397    /**
2398     * Flag indicating that nested scrolling is enabled for this view.
2399     * The view will optionally cooperate with views up its parent chain to allow for
2400     * integrated nested scrolling along the same axis.
2401     */
2402    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2403
2404    /* End of masks for mPrivateFlags3 */
2405
2406    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2407
2408    /**
2409     * Always allow a user to over-scroll this view, provided it is a
2410     * view that can scroll.
2411     *
2412     * @see #getOverScrollMode()
2413     * @see #setOverScrollMode(int)
2414     */
2415    public static final int OVER_SCROLL_ALWAYS = 0;
2416
2417    /**
2418     * Allow a user to over-scroll this view only if the content is large
2419     * enough to meaningfully scroll, provided it is a view that can scroll.
2420     *
2421     * @see #getOverScrollMode()
2422     * @see #setOverScrollMode(int)
2423     */
2424    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2425
2426    /**
2427     * Never allow a user to over-scroll this view.
2428     *
2429     * @see #getOverScrollMode()
2430     * @see #setOverScrollMode(int)
2431     */
2432    public static final int OVER_SCROLL_NEVER = 2;
2433
2434    /**
2435     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2436     * requested the system UI (status bar) to be visible (the default).
2437     *
2438     * @see #setSystemUiVisibility(int)
2439     */
2440    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2441
2442    /**
2443     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2444     * system UI to enter an unobtrusive "low profile" mode.
2445     *
2446     * <p>This is for use in games, book readers, video players, or any other
2447     * "immersive" application where the usual system chrome is deemed too distracting.
2448     *
2449     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2450     *
2451     * @see #setSystemUiVisibility(int)
2452     */
2453    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2454
2455    /**
2456     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2457     * system navigation be temporarily hidden.
2458     *
2459     * <p>This is an even less obtrusive state than that called for by
2460     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2461     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2462     * those to disappear. This is useful (in conjunction with the
2463     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2464     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2465     * window flags) for displaying content using every last pixel on the display.
2466     *
2467     * <p>There is a limitation: because navigation controls are so important, the least user
2468     * interaction will cause them to reappear immediately.  When this happens, both
2469     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2470     * so that both elements reappear at the same time.
2471     *
2472     * @see #setSystemUiVisibility(int)
2473     */
2474    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2475
2476    /**
2477     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2478     * into the normal fullscreen mode so that its content can take over the screen
2479     * while still allowing the user to interact with the application.
2480     *
2481     * <p>This has the same visual effect as
2482     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2483     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2484     * meaning that non-critical screen decorations (such as the status bar) will be
2485     * hidden while the user is in the View's window, focusing the experience on
2486     * that content.  Unlike the window flag, if you are using ActionBar in
2487     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2488     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2489     * hide the action bar.
2490     *
2491     * <p>This approach to going fullscreen is best used over the window flag when
2492     * it is a transient state -- that is, the application does this at certain
2493     * points in its user interaction where it wants to allow the user to focus
2494     * on content, but not as a continuous state.  For situations where the application
2495     * would like to simply stay full screen the entire time (such as a game that
2496     * wants to take over the screen), the
2497     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2498     * is usually a better approach.  The state set here will be removed by the system
2499     * in various situations (such as the user moving to another application) like
2500     * the other system UI states.
2501     *
2502     * <p>When using this flag, the application should provide some easy facility
2503     * for the user to go out of it.  A common example would be in an e-book
2504     * reader, where tapping on the screen brings back whatever screen and UI
2505     * decorations that had been hidden while the user was immersed in reading
2506     * the book.
2507     *
2508     * @see #setSystemUiVisibility(int)
2509     */
2510    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2511
2512    /**
2513     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2514     * flags, we would like a stable view of the content insets given to
2515     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2516     * will always represent the worst case that the application can expect
2517     * as a continuous state.  In the stock Android UI this is the space for
2518     * the system bar, nav bar, and status bar, but not more transient elements
2519     * such as an input method.
2520     *
2521     * The stable layout your UI sees is based on the system UI modes you can
2522     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2523     * then you will get a stable layout for changes of the
2524     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2525     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2526     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2527     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2528     * with a stable layout.  (Note that you should avoid using
2529     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2530     *
2531     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2532     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2533     * then a hidden status bar will be considered a "stable" state for purposes
2534     * here.  This allows your UI to continually hide the status bar, while still
2535     * using the system UI flags to hide the action bar while still retaining
2536     * a stable layout.  Note that changing the window fullscreen flag will never
2537     * provide a stable layout for a clean transition.
2538     *
2539     * <p>If you are using ActionBar in
2540     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2541     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2542     * insets it adds to those given to the application.
2543     */
2544    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2545
2546    /**
2547     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2548     * to be layed out as if it has requested
2549     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2550     * allows it to avoid artifacts when switching in and out of that mode, at
2551     * the expense that some of its user interface may be covered by screen
2552     * decorations when they are shown.  You can perform layout of your inner
2553     * UI elements to account for the navigation system UI through the
2554     * {@link #fitSystemWindows(Rect)} method.
2555     */
2556    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2557
2558    /**
2559     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2560     * to be layed out as if it has requested
2561     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2562     * allows it to avoid artifacts when switching in and out of that mode, at
2563     * the expense that some of its user interface may be covered by screen
2564     * decorations when they are shown.  You can perform layout of your inner
2565     * UI elements to account for non-fullscreen system UI through the
2566     * {@link #fitSystemWindows(Rect)} method.
2567     */
2568    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2569
2570    /**
2571     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2572     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2573     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2574     * user interaction.
2575     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2576     * has an effect when used in combination with that flag.</p>
2577     */
2578    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2579
2580    /**
2581     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2582     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2583     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2584     * experience while also hiding the system bars.  If this flag is not set,
2585     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2586     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2587     * if the user swipes from the top of the screen.
2588     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2589     * system gestures, such as swiping from the top of the screen.  These transient system bars
2590     * will overlay app’s content, may have some degree of transparency, and will automatically
2591     * hide after a short timeout.
2592     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2593     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2594     * with one or both of those flags.</p>
2595     */
2596    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2597
2598    /**
2599     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2600     */
2601    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2602
2603    /**
2604     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2605     */
2606    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2607
2608    /**
2609     * @hide
2610     *
2611     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2612     * out of the public fields to keep the undefined bits out of the developer's way.
2613     *
2614     * Flag to make the status bar not expandable.  Unless you also
2615     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2616     */
2617    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2618
2619    /**
2620     * @hide
2621     *
2622     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2623     * out of the public fields to keep the undefined bits out of the developer's way.
2624     *
2625     * Flag to hide notification icons and scrolling ticker text.
2626     */
2627    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2628
2629    /**
2630     * @hide
2631     *
2632     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2633     * out of the public fields to keep the undefined bits out of the developer's way.
2634     *
2635     * Flag to disable incoming notification alerts.  This will not block
2636     * icons, but it will block sound, vibrating and other visual or aural notifications.
2637     */
2638    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2639
2640    /**
2641     * @hide
2642     *
2643     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2644     * out of the public fields to keep the undefined bits out of the developer's way.
2645     *
2646     * Flag to hide only the scrolling ticker.  Note that
2647     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2648     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2649     */
2650    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2651
2652    /**
2653     * @hide
2654     *
2655     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2656     * out of the public fields to keep the undefined bits out of the developer's way.
2657     *
2658     * Flag to hide the center system info area.
2659     */
2660    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2661
2662    /**
2663     * @hide
2664     *
2665     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2666     * out of the public fields to keep the undefined bits out of the developer's way.
2667     *
2668     * Flag to hide only the home button.  Don't use this
2669     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2670     */
2671    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2672
2673    /**
2674     * @hide
2675     *
2676     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2677     * out of the public fields to keep the undefined bits out of the developer's way.
2678     *
2679     * Flag to hide only the back button. Don't use this
2680     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2681     */
2682    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2683
2684    /**
2685     * @hide
2686     *
2687     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2688     * out of the public fields to keep the undefined bits out of the developer's way.
2689     *
2690     * Flag to hide only the clock.  You might use this if your activity has
2691     * its own clock making the status bar's clock redundant.
2692     */
2693    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2694
2695    /**
2696     * @hide
2697     *
2698     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2699     * out of the public fields to keep the undefined bits out of the developer's way.
2700     *
2701     * Flag to hide only the recent apps button. Don't use this
2702     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2703     */
2704    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2705
2706    /**
2707     * @hide
2708     *
2709     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2710     * out of the public fields to keep the undefined bits out of the developer's way.
2711     *
2712     * Flag to disable the global search gesture. Don't use this
2713     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2714     */
2715    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2716
2717    /**
2718     * @hide
2719     *
2720     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2721     * out of the public fields to keep the undefined bits out of the developer's way.
2722     *
2723     * Flag to specify that the status bar is displayed in transient mode.
2724     */
2725    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2726
2727    /**
2728     * @hide
2729     *
2730     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2731     * out of the public fields to keep the undefined bits out of the developer's way.
2732     *
2733     * Flag to specify that the navigation bar is displayed in transient mode.
2734     */
2735    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2736
2737    /**
2738     * @hide
2739     *
2740     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2741     * out of the public fields to keep the undefined bits out of the developer's way.
2742     *
2743     * Flag to specify that the hidden status bar would like to be shown.
2744     */
2745    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2746
2747    /**
2748     * @hide
2749     *
2750     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2751     * out of the public fields to keep the undefined bits out of the developer's way.
2752     *
2753     * Flag to specify that the hidden navigation bar would like to be shown.
2754     */
2755    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2756
2757    /**
2758     * @hide
2759     *
2760     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2761     * out of the public fields to keep the undefined bits out of the developer's way.
2762     *
2763     * Flag to specify that the status bar is displayed in translucent mode.
2764     */
2765    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2766
2767    /**
2768     * @hide
2769     *
2770     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2771     * out of the public fields to keep the undefined bits out of the developer's way.
2772     *
2773     * Flag to specify that the navigation bar is displayed in translucent mode.
2774     */
2775    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2776
2777    /**
2778     * @hide
2779     *
2780     * Whether Recents is visible or not.
2781     */
2782    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2783
2784    /**
2785     * @hide
2786     *
2787     * Makes system ui transparent.
2788     */
2789    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2790
2791    /**
2792     * @hide
2793     */
2794    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2795
2796    /**
2797     * These are the system UI flags that can be cleared by events outside
2798     * of an application.  Currently this is just the ability to tap on the
2799     * screen while hiding the navigation bar to have it return.
2800     * @hide
2801     */
2802    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2803            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2804            | SYSTEM_UI_FLAG_FULLSCREEN;
2805
2806    /**
2807     * Flags that can impact the layout in relation to system UI.
2808     */
2809    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2810            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2811            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2812
2813    /** @hide */
2814    @IntDef(flag = true,
2815            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2816    @Retention(RetentionPolicy.SOURCE)
2817    public @interface FindViewFlags {}
2818
2819    /**
2820     * Find views that render the specified text.
2821     *
2822     * @see #findViewsWithText(ArrayList, CharSequence, int)
2823     */
2824    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2825
2826    /**
2827     * Find find views that contain the specified content description.
2828     *
2829     * @see #findViewsWithText(ArrayList, CharSequence, int)
2830     */
2831    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2832
2833    /**
2834     * Find views that contain {@link AccessibilityNodeProvider}. Such
2835     * a View is a root of virtual view hierarchy and may contain the searched
2836     * text. If this flag is set Views with providers are automatically
2837     * added and it is a responsibility of the client to call the APIs of
2838     * the provider to determine whether the virtual tree rooted at this View
2839     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2840     * representing the virtual views with this text.
2841     *
2842     * @see #findViewsWithText(ArrayList, CharSequence, int)
2843     *
2844     * @hide
2845     */
2846    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2847
2848    /**
2849     * The undefined cursor position.
2850     *
2851     * @hide
2852     */
2853    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2854
2855    /**
2856     * Indicates that the screen has changed state and is now off.
2857     *
2858     * @see #onScreenStateChanged(int)
2859     */
2860    public static final int SCREEN_STATE_OFF = 0x0;
2861
2862    /**
2863     * Indicates that the screen has changed state and is now on.
2864     *
2865     * @see #onScreenStateChanged(int)
2866     */
2867    public static final int SCREEN_STATE_ON = 0x1;
2868
2869    /**
2870     * Indicates no axis of view scrolling.
2871     */
2872    public static final int SCROLL_AXIS_NONE = 0;
2873
2874    /**
2875     * Indicates scrolling along the horizontal axis.
2876     */
2877    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2878
2879    /**
2880     * Indicates scrolling along the vertical axis.
2881     */
2882    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2883
2884    /**
2885     * Controls the over-scroll mode for this view.
2886     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2887     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2888     * and {@link #OVER_SCROLL_NEVER}.
2889     */
2890    private int mOverScrollMode;
2891
2892    /**
2893     * The parent this view is attached to.
2894     * {@hide}
2895     *
2896     * @see #getParent()
2897     */
2898    protected ViewParent mParent;
2899
2900    /**
2901     * {@hide}
2902     */
2903    AttachInfo mAttachInfo;
2904
2905    /**
2906     * {@hide}
2907     */
2908    @ViewDebug.ExportedProperty(flagMapping = {
2909        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2910                name = "FORCE_LAYOUT"),
2911        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2912                name = "LAYOUT_REQUIRED"),
2913        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2914            name = "DRAWING_CACHE_INVALID", outputIf = false),
2915        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2916        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2917        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2918        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2919    }, formatToHexString = true)
2920    int mPrivateFlags;
2921    int mPrivateFlags2;
2922    int mPrivateFlags3;
2923
2924    /**
2925     * This view's request for the visibility of the status bar.
2926     * @hide
2927     */
2928    @ViewDebug.ExportedProperty(flagMapping = {
2929        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2930                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2931                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2932        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2933                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2934                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2935        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2936                                equals = SYSTEM_UI_FLAG_VISIBLE,
2937                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2938    }, formatToHexString = true)
2939    int mSystemUiVisibility;
2940
2941    /**
2942     * Reference count for transient state.
2943     * @see #setHasTransientState(boolean)
2944     */
2945    int mTransientStateCount = 0;
2946
2947    /**
2948     * Count of how many windows this view has been attached to.
2949     */
2950    int mWindowAttachCount;
2951
2952    /**
2953     * The layout parameters associated with this view and used by the parent
2954     * {@link android.view.ViewGroup} to determine how this view should be
2955     * laid out.
2956     * {@hide}
2957     */
2958    protected ViewGroup.LayoutParams mLayoutParams;
2959
2960    /**
2961     * The view flags hold various views states.
2962     * {@hide}
2963     */
2964    @ViewDebug.ExportedProperty(formatToHexString = true)
2965    int mViewFlags;
2966
2967    static class TransformationInfo {
2968        /**
2969         * The transform matrix for the View. This transform is calculated internally
2970         * based on the translation, rotation, and scale properties.
2971         *
2972         * Do *not* use this variable directly; instead call getMatrix(), which will
2973         * load the value from the View's RenderNode.
2974         */
2975        private final Matrix mMatrix = new Matrix();
2976
2977        /**
2978         * The inverse transform matrix for the View. This transform is calculated
2979         * internally based on the translation, rotation, and scale properties.
2980         *
2981         * Do *not* use this variable directly; instead call getInverseMatrix(),
2982         * which will load the value from the View's RenderNode.
2983         */
2984        private Matrix mInverseMatrix;
2985
2986        /**
2987         * The opacity of the View. This is a value from 0 to 1, where 0 means
2988         * completely transparent and 1 means completely opaque.
2989         */
2990        @ViewDebug.ExportedProperty
2991        float mAlpha = 1f;
2992
2993        /**
2994         * The opacity of the view as manipulated by the Fade transition. This is a hidden
2995         * property only used by transitions, which is composited with the other alpha
2996         * values to calculate the final visual alpha value.
2997         */
2998        float mTransitionAlpha = 1f;
2999    }
3000
3001    TransformationInfo mTransformationInfo;
3002
3003    /**
3004     * Current clip bounds. to which all drawing of this view are constrained.
3005     */
3006    Rect mClipBounds = null;
3007
3008    private boolean mLastIsOpaque;
3009
3010    /**
3011     * The distance in pixels from the left edge of this view's parent
3012     * to the left edge of this view.
3013     * {@hide}
3014     */
3015    @ViewDebug.ExportedProperty(category = "layout")
3016    protected int mLeft;
3017    /**
3018     * The distance in pixels from the left edge of this view's parent
3019     * to the right edge of this view.
3020     * {@hide}
3021     */
3022    @ViewDebug.ExportedProperty(category = "layout")
3023    protected int mRight;
3024    /**
3025     * The distance in pixels from the top edge of this view's parent
3026     * to the top edge of this view.
3027     * {@hide}
3028     */
3029    @ViewDebug.ExportedProperty(category = "layout")
3030    protected int mTop;
3031    /**
3032     * The distance in pixels from the top edge of this view's parent
3033     * to the bottom edge of this view.
3034     * {@hide}
3035     */
3036    @ViewDebug.ExportedProperty(category = "layout")
3037    protected int mBottom;
3038
3039    /**
3040     * The offset, in pixels, by which the content of this view is scrolled
3041     * horizontally.
3042     * {@hide}
3043     */
3044    @ViewDebug.ExportedProperty(category = "scrolling")
3045    protected int mScrollX;
3046    /**
3047     * The offset, in pixels, by which the content of this view is scrolled
3048     * vertically.
3049     * {@hide}
3050     */
3051    @ViewDebug.ExportedProperty(category = "scrolling")
3052    protected int mScrollY;
3053
3054    /**
3055     * The left padding in pixels, that is the distance in pixels between the
3056     * left edge of this view and the left edge of its content.
3057     * {@hide}
3058     */
3059    @ViewDebug.ExportedProperty(category = "padding")
3060    protected int mPaddingLeft = 0;
3061    /**
3062     * The right padding in pixels, that is the distance in pixels between the
3063     * right edge of this view and the right edge of its content.
3064     * {@hide}
3065     */
3066    @ViewDebug.ExportedProperty(category = "padding")
3067    protected int mPaddingRight = 0;
3068    /**
3069     * The top padding in pixels, that is the distance in pixels between the
3070     * top edge of this view and the top edge of its content.
3071     * {@hide}
3072     */
3073    @ViewDebug.ExportedProperty(category = "padding")
3074    protected int mPaddingTop;
3075    /**
3076     * The bottom padding in pixels, that is the distance in pixels between the
3077     * bottom edge of this view and the bottom edge of its content.
3078     * {@hide}
3079     */
3080    @ViewDebug.ExportedProperty(category = "padding")
3081    protected int mPaddingBottom;
3082
3083    /**
3084     * The layout insets in pixels, that is the distance in pixels between the
3085     * visible edges of this view its bounds.
3086     */
3087    private Insets mLayoutInsets;
3088
3089    /**
3090     * Briefly describes the view and is primarily used for accessibility support.
3091     */
3092    private CharSequence mContentDescription;
3093
3094    /**
3095     * Specifies the id of a view for which this view serves as a label for
3096     * accessibility purposes.
3097     */
3098    private int mLabelForId = View.NO_ID;
3099
3100    /**
3101     * Predicate for matching labeled view id with its label for
3102     * accessibility purposes.
3103     */
3104    private MatchLabelForPredicate mMatchLabelForPredicate;
3105
3106    /**
3107     * Specifies a view before which this one is visited in accessibility traversal.
3108     */
3109    private int mAccessibilityTraversalBeforeId = NO_ID;
3110
3111    /**
3112     * Specifies a view after which this one is visited in accessibility traversal.
3113     */
3114    private int mAccessibilityTraversalAfterId = NO_ID;
3115
3116    /**
3117     * Predicate for matching a view by its id.
3118     */
3119    private MatchIdPredicate mMatchIdPredicate;
3120
3121    /**
3122     * Cache the paddingRight set by the user to append to the scrollbar's size.
3123     *
3124     * @hide
3125     */
3126    @ViewDebug.ExportedProperty(category = "padding")
3127    protected int mUserPaddingRight;
3128
3129    /**
3130     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3131     *
3132     * @hide
3133     */
3134    @ViewDebug.ExportedProperty(category = "padding")
3135    protected int mUserPaddingBottom;
3136
3137    /**
3138     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3139     *
3140     * @hide
3141     */
3142    @ViewDebug.ExportedProperty(category = "padding")
3143    protected int mUserPaddingLeft;
3144
3145    /**
3146     * Cache the paddingStart set by the user to append to the scrollbar's size.
3147     *
3148     */
3149    @ViewDebug.ExportedProperty(category = "padding")
3150    int mUserPaddingStart;
3151
3152    /**
3153     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3154     *
3155     */
3156    @ViewDebug.ExportedProperty(category = "padding")
3157    int mUserPaddingEnd;
3158
3159    /**
3160     * Cache initial left padding.
3161     *
3162     * @hide
3163     */
3164    int mUserPaddingLeftInitial;
3165
3166    /**
3167     * Cache initial right padding.
3168     *
3169     * @hide
3170     */
3171    int mUserPaddingRightInitial;
3172
3173    /**
3174     * Default undefined padding
3175     */
3176    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3177
3178    /**
3179     * Cache if a left padding has been defined
3180     */
3181    private boolean mLeftPaddingDefined = false;
3182
3183    /**
3184     * Cache if a right padding has been defined
3185     */
3186    private boolean mRightPaddingDefined = false;
3187
3188    /**
3189     * @hide
3190     */
3191    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3192    /**
3193     * @hide
3194     */
3195    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3196
3197    private LongSparseLongArray mMeasureCache;
3198
3199    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3200    private Drawable mBackground;
3201    private TintInfo mBackgroundTint;
3202
3203    /**
3204     * RenderNode used for backgrounds.
3205     * <p>
3206     * When non-null and valid, this is expected to contain an up-to-date copy
3207     * of the background drawable. It is cleared on temporary detach, and reset
3208     * on cleanup.
3209     */
3210    private RenderNode mBackgroundRenderNode;
3211
3212    private int mBackgroundResource;
3213    private boolean mBackgroundSizeChanged;
3214
3215    private String mTransitionName;
3216
3217    private static class TintInfo {
3218        ColorStateList mTintList;
3219        PorterDuff.Mode mTintMode;
3220        boolean mHasTintMode;
3221        boolean mHasTintList;
3222    }
3223
3224    static class ListenerInfo {
3225        /**
3226         * Listener used to dispatch focus change events.
3227         * This field should be made private, so it is hidden from the SDK.
3228         * {@hide}
3229         */
3230        protected OnFocusChangeListener mOnFocusChangeListener;
3231
3232        /**
3233         * Listeners for layout change events.
3234         */
3235        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3236
3237        protected OnScrollChangeListener mOnScrollChangeListener;
3238
3239        /**
3240         * Listeners for attach events.
3241         */
3242        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3243
3244        /**
3245         * Listener used to dispatch click events.
3246         * This field should be made private, so it is hidden from the SDK.
3247         * {@hide}
3248         */
3249        public OnClickListener mOnClickListener;
3250
3251        /**
3252         * Listener used to dispatch long click events.
3253         * This field should be made private, so it is hidden from the SDK.
3254         * {@hide}
3255         */
3256        protected OnLongClickListener mOnLongClickListener;
3257
3258        /**
3259         * Listener used to build the context menu.
3260         * This field should be made private, so it is hidden from the SDK.
3261         * {@hide}
3262         */
3263        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3264
3265        private OnKeyListener mOnKeyListener;
3266
3267        private OnTouchListener mOnTouchListener;
3268
3269        private OnHoverListener mOnHoverListener;
3270
3271        private OnGenericMotionListener mOnGenericMotionListener;
3272
3273        private OnDragListener mOnDragListener;
3274
3275        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3276
3277        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3278    }
3279
3280    ListenerInfo mListenerInfo;
3281
3282    /**
3283     * The application environment this view lives in.
3284     * This field should be made private, so it is hidden from the SDK.
3285     * {@hide}
3286     */
3287    @ViewDebug.ExportedProperty(deepExport = true)
3288    protected Context mContext;
3289
3290    private final Resources mResources;
3291
3292    private ScrollabilityCache mScrollCache;
3293
3294    private int[] mDrawableState = null;
3295
3296    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3297
3298    /**
3299     * Animator that automatically runs based on state changes.
3300     */
3301    private StateListAnimator mStateListAnimator;
3302
3303    /**
3304     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3305     * the user may specify which view to go to next.
3306     */
3307    private int mNextFocusLeftId = View.NO_ID;
3308
3309    /**
3310     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3311     * the user may specify which view to go to next.
3312     */
3313    private int mNextFocusRightId = View.NO_ID;
3314
3315    /**
3316     * When this view has focus and the next focus is {@link #FOCUS_UP},
3317     * the user may specify which view to go to next.
3318     */
3319    private int mNextFocusUpId = View.NO_ID;
3320
3321    /**
3322     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3323     * the user may specify which view to go to next.
3324     */
3325    private int mNextFocusDownId = View.NO_ID;
3326
3327    /**
3328     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3329     * the user may specify which view to go to next.
3330     */
3331    int mNextFocusForwardId = View.NO_ID;
3332
3333    private CheckForLongPress mPendingCheckForLongPress;
3334    private CheckForTap mPendingCheckForTap = null;
3335    private PerformClick mPerformClick;
3336    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3337
3338    private UnsetPressedState mUnsetPressedState;
3339
3340    /**
3341     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3342     * up event while a long press is invoked as soon as the long press duration is reached, so
3343     * a long press could be performed before the tap is checked, in which case the tap's action
3344     * should not be invoked.
3345     */
3346    private boolean mHasPerformedLongPress;
3347
3348    /**
3349     * The minimum height of the view. We'll try our best to have the height
3350     * of this view to at least this amount.
3351     */
3352    @ViewDebug.ExportedProperty(category = "measurement")
3353    private int mMinHeight;
3354
3355    /**
3356     * The minimum width of the view. We'll try our best to have the width
3357     * of this view to at least this amount.
3358     */
3359    @ViewDebug.ExportedProperty(category = "measurement")
3360    private int mMinWidth;
3361
3362    /**
3363     * The delegate to handle touch events that are physically in this view
3364     * but should be handled by another view.
3365     */
3366    private TouchDelegate mTouchDelegate = null;
3367
3368    /**
3369     * Solid color to use as a background when creating the drawing cache. Enables
3370     * the cache to use 16 bit bitmaps instead of 32 bit.
3371     */
3372    private int mDrawingCacheBackgroundColor = 0;
3373
3374    /**
3375     * Special tree observer used when mAttachInfo is null.
3376     */
3377    private ViewTreeObserver mFloatingTreeObserver;
3378
3379    /**
3380     * Cache the touch slop from the context that created the view.
3381     */
3382    private int mTouchSlop;
3383
3384    /**
3385     * Object that handles automatic animation of view properties.
3386     */
3387    private ViewPropertyAnimator mAnimator = null;
3388
3389    /**
3390     * Flag indicating that a drag can cross window boundaries.  When
3391     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3392     * with this flag set, all visible applications will be able to participate
3393     * in the drag operation and receive the dragged content.
3394     *
3395     * @hide
3396     */
3397    public static final int DRAG_FLAG_GLOBAL = 1;
3398
3399    /**
3400     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3401     */
3402    private float mVerticalScrollFactor;
3403
3404    /**
3405     * Position of the vertical scroll bar.
3406     */
3407    private int mVerticalScrollbarPosition;
3408
3409    /**
3410     * Position the scroll bar at the default position as determined by the system.
3411     */
3412    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3413
3414    /**
3415     * Position the scroll bar along the left edge.
3416     */
3417    public static final int SCROLLBAR_POSITION_LEFT = 1;
3418
3419    /**
3420     * Position the scroll bar along the right edge.
3421     */
3422    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3423
3424    /**
3425     * Indicates that the view does not have a layer.
3426     *
3427     * @see #getLayerType()
3428     * @see #setLayerType(int, android.graphics.Paint)
3429     * @see #LAYER_TYPE_SOFTWARE
3430     * @see #LAYER_TYPE_HARDWARE
3431     */
3432    public static final int LAYER_TYPE_NONE = 0;
3433
3434    /**
3435     * <p>Indicates that the view has a software layer. A software layer is backed
3436     * by a bitmap and causes the view to be rendered using Android's software
3437     * rendering pipeline, even if hardware acceleration is enabled.</p>
3438     *
3439     * <p>Software layers have various usages:</p>
3440     * <p>When the application is not using hardware acceleration, a software layer
3441     * is useful to apply a specific color filter and/or blending mode and/or
3442     * translucency to a view and all its children.</p>
3443     * <p>When the application is using hardware acceleration, a software layer
3444     * is useful to render drawing primitives not supported by the hardware
3445     * accelerated pipeline. It can also be used to cache a complex view tree
3446     * into a texture and reduce the complexity of drawing operations. For instance,
3447     * when animating a complex view tree with a translation, a software layer can
3448     * be used to render the view tree only once.</p>
3449     * <p>Software layers should be avoided when the affected view tree updates
3450     * often. Every update will require to re-render the software layer, which can
3451     * potentially be slow (particularly when hardware acceleration is turned on
3452     * since the layer will have to be uploaded into a hardware texture after every
3453     * update.)</p>
3454     *
3455     * @see #getLayerType()
3456     * @see #setLayerType(int, android.graphics.Paint)
3457     * @see #LAYER_TYPE_NONE
3458     * @see #LAYER_TYPE_HARDWARE
3459     */
3460    public static final int LAYER_TYPE_SOFTWARE = 1;
3461
3462    /**
3463     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3464     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3465     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3466     * rendering pipeline, but only if hardware acceleration is turned on for the
3467     * view hierarchy. When hardware acceleration is turned off, hardware layers
3468     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3469     *
3470     * <p>A hardware layer is useful to apply a specific color filter and/or
3471     * blending mode and/or translucency to a view and all its children.</p>
3472     * <p>A hardware layer can be used to cache a complex view tree into a
3473     * texture and reduce the complexity of drawing operations. For instance,
3474     * when animating a complex view tree with a translation, a hardware layer can
3475     * be used to render the view tree only once.</p>
3476     * <p>A hardware layer can also be used to increase the rendering quality when
3477     * rotation transformations are applied on a view. It can also be used to
3478     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3479     *
3480     * @see #getLayerType()
3481     * @see #setLayerType(int, android.graphics.Paint)
3482     * @see #LAYER_TYPE_NONE
3483     * @see #LAYER_TYPE_SOFTWARE
3484     */
3485    public static final int LAYER_TYPE_HARDWARE = 2;
3486
3487    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3488            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3489            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3490            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3491    })
3492    int mLayerType = LAYER_TYPE_NONE;
3493    Paint mLayerPaint;
3494
3495    /**
3496     * Set to true when drawing cache is enabled and cannot be created.
3497     *
3498     * @hide
3499     */
3500    public boolean mCachingFailed;
3501    private Bitmap mDrawingCache;
3502    private Bitmap mUnscaledDrawingCache;
3503
3504    /**
3505     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3506     * <p>
3507     * When non-null and valid, this is expected to contain an up-to-date copy
3508     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3509     * cleanup.
3510     */
3511    final RenderNode mRenderNode;
3512
3513    /**
3514     * Set to true when the view is sending hover accessibility events because it
3515     * is the innermost hovered view.
3516     */
3517    private boolean mSendingHoverAccessibilityEvents;
3518
3519    /**
3520     * Delegate for injecting accessibility functionality.
3521     */
3522    AccessibilityDelegate mAccessibilityDelegate;
3523
3524    /**
3525     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3526     * and add/remove objects to/from the overlay directly through the Overlay methods.
3527     */
3528    ViewOverlay mOverlay;
3529
3530    /**
3531     * The currently active parent view for receiving delegated nested scrolling events.
3532     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3533     * by {@link #stopNestedScroll()} at the same point where we clear
3534     * requestDisallowInterceptTouchEvent.
3535     */
3536    private ViewParent mNestedScrollingParent;
3537
3538    /**
3539     * Consistency verifier for debugging purposes.
3540     * @hide
3541     */
3542    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3543            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3544                    new InputEventConsistencyVerifier(this, 0) : null;
3545
3546    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3547
3548    private int[] mTempNestedScrollConsumed;
3549
3550    /**
3551     * An overlay is going to draw this View instead of being drawn as part of this
3552     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3553     * when this view is invalidated.
3554     */
3555    GhostView mGhostView;
3556
3557    /**
3558     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3559     * @hide
3560     */
3561    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3562    public String[] mAttributes;
3563
3564    /**
3565     * Maps a Resource id to its name.
3566     */
3567    private static SparseArray<String> mAttributeMap;
3568
3569    /**
3570     * Simple constructor to use when creating a view from code.
3571     *
3572     * @param context The Context the view is running in, through which it can
3573     *        access the current theme, resources, etc.
3574     */
3575    public View(Context context) {
3576        mContext = context;
3577        mResources = context != null ? context.getResources() : null;
3578        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3579        // Set some flags defaults
3580        mPrivateFlags2 =
3581                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3582                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3583                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3584                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3585                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3586                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3587        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3588        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3589        mUserPaddingStart = UNDEFINED_PADDING;
3590        mUserPaddingEnd = UNDEFINED_PADDING;
3591        mRenderNode = RenderNode.create(getClass().getName(), this);
3592
3593        if (!sCompatibilityDone && context != null) {
3594            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3595
3596            // Older apps may need this compatibility hack for measurement.
3597            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3598
3599            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3600            // of whether a layout was requested on that View.
3601            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3602
3603            sCompatibilityDone = true;
3604        }
3605    }
3606
3607    /**
3608     * Constructor that is called when inflating a view from XML. This is called
3609     * when a view is being constructed from an XML file, supplying attributes
3610     * that were specified in the XML file. This version uses a default style of
3611     * 0, so the only attribute values applied are those in the Context's Theme
3612     * and the given AttributeSet.
3613     *
3614     * <p>
3615     * The method onFinishInflate() will be called after all children have been
3616     * added.
3617     *
3618     * @param context The Context the view is running in, through which it can
3619     *        access the current theme, resources, etc.
3620     * @param attrs The attributes of the XML tag that is inflating the view.
3621     * @see #View(Context, AttributeSet, int)
3622     */
3623    public View(Context context, AttributeSet attrs) {
3624        this(context, attrs, 0);
3625    }
3626
3627    /**
3628     * Perform inflation from XML and apply a class-specific base style from a
3629     * theme attribute. This constructor of View allows subclasses to use their
3630     * own base style when they are inflating. For example, a Button class's
3631     * constructor would call this version of the super class constructor and
3632     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3633     * allows the theme's button style to modify all of the base view attributes
3634     * (in particular its background) as well as the Button class's attributes.
3635     *
3636     * @param context The Context the view is running in, through which it can
3637     *        access the current theme, resources, etc.
3638     * @param attrs The attributes of the XML tag that is inflating the view.
3639     * @param defStyleAttr An attribute in the current theme that contains a
3640     *        reference to a style resource that supplies default values for
3641     *        the view. Can be 0 to not look for defaults.
3642     * @see #View(Context, AttributeSet)
3643     */
3644    public View(Context context, AttributeSet attrs, int defStyleAttr) {
3645        this(context, attrs, defStyleAttr, 0);
3646    }
3647
3648    /**
3649     * Perform inflation from XML and apply a class-specific base style from a
3650     * theme attribute or style resource. This constructor of View allows
3651     * subclasses to use their own base style when they are inflating.
3652     * <p>
3653     * When determining the final value of a particular attribute, there are
3654     * four inputs that come into play:
3655     * <ol>
3656     * <li>Any attribute values in the given AttributeSet.
3657     * <li>The style resource specified in the AttributeSet (named "style").
3658     * <li>The default style specified by <var>defStyleAttr</var>.
3659     * <li>The default style specified by <var>defStyleRes</var>.
3660     * <li>The base values in this theme.
3661     * </ol>
3662     * <p>
3663     * Each of these inputs is considered in-order, with the first listed taking
3664     * precedence over the following ones. In other words, if in the
3665     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3666     * , then the button's text will <em>always</em> be black, regardless of
3667     * what is specified in any of the styles.
3668     *
3669     * @param context The Context the view is running in, through which it can
3670     *        access the current theme, resources, etc.
3671     * @param attrs The attributes of the XML tag that is inflating the view.
3672     * @param defStyleAttr An attribute in the current theme that contains a
3673     *        reference to a style resource that supplies default values for
3674     *        the view. Can be 0 to not look for defaults.
3675     * @param defStyleRes A resource identifier of a style resource that
3676     *        supplies default values for the view, used only if
3677     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3678     *        to not look for defaults.
3679     * @see #View(Context, AttributeSet, int)
3680     */
3681    public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3682        this(context);
3683
3684        final TypedArray a = context.obtainStyledAttributes(
3685                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3686
3687        if (mDebugViewAttributes) {
3688            saveAttributeData(attrs, a);
3689        }
3690
3691        Drawable background = null;
3692
3693        int leftPadding = -1;
3694        int topPadding = -1;
3695        int rightPadding = -1;
3696        int bottomPadding = -1;
3697        int startPadding = UNDEFINED_PADDING;
3698        int endPadding = UNDEFINED_PADDING;
3699
3700        int padding = -1;
3701
3702        int viewFlagValues = 0;
3703        int viewFlagMasks = 0;
3704
3705        boolean setScrollContainer = false;
3706
3707        int x = 0;
3708        int y = 0;
3709
3710        float tx = 0;
3711        float ty = 0;
3712        float tz = 0;
3713        float elevation = 0;
3714        float rotation = 0;
3715        float rotationX = 0;
3716        float rotationY = 0;
3717        float sx = 1f;
3718        float sy = 1f;
3719        boolean transformSet = false;
3720
3721        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3722        int overScrollMode = mOverScrollMode;
3723        boolean initializeScrollbars = false;
3724
3725        boolean startPaddingDefined = false;
3726        boolean endPaddingDefined = false;
3727        boolean leftPaddingDefined = false;
3728        boolean rightPaddingDefined = false;
3729
3730        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3731
3732        final int N = a.getIndexCount();
3733        for (int i = 0; i < N; i++) {
3734            int attr = a.getIndex(i);
3735            switch (attr) {
3736                case com.android.internal.R.styleable.View_background:
3737                    background = a.getDrawable(attr);
3738                    break;
3739                case com.android.internal.R.styleable.View_padding:
3740                    padding = a.getDimensionPixelSize(attr, -1);
3741                    mUserPaddingLeftInitial = padding;
3742                    mUserPaddingRightInitial = padding;
3743                    leftPaddingDefined = true;
3744                    rightPaddingDefined = true;
3745                    break;
3746                 case com.android.internal.R.styleable.View_paddingLeft:
3747                    leftPadding = a.getDimensionPixelSize(attr, -1);
3748                    mUserPaddingLeftInitial = leftPadding;
3749                    leftPaddingDefined = true;
3750                    break;
3751                case com.android.internal.R.styleable.View_paddingTop:
3752                    topPadding = a.getDimensionPixelSize(attr, -1);
3753                    break;
3754                case com.android.internal.R.styleable.View_paddingRight:
3755                    rightPadding = a.getDimensionPixelSize(attr, -1);
3756                    mUserPaddingRightInitial = rightPadding;
3757                    rightPaddingDefined = true;
3758                    break;
3759                case com.android.internal.R.styleable.View_paddingBottom:
3760                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3761                    break;
3762                case com.android.internal.R.styleable.View_paddingStart:
3763                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3764                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3765                    break;
3766                case com.android.internal.R.styleable.View_paddingEnd:
3767                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3768                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3769                    break;
3770                case com.android.internal.R.styleable.View_scrollX:
3771                    x = a.getDimensionPixelOffset(attr, 0);
3772                    break;
3773                case com.android.internal.R.styleable.View_scrollY:
3774                    y = a.getDimensionPixelOffset(attr, 0);
3775                    break;
3776                case com.android.internal.R.styleable.View_alpha:
3777                    setAlpha(a.getFloat(attr, 1f));
3778                    break;
3779                case com.android.internal.R.styleable.View_transformPivotX:
3780                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3781                    break;
3782                case com.android.internal.R.styleable.View_transformPivotY:
3783                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3784                    break;
3785                case com.android.internal.R.styleable.View_translationX:
3786                    tx = a.getDimensionPixelOffset(attr, 0);
3787                    transformSet = true;
3788                    break;
3789                case com.android.internal.R.styleable.View_translationY:
3790                    ty = a.getDimensionPixelOffset(attr, 0);
3791                    transformSet = true;
3792                    break;
3793                case com.android.internal.R.styleable.View_translationZ:
3794                    tz = a.getDimensionPixelOffset(attr, 0);
3795                    transformSet = true;
3796                    break;
3797                case com.android.internal.R.styleable.View_elevation:
3798                    elevation = a.getDimensionPixelOffset(attr, 0);
3799                    transformSet = true;
3800                    break;
3801                case com.android.internal.R.styleable.View_rotation:
3802                    rotation = a.getFloat(attr, 0);
3803                    transformSet = true;
3804                    break;
3805                case com.android.internal.R.styleable.View_rotationX:
3806                    rotationX = a.getFloat(attr, 0);
3807                    transformSet = true;
3808                    break;
3809                case com.android.internal.R.styleable.View_rotationY:
3810                    rotationY = a.getFloat(attr, 0);
3811                    transformSet = true;
3812                    break;
3813                case com.android.internal.R.styleable.View_scaleX:
3814                    sx = a.getFloat(attr, 1f);
3815                    transformSet = true;
3816                    break;
3817                case com.android.internal.R.styleable.View_scaleY:
3818                    sy = a.getFloat(attr, 1f);
3819                    transformSet = true;
3820                    break;
3821                case com.android.internal.R.styleable.View_id:
3822                    mID = a.getResourceId(attr, NO_ID);
3823                    break;
3824                case com.android.internal.R.styleable.View_tag:
3825                    mTag = a.getText(attr);
3826                    break;
3827                case com.android.internal.R.styleable.View_fitsSystemWindows:
3828                    if (a.getBoolean(attr, false)) {
3829                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3830                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3831                    }
3832                    break;
3833                case com.android.internal.R.styleable.View_focusable:
3834                    if (a.getBoolean(attr, false)) {
3835                        viewFlagValues |= FOCUSABLE;
3836                        viewFlagMasks |= FOCUSABLE_MASK;
3837                    }
3838                    break;
3839                case com.android.internal.R.styleable.View_focusableInTouchMode:
3840                    if (a.getBoolean(attr, false)) {
3841                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3842                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3843                    }
3844                    break;
3845                case com.android.internal.R.styleable.View_clickable:
3846                    if (a.getBoolean(attr, false)) {
3847                        viewFlagValues |= CLICKABLE;
3848                        viewFlagMasks |= CLICKABLE;
3849                    }
3850                    break;
3851                case com.android.internal.R.styleable.View_longClickable:
3852                    if (a.getBoolean(attr, false)) {
3853                        viewFlagValues |= LONG_CLICKABLE;
3854                        viewFlagMasks |= LONG_CLICKABLE;
3855                    }
3856                    break;
3857                case com.android.internal.R.styleable.View_saveEnabled:
3858                    if (!a.getBoolean(attr, true)) {
3859                        viewFlagValues |= SAVE_DISABLED;
3860                        viewFlagMasks |= SAVE_DISABLED_MASK;
3861                    }
3862                    break;
3863                case com.android.internal.R.styleable.View_duplicateParentState:
3864                    if (a.getBoolean(attr, false)) {
3865                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3866                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3867                    }
3868                    break;
3869                case com.android.internal.R.styleable.View_visibility:
3870                    final int visibility = a.getInt(attr, 0);
3871                    if (visibility != 0) {
3872                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3873                        viewFlagMasks |= VISIBILITY_MASK;
3874                    }
3875                    break;
3876                case com.android.internal.R.styleable.View_layoutDirection:
3877                    // Clear any layout direction flags (included resolved bits) already set
3878                    mPrivateFlags2 &=
3879                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3880                    // Set the layout direction flags depending on the value of the attribute
3881                    final int layoutDirection = a.getInt(attr, -1);
3882                    final int value = (layoutDirection != -1) ?
3883                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3884                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3885                    break;
3886                case com.android.internal.R.styleable.View_drawingCacheQuality:
3887                    final int cacheQuality = a.getInt(attr, 0);
3888                    if (cacheQuality != 0) {
3889                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3890                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3891                    }
3892                    break;
3893                case com.android.internal.R.styleable.View_contentDescription:
3894                    setContentDescription(a.getString(attr));
3895                    break;
3896                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
3897                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
3898                    break;
3899                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
3900                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
3901                    break;
3902                case com.android.internal.R.styleable.View_labelFor:
3903                    setLabelFor(a.getResourceId(attr, NO_ID));
3904                    break;
3905                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3906                    if (!a.getBoolean(attr, true)) {
3907                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3908                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3909                    }
3910                    break;
3911                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3912                    if (!a.getBoolean(attr, true)) {
3913                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3914                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3915                    }
3916                    break;
3917                case R.styleable.View_scrollbars:
3918                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3919                    if (scrollbars != SCROLLBARS_NONE) {
3920                        viewFlagValues |= scrollbars;
3921                        viewFlagMasks |= SCROLLBARS_MASK;
3922                        initializeScrollbars = true;
3923                    }
3924                    break;
3925                //noinspection deprecation
3926                case R.styleable.View_fadingEdge:
3927                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3928                        // Ignore the attribute starting with ICS
3929                        break;
3930                    }
3931                    // With builds < ICS, fall through and apply fading edges
3932                case R.styleable.View_requiresFadingEdge:
3933                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3934                    if (fadingEdge != FADING_EDGE_NONE) {
3935                        viewFlagValues |= fadingEdge;
3936                        viewFlagMasks |= FADING_EDGE_MASK;
3937                        initializeFadingEdgeInternal(a);
3938                    }
3939                    break;
3940                case R.styleable.View_scrollbarStyle:
3941                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3942                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3943                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3944                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3945                    }
3946                    break;
3947                case R.styleable.View_isScrollContainer:
3948                    setScrollContainer = true;
3949                    if (a.getBoolean(attr, false)) {
3950                        setScrollContainer(true);
3951                    }
3952                    break;
3953                case com.android.internal.R.styleable.View_keepScreenOn:
3954                    if (a.getBoolean(attr, false)) {
3955                        viewFlagValues |= KEEP_SCREEN_ON;
3956                        viewFlagMasks |= KEEP_SCREEN_ON;
3957                    }
3958                    break;
3959                case R.styleable.View_filterTouchesWhenObscured:
3960                    if (a.getBoolean(attr, false)) {
3961                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3962                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3963                    }
3964                    break;
3965                case R.styleable.View_nextFocusLeft:
3966                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3967                    break;
3968                case R.styleable.View_nextFocusRight:
3969                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3970                    break;
3971                case R.styleable.View_nextFocusUp:
3972                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3973                    break;
3974                case R.styleable.View_nextFocusDown:
3975                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3976                    break;
3977                case R.styleable.View_nextFocusForward:
3978                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3979                    break;
3980                case R.styleable.View_minWidth:
3981                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3982                    break;
3983                case R.styleable.View_minHeight:
3984                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3985                    break;
3986                case R.styleable.View_onClick:
3987                    if (context.isRestricted()) {
3988                        throw new IllegalStateException("The android:onClick attribute cannot "
3989                                + "be used within a restricted context");
3990                    }
3991
3992                    final String handlerName = a.getString(attr);
3993                    if (handlerName != null) {
3994                        setOnClickListener(new OnClickListener() {
3995                            private Method mHandler;
3996
3997                            public void onClick(View v) {
3998                                if (mHandler == null) {
3999                                    try {
4000                                        mHandler = getContext().getClass().getMethod(handlerName,
4001                                                View.class);
4002                                    } catch (NoSuchMethodException e) {
4003                                        int id = getId();
4004                                        String idText = id == NO_ID ? "" : " with id '"
4005                                                + getContext().getResources().getResourceEntryName(
4006                                                    id) + "'";
4007                                        throw new IllegalStateException("Could not find a method " +
4008                                                handlerName + "(View) in the activity "
4009                                                + getContext().getClass() + " for onClick handler"
4010                                                + " on view " + View.this.getClass() + idText, e);
4011                                    }
4012                                }
4013
4014                                try {
4015                                    mHandler.invoke(getContext(), View.this);
4016                                } catch (IllegalAccessException e) {
4017                                    throw new IllegalStateException("Could not execute non "
4018                                            + "public method of the activity", e);
4019                                } catch (InvocationTargetException e) {
4020                                    throw new IllegalStateException("Could not execute "
4021                                            + "method of the activity", e);
4022                                }
4023                            }
4024                        });
4025                    }
4026                    break;
4027                case R.styleable.View_overScrollMode:
4028                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4029                    break;
4030                case R.styleable.View_verticalScrollbarPosition:
4031                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4032                    break;
4033                case R.styleable.View_layerType:
4034                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4035                    break;
4036                case R.styleable.View_textDirection:
4037                    // Clear any text direction flag already set
4038                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4039                    // Set the text direction flags depending on the value of the attribute
4040                    final int textDirection = a.getInt(attr, -1);
4041                    if (textDirection != -1) {
4042                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4043                    }
4044                    break;
4045                case R.styleable.View_textAlignment:
4046                    // Clear any text alignment flag already set
4047                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4048                    // Set the text alignment flag depending on the value of the attribute
4049                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4050                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4051                    break;
4052                case R.styleable.View_importantForAccessibility:
4053                    setImportantForAccessibility(a.getInt(attr,
4054                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4055                    break;
4056                case R.styleable.View_accessibilityLiveRegion:
4057                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4058                    break;
4059                case R.styleable.View_transitionName:
4060                    setTransitionName(a.getString(attr));
4061                    break;
4062                case R.styleable.View_nestedScrollingEnabled:
4063                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4064                    break;
4065                case R.styleable.View_stateListAnimator:
4066                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4067                            a.getResourceId(attr, 0)));
4068                    break;
4069                case R.styleable.View_backgroundTint:
4070                    // This will get applied later during setBackground().
4071                    if (mBackgroundTint == null) {
4072                        mBackgroundTint = new TintInfo();
4073                    }
4074                    mBackgroundTint.mTintList = a.getColorStateList(
4075                            R.styleable.View_backgroundTint);
4076                    mBackgroundTint.mHasTintList = true;
4077                    break;
4078                case R.styleable.View_backgroundTintMode:
4079                    // This will get applied later during setBackground().
4080                    if (mBackgroundTint == null) {
4081                        mBackgroundTint = new TintInfo();
4082                    }
4083                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4084                            R.styleable.View_backgroundTintMode, -1), null);
4085                    mBackgroundTint.mHasTintMode = true;
4086                    break;
4087                case R.styleable.View_outlineProvider:
4088                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4089                            PROVIDER_BACKGROUND));
4090                    break;
4091            }
4092        }
4093
4094        setOverScrollMode(overScrollMode);
4095
4096        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4097        // the resolved layout direction). Those cached values will be used later during padding
4098        // resolution.
4099        mUserPaddingStart = startPadding;
4100        mUserPaddingEnd = endPadding;
4101
4102        if (background != null) {
4103            setBackground(background);
4104        }
4105
4106        // setBackground above will record that padding is currently provided by the background.
4107        // If we have padding specified via xml, record that here instead and use it.
4108        mLeftPaddingDefined = leftPaddingDefined;
4109        mRightPaddingDefined = rightPaddingDefined;
4110
4111        if (padding >= 0) {
4112            leftPadding = padding;
4113            topPadding = padding;
4114            rightPadding = padding;
4115            bottomPadding = padding;
4116            mUserPaddingLeftInitial = padding;
4117            mUserPaddingRightInitial = padding;
4118        }
4119
4120        if (isRtlCompatibilityMode()) {
4121            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4122            // left / right padding are used if defined (meaning here nothing to do). If they are not
4123            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4124            // start / end and resolve them as left / right (layout direction is not taken into account).
4125            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4126            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4127            // defined.
4128            if (!mLeftPaddingDefined && startPaddingDefined) {
4129                leftPadding = startPadding;
4130            }
4131            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4132            if (!mRightPaddingDefined && endPaddingDefined) {
4133                rightPadding = endPadding;
4134            }
4135            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4136        } else {
4137            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4138            // values defined. Otherwise, left /right values are used.
4139            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4140            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4141            // defined.
4142            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4143
4144            if (mLeftPaddingDefined && !hasRelativePadding) {
4145                mUserPaddingLeftInitial = leftPadding;
4146            }
4147            if (mRightPaddingDefined && !hasRelativePadding) {
4148                mUserPaddingRightInitial = rightPadding;
4149            }
4150        }
4151
4152        internalSetPadding(
4153                mUserPaddingLeftInitial,
4154                topPadding >= 0 ? topPadding : mPaddingTop,
4155                mUserPaddingRightInitial,
4156                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4157
4158        if (viewFlagMasks != 0) {
4159            setFlags(viewFlagValues, viewFlagMasks);
4160        }
4161
4162        if (initializeScrollbars) {
4163            initializeScrollbarsInternal(a);
4164        }
4165
4166        a.recycle();
4167
4168        // Needs to be called after mViewFlags is set
4169        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4170            recomputePadding();
4171        }
4172
4173        if (x != 0 || y != 0) {
4174            scrollTo(x, y);
4175        }
4176
4177        if (transformSet) {
4178            setTranslationX(tx);
4179            setTranslationY(ty);
4180            setTranslationZ(tz);
4181            setElevation(elevation);
4182            setRotation(rotation);
4183            setRotationX(rotationX);
4184            setRotationY(rotationY);
4185            setScaleX(sx);
4186            setScaleY(sy);
4187        }
4188
4189        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4190            setScrollContainer(true);
4191        }
4192
4193        computeOpaqueFlags();
4194    }
4195
4196    /**
4197     * Non-public constructor for use in testing
4198     */
4199    View() {
4200        mResources = null;
4201        mRenderNode = RenderNode.create(getClass().getName(), this);
4202    }
4203
4204    private static SparseArray<String> getAttributeMap() {
4205        if (mAttributeMap == null) {
4206            mAttributeMap = new SparseArray<String>();
4207        }
4208        return mAttributeMap;
4209    }
4210
4211    private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4212        int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4213        mAttributes = new String[length];
4214
4215        int i = 0;
4216        if (attrs != null) {
4217            for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4218                mAttributes[i] = attrs.getAttributeName(i);
4219                mAttributes[i + 1] = attrs.getAttributeValue(i);
4220            }
4221
4222        }
4223
4224        SparseArray<String> attributeMap = getAttributeMap();
4225        for (int j = 0; j < a.length(); ++j) {
4226            if (a.hasValue(j)) {
4227                try {
4228                    int resourceId = a.getResourceId(j, 0);
4229                    if (resourceId == 0) {
4230                        continue;
4231                    }
4232
4233                    String resourceName = attributeMap.get(resourceId);
4234                    if (resourceName == null) {
4235                        resourceName = a.getResources().getResourceName(resourceId);
4236                        attributeMap.put(resourceId, resourceName);
4237                    }
4238
4239                    mAttributes[i] = resourceName;
4240                    mAttributes[i + 1] = a.getText(j).toString();
4241                    i += 2;
4242                } catch (Resources.NotFoundException e) {
4243                    // if we can't get the resource name, we just ignore it
4244                }
4245            }
4246        }
4247    }
4248
4249    public String toString() {
4250        StringBuilder out = new StringBuilder(128);
4251        out.append(getClass().getName());
4252        out.append('{');
4253        out.append(Integer.toHexString(System.identityHashCode(this)));
4254        out.append(' ');
4255        switch (mViewFlags&VISIBILITY_MASK) {
4256            case VISIBLE: out.append('V'); break;
4257            case INVISIBLE: out.append('I'); break;
4258            case GONE: out.append('G'); break;
4259            default: out.append('.'); break;
4260        }
4261        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4262        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4263        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4264        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4265        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4266        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4267        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4268        out.append(' ');
4269        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4270        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4271        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4272        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4273            out.append('p');
4274        } else {
4275            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4276        }
4277        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4278        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4279        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4280        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4281        out.append(' ');
4282        out.append(mLeft);
4283        out.append(',');
4284        out.append(mTop);
4285        out.append('-');
4286        out.append(mRight);
4287        out.append(',');
4288        out.append(mBottom);
4289        final int id = getId();
4290        if (id != NO_ID) {
4291            out.append(" #");
4292            out.append(Integer.toHexString(id));
4293            final Resources r = mResources;
4294            if (Resources.resourceHasPackage(id) && r != null) {
4295                try {
4296                    String pkgname;
4297                    switch (id&0xff000000) {
4298                        case 0x7f000000:
4299                            pkgname="app";
4300                            break;
4301                        case 0x01000000:
4302                            pkgname="android";
4303                            break;
4304                        default:
4305                            pkgname = r.getResourcePackageName(id);
4306                            break;
4307                    }
4308                    String typename = r.getResourceTypeName(id);
4309                    String entryname = r.getResourceEntryName(id);
4310                    out.append(" ");
4311                    out.append(pkgname);
4312                    out.append(":");
4313                    out.append(typename);
4314                    out.append("/");
4315                    out.append(entryname);
4316                } catch (Resources.NotFoundException e) {
4317                }
4318            }
4319        }
4320        out.append("}");
4321        return out.toString();
4322    }
4323
4324    /**
4325     * <p>
4326     * Initializes the fading edges from a given set of styled attributes. This
4327     * method should be called by subclasses that need fading edges and when an
4328     * instance of these subclasses is created programmatically rather than
4329     * being inflated from XML. This method is automatically called when the XML
4330     * is inflated.
4331     * </p>
4332     *
4333     * @param a the styled attributes set to initialize the fading edges from
4334     *
4335     * @removed
4336     */
4337    protected void initializeFadingEdge(TypedArray a) {
4338        // This method probably shouldn't have been included in the SDK to begin with.
4339        // It relies on 'a' having been initialized using an attribute filter array that is
4340        // not publicly available to the SDK. The old method has been renamed
4341        // to initializeFadingEdgeInternal and hidden for framework use only;
4342        // this one initializes using defaults to make it safe to call for apps.
4343
4344        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4345
4346        initializeFadingEdgeInternal(arr);
4347
4348        arr.recycle();
4349    }
4350
4351    /**
4352     * <p>
4353     * Initializes the fading edges from a given set of styled attributes. This
4354     * method should be called by subclasses that need fading edges and when an
4355     * instance of these subclasses is created programmatically rather than
4356     * being inflated from XML. This method is automatically called when the XML
4357     * is inflated.
4358     * </p>
4359     *
4360     * @param a the styled attributes set to initialize the fading edges from
4361     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4362     */
4363    protected void initializeFadingEdgeInternal(TypedArray a) {
4364        initScrollCache();
4365
4366        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4367                R.styleable.View_fadingEdgeLength,
4368                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4369    }
4370
4371    /**
4372     * Returns the size of the vertical faded edges used to indicate that more
4373     * content in this view is visible.
4374     *
4375     * @return The size in pixels of the vertical faded edge or 0 if vertical
4376     *         faded edges are not enabled for this view.
4377     * @attr ref android.R.styleable#View_fadingEdgeLength
4378     */
4379    public int getVerticalFadingEdgeLength() {
4380        if (isVerticalFadingEdgeEnabled()) {
4381            ScrollabilityCache cache = mScrollCache;
4382            if (cache != null) {
4383                return cache.fadingEdgeLength;
4384            }
4385        }
4386        return 0;
4387    }
4388
4389    /**
4390     * Set the size of the faded edge used to indicate that more content in this
4391     * view is available.  Will not change whether the fading edge is enabled; use
4392     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4393     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4394     * for the vertical or horizontal fading edges.
4395     *
4396     * @param length The size in pixels of the faded edge used to indicate that more
4397     *        content in this view is visible.
4398     */
4399    public void setFadingEdgeLength(int length) {
4400        initScrollCache();
4401        mScrollCache.fadingEdgeLength = length;
4402    }
4403
4404    /**
4405     * Returns the size of the horizontal faded edges used to indicate that more
4406     * content in this view is visible.
4407     *
4408     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4409     *         faded edges are not enabled for this view.
4410     * @attr ref android.R.styleable#View_fadingEdgeLength
4411     */
4412    public int getHorizontalFadingEdgeLength() {
4413        if (isHorizontalFadingEdgeEnabled()) {
4414            ScrollabilityCache cache = mScrollCache;
4415            if (cache != null) {
4416                return cache.fadingEdgeLength;
4417            }
4418        }
4419        return 0;
4420    }
4421
4422    /**
4423     * Returns the width of the vertical scrollbar.
4424     *
4425     * @return The width in pixels of the vertical scrollbar or 0 if there
4426     *         is no vertical scrollbar.
4427     */
4428    public int getVerticalScrollbarWidth() {
4429        ScrollabilityCache cache = mScrollCache;
4430        if (cache != null) {
4431            ScrollBarDrawable scrollBar = cache.scrollBar;
4432            if (scrollBar != null) {
4433                int size = scrollBar.getSize(true);
4434                if (size <= 0) {
4435                    size = cache.scrollBarSize;
4436                }
4437                return size;
4438            }
4439            return 0;
4440        }
4441        return 0;
4442    }
4443
4444    /**
4445     * Returns the height of the horizontal scrollbar.
4446     *
4447     * @return The height in pixels of the horizontal scrollbar or 0 if
4448     *         there is no horizontal scrollbar.
4449     */
4450    protected int getHorizontalScrollbarHeight() {
4451        ScrollabilityCache cache = mScrollCache;
4452        if (cache != null) {
4453            ScrollBarDrawable scrollBar = cache.scrollBar;
4454            if (scrollBar != null) {
4455                int size = scrollBar.getSize(false);
4456                if (size <= 0) {
4457                    size = cache.scrollBarSize;
4458                }
4459                return size;
4460            }
4461            return 0;
4462        }
4463        return 0;
4464    }
4465
4466    /**
4467     * <p>
4468     * Initializes the scrollbars from a given set of styled attributes. This
4469     * method should be called by subclasses that need scrollbars and when an
4470     * instance of these subclasses is created programmatically rather than
4471     * being inflated from XML. This method is automatically called when the XML
4472     * is inflated.
4473     * </p>
4474     *
4475     * @param a the styled attributes set to initialize the scrollbars from
4476     *
4477     * @removed
4478     */
4479    protected void initializeScrollbars(TypedArray a) {
4480        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4481        // using the View filter array which is not available to the SDK. As such, internal
4482        // framework usage now uses initializeScrollbarsInternal and we grab a default
4483        // TypedArray with the right filter instead here.
4484        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4485
4486        initializeScrollbarsInternal(arr);
4487
4488        // We ignored the method parameter. Recycle the one we actually did use.
4489        arr.recycle();
4490    }
4491
4492    /**
4493     * <p>
4494     * Initializes the scrollbars from a given set of styled attributes. This
4495     * method should be called by subclasses that need scrollbars and when an
4496     * instance of these subclasses is created programmatically rather than
4497     * being inflated from XML. This method is automatically called when the XML
4498     * is inflated.
4499     * </p>
4500     *
4501     * @param a the styled attributes set to initialize the scrollbars from
4502     * @hide
4503     */
4504    protected void initializeScrollbarsInternal(TypedArray a) {
4505        initScrollCache();
4506
4507        final ScrollabilityCache scrollabilityCache = mScrollCache;
4508
4509        if (scrollabilityCache.scrollBar == null) {
4510            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4511        }
4512
4513        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4514
4515        if (!fadeScrollbars) {
4516            scrollabilityCache.state = ScrollabilityCache.ON;
4517        }
4518        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4519
4520
4521        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4522                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4523                        .getScrollBarFadeDuration());
4524        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4525                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4526                ViewConfiguration.getScrollDefaultDelay());
4527
4528
4529        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4530                com.android.internal.R.styleable.View_scrollbarSize,
4531                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4532
4533        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4534        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4535
4536        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4537        if (thumb != null) {
4538            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4539        }
4540
4541        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4542                false);
4543        if (alwaysDraw) {
4544            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4545        }
4546
4547        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4548        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4549
4550        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4551        if (thumb != null) {
4552            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4553        }
4554
4555        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4556                false);
4557        if (alwaysDraw) {
4558            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4559        }
4560
4561        // Apply layout direction to the new Drawables if needed
4562        final int layoutDirection = getLayoutDirection();
4563        if (track != null) {
4564            track.setLayoutDirection(layoutDirection);
4565        }
4566        if (thumb != null) {
4567            thumb.setLayoutDirection(layoutDirection);
4568        }
4569
4570        // Re-apply user/background padding so that scrollbar(s) get added
4571        resolvePadding();
4572    }
4573
4574    /**
4575     * <p>
4576     * Initalizes the scrollability cache if necessary.
4577     * </p>
4578     */
4579    private void initScrollCache() {
4580        if (mScrollCache == null) {
4581            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4582        }
4583    }
4584
4585    private ScrollabilityCache getScrollCache() {
4586        initScrollCache();
4587        return mScrollCache;
4588    }
4589
4590    /**
4591     * Set the position of the vertical scroll bar. Should be one of
4592     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4593     * {@link #SCROLLBAR_POSITION_RIGHT}.
4594     *
4595     * @param position Where the vertical scroll bar should be positioned.
4596     */
4597    public void setVerticalScrollbarPosition(int position) {
4598        if (mVerticalScrollbarPosition != position) {
4599            mVerticalScrollbarPosition = position;
4600            computeOpaqueFlags();
4601            resolvePadding();
4602        }
4603    }
4604
4605    /**
4606     * @return The position where the vertical scroll bar will show, if applicable.
4607     * @see #setVerticalScrollbarPosition(int)
4608     */
4609    public int getVerticalScrollbarPosition() {
4610        return mVerticalScrollbarPosition;
4611    }
4612
4613    ListenerInfo getListenerInfo() {
4614        if (mListenerInfo != null) {
4615            return mListenerInfo;
4616        }
4617        mListenerInfo = new ListenerInfo();
4618        return mListenerInfo;
4619    }
4620
4621    /**
4622     * Register a callback to be invoked when the scroll position of this view
4623     * changed.
4624     *
4625     * @param l The callback that will run.
4626     * @hide Only used internally.
4627     */
4628    public void setOnScrollChangeListener(OnScrollChangeListener l) {
4629        getListenerInfo().mOnScrollChangeListener = l;
4630    }
4631
4632    /**
4633     * Register a callback to be invoked when focus of this view changed.
4634     *
4635     * @param l The callback that will run.
4636     */
4637    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4638        getListenerInfo().mOnFocusChangeListener = l;
4639    }
4640
4641    /**
4642     * Add a listener that will be called when the bounds of the view change due to
4643     * layout processing.
4644     *
4645     * @param listener The listener that will be called when layout bounds change.
4646     */
4647    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4648        ListenerInfo li = getListenerInfo();
4649        if (li.mOnLayoutChangeListeners == null) {
4650            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4651        }
4652        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4653            li.mOnLayoutChangeListeners.add(listener);
4654        }
4655    }
4656
4657    /**
4658     * Remove a listener for layout changes.
4659     *
4660     * @param listener The listener for layout bounds change.
4661     */
4662    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4663        ListenerInfo li = mListenerInfo;
4664        if (li == null || li.mOnLayoutChangeListeners == null) {
4665            return;
4666        }
4667        li.mOnLayoutChangeListeners.remove(listener);
4668    }
4669
4670    /**
4671     * Add a listener for attach state changes.
4672     *
4673     * This listener will be called whenever this view is attached or detached
4674     * from a window. Remove the listener using
4675     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4676     *
4677     * @param listener Listener to attach
4678     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4679     */
4680    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4681        ListenerInfo li = getListenerInfo();
4682        if (li.mOnAttachStateChangeListeners == null) {
4683            li.mOnAttachStateChangeListeners
4684                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4685        }
4686        li.mOnAttachStateChangeListeners.add(listener);
4687    }
4688
4689    /**
4690     * Remove a listener for attach state changes. The listener will receive no further
4691     * notification of window attach/detach events.
4692     *
4693     * @param listener Listener to remove
4694     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4695     */
4696    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4697        ListenerInfo li = mListenerInfo;
4698        if (li == null || li.mOnAttachStateChangeListeners == null) {
4699            return;
4700        }
4701        li.mOnAttachStateChangeListeners.remove(listener);
4702    }
4703
4704    /**
4705     * Returns the focus-change callback registered for this view.
4706     *
4707     * @return The callback, or null if one is not registered.
4708     */
4709    public OnFocusChangeListener getOnFocusChangeListener() {
4710        ListenerInfo li = mListenerInfo;
4711        return li != null ? li.mOnFocusChangeListener : null;
4712    }
4713
4714    /**
4715     * Register a callback to be invoked when this view is clicked. If this view is not
4716     * clickable, it becomes clickable.
4717     *
4718     * @param l The callback that will run
4719     *
4720     * @see #setClickable(boolean)
4721     */
4722    public void setOnClickListener(OnClickListener l) {
4723        if (!isClickable()) {
4724            setClickable(true);
4725        }
4726        getListenerInfo().mOnClickListener = l;
4727    }
4728
4729    /**
4730     * Return whether this view has an attached OnClickListener.  Returns
4731     * true if there is a listener, false if there is none.
4732     */
4733    public boolean hasOnClickListeners() {
4734        ListenerInfo li = mListenerInfo;
4735        return (li != null && li.mOnClickListener != null);
4736    }
4737
4738    /**
4739     * Register a callback to be invoked when this view is clicked and held. If this view is not
4740     * long clickable, it becomes long clickable.
4741     *
4742     * @param l The callback that will run
4743     *
4744     * @see #setLongClickable(boolean)
4745     */
4746    public void setOnLongClickListener(OnLongClickListener l) {
4747        if (!isLongClickable()) {
4748            setLongClickable(true);
4749        }
4750        getListenerInfo().mOnLongClickListener = l;
4751    }
4752
4753    /**
4754     * Register a callback to be invoked when the context menu for this view is
4755     * being built. If this view is not long clickable, it becomes long clickable.
4756     *
4757     * @param l The callback that will run
4758     *
4759     */
4760    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4761        if (!isLongClickable()) {
4762            setLongClickable(true);
4763        }
4764        getListenerInfo().mOnCreateContextMenuListener = l;
4765    }
4766
4767    /**
4768     * Call this view's OnClickListener, if it is defined.  Performs all normal
4769     * actions associated with clicking: reporting accessibility event, playing
4770     * a sound, etc.
4771     *
4772     * @return True there was an assigned OnClickListener that was called, false
4773     *         otherwise is returned.
4774     */
4775    public boolean performClick() {
4776        final boolean result;
4777        final ListenerInfo li = mListenerInfo;
4778        if (li != null && li.mOnClickListener != null) {
4779            playSoundEffect(SoundEffectConstants.CLICK);
4780            li.mOnClickListener.onClick(this);
4781            result = true;
4782        } else {
4783            result = false;
4784        }
4785
4786        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4787        return result;
4788    }
4789
4790    /**
4791     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4792     * this only calls the listener, and does not do any associated clicking
4793     * actions like reporting an accessibility event.
4794     *
4795     * @return True there was an assigned OnClickListener that was called, false
4796     *         otherwise is returned.
4797     */
4798    public boolean callOnClick() {
4799        ListenerInfo li = mListenerInfo;
4800        if (li != null && li.mOnClickListener != null) {
4801            li.mOnClickListener.onClick(this);
4802            return true;
4803        }
4804        return false;
4805    }
4806
4807    /**
4808     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4809     * OnLongClickListener did not consume the event.
4810     *
4811     * @return True if one of the above receivers consumed the event, false otherwise.
4812     */
4813    public boolean performLongClick() {
4814        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4815
4816        boolean handled = false;
4817        ListenerInfo li = mListenerInfo;
4818        if (li != null && li.mOnLongClickListener != null) {
4819            handled = li.mOnLongClickListener.onLongClick(View.this);
4820        }
4821        if (!handled) {
4822            handled = showContextMenu();
4823        }
4824        if (handled) {
4825            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4826        }
4827        return handled;
4828    }
4829
4830    /**
4831     * Performs button-related actions during a touch down event.
4832     *
4833     * @param event The event.
4834     * @return True if the down was consumed.
4835     *
4836     * @hide
4837     */
4838    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4839        if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4840            if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4841                return true;
4842            }
4843        }
4844        return false;
4845    }
4846
4847    /**
4848     * Bring up the context menu for this view.
4849     *
4850     * @return Whether a context menu was displayed.
4851     */
4852    public boolean showContextMenu() {
4853        return getParent().showContextMenuForChild(this);
4854    }
4855
4856    /**
4857     * Bring up the context menu for this view, referring to the item under the specified point.
4858     *
4859     * @param x The referenced x coordinate.
4860     * @param y The referenced y coordinate.
4861     * @param metaState The keyboard modifiers that were pressed.
4862     * @return Whether a context menu was displayed.
4863     *
4864     * @hide
4865     */
4866    public boolean showContextMenu(float x, float y, int metaState) {
4867        return showContextMenu();
4868    }
4869
4870    /**
4871     * Start an action mode.
4872     *
4873     * @param callback Callback that will control the lifecycle of the action mode
4874     * @return The new action mode if it is started, null otherwise
4875     *
4876     * @see ActionMode
4877     */
4878    public ActionMode startActionMode(ActionMode.Callback callback) {
4879        ViewParent parent = getParent();
4880        if (parent == null) return null;
4881        return parent.startActionModeForChild(this, callback);
4882    }
4883
4884    /**
4885     * Register a callback to be invoked when a hardware key is pressed in this view.
4886     * Key presses in software input methods will generally not trigger the methods of
4887     * this listener.
4888     * @param l the key listener to attach to this view
4889     */
4890    public void setOnKeyListener(OnKeyListener l) {
4891        getListenerInfo().mOnKeyListener = l;
4892    }
4893
4894    /**
4895     * Register a callback to be invoked when a touch event is sent to this view.
4896     * @param l the touch listener to attach to this view
4897     */
4898    public void setOnTouchListener(OnTouchListener l) {
4899        getListenerInfo().mOnTouchListener = l;
4900    }
4901
4902    /**
4903     * Register a callback to be invoked when a generic motion event is sent to this view.
4904     * @param l the generic motion listener to attach to this view
4905     */
4906    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4907        getListenerInfo().mOnGenericMotionListener = l;
4908    }
4909
4910    /**
4911     * Register a callback to be invoked when a hover event is sent to this view.
4912     * @param l the hover listener to attach to this view
4913     */
4914    public void setOnHoverListener(OnHoverListener l) {
4915        getListenerInfo().mOnHoverListener = l;
4916    }
4917
4918    /**
4919     * Register a drag event listener callback object for this View. The parameter is
4920     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4921     * View, the system calls the
4922     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4923     * @param l An implementation of {@link android.view.View.OnDragListener}.
4924     */
4925    public void setOnDragListener(OnDragListener l) {
4926        getListenerInfo().mOnDragListener = l;
4927    }
4928
4929    /**
4930     * Give this view focus. This will cause
4931     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4932     *
4933     * Note: this does not check whether this {@link View} should get focus, it just
4934     * gives it focus no matter what.  It should only be called internally by framework
4935     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4936     *
4937     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4938     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4939     *        focus moved when requestFocus() is called. It may not always
4940     *        apply, in which case use the default View.FOCUS_DOWN.
4941     * @param previouslyFocusedRect The rectangle of the view that had focus
4942     *        prior in this View's coordinate system.
4943     */
4944    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4945        if (DBG) {
4946            System.out.println(this + " requestFocus()");
4947        }
4948
4949        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4950            mPrivateFlags |= PFLAG_FOCUSED;
4951
4952            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4953
4954            if (mParent != null) {
4955                mParent.requestChildFocus(this, this);
4956            }
4957
4958            if (mAttachInfo != null) {
4959                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4960            }
4961
4962            onFocusChanged(true, direction, previouslyFocusedRect);
4963            refreshDrawableState();
4964        }
4965    }
4966
4967    /**
4968     * Populates <code>outRect</code> with the hotspot bounds. By default,
4969     * the hotspot bounds are identical to the screen bounds.
4970     *
4971     * @param outRect rect to populate with hotspot bounds
4972     * @hide Only for internal use by views and widgets.
4973     */
4974    public void getHotspotBounds(Rect outRect) {
4975        final Drawable background = getBackground();
4976        if (background != null) {
4977            background.getHotspotBounds(outRect);
4978        } else {
4979            getBoundsOnScreen(outRect);
4980        }
4981    }
4982
4983    /**
4984     * Request that a rectangle of this view be visible on the screen,
4985     * scrolling if necessary just enough.
4986     *
4987     * <p>A View should call this if it maintains some notion of which part
4988     * of its content is interesting.  For example, a text editing view
4989     * should call this when its cursor moves.
4990     *
4991     * @param rectangle The rectangle.
4992     * @return Whether any parent scrolled.
4993     */
4994    public boolean requestRectangleOnScreen(Rect rectangle) {
4995        return requestRectangleOnScreen(rectangle, false);
4996    }
4997
4998    /**
4999     * Request that a rectangle of this view be visible on the screen,
5000     * scrolling if necessary just enough.
5001     *
5002     * <p>A View should call this if it maintains some notion of which part
5003     * of its content is interesting.  For example, a text editing view
5004     * should call this when its cursor moves.
5005     *
5006     * <p>When <code>immediate</code> is set to true, scrolling will not be
5007     * animated.
5008     *
5009     * @param rectangle The rectangle.
5010     * @param immediate True to forbid animated scrolling, false otherwise
5011     * @return Whether any parent scrolled.
5012     */
5013    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5014        if (mParent == null) {
5015            return false;
5016        }
5017
5018        View child = this;
5019
5020        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5021        position.set(rectangle);
5022
5023        ViewParent parent = mParent;
5024        boolean scrolled = false;
5025        while (parent != null) {
5026            rectangle.set((int) position.left, (int) position.top,
5027                    (int) position.right, (int) position.bottom);
5028
5029            scrolled |= parent.requestChildRectangleOnScreen(child,
5030                    rectangle, immediate);
5031
5032            if (!child.hasIdentityMatrix()) {
5033                child.getMatrix().mapRect(position);
5034            }
5035
5036            position.offset(child.mLeft, child.mTop);
5037
5038            if (!(parent instanceof View)) {
5039                break;
5040            }
5041
5042            View parentView = (View) parent;
5043
5044            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5045
5046            child = parentView;
5047            parent = child.getParent();
5048        }
5049
5050        return scrolled;
5051    }
5052
5053    /**
5054     * Called when this view wants to give up focus. If focus is cleared
5055     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5056     * <p>
5057     * <strong>Note:</strong> When a View clears focus the framework is trying
5058     * to give focus to the first focusable View from the top. Hence, if this
5059     * View is the first from the top that can take focus, then all callbacks
5060     * related to clearing focus will be invoked after which the framework will
5061     * give focus to this view.
5062     * </p>
5063     */
5064    public void clearFocus() {
5065        if (DBG) {
5066            System.out.println(this + " clearFocus()");
5067        }
5068
5069        clearFocusInternal(null, true, true);
5070    }
5071
5072    /**
5073     * Clears focus from the view, optionally propagating the change up through
5074     * the parent hierarchy and requesting that the root view place new focus.
5075     *
5076     * @param propagate whether to propagate the change up through the parent
5077     *            hierarchy
5078     * @param refocus when propagate is true, specifies whether to request the
5079     *            root view place new focus
5080     */
5081    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5082        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5083            mPrivateFlags &= ~PFLAG_FOCUSED;
5084
5085            if (propagate && mParent != null) {
5086                mParent.clearChildFocus(this);
5087            }
5088
5089            onFocusChanged(false, 0, null);
5090            refreshDrawableState();
5091
5092            if (propagate && (!refocus || !rootViewRequestFocus())) {
5093                notifyGlobalFocusCleared(this);
5094            }
5095        }
5096    }
5097
5098    void notifyGlobalFocusCleared(View oldFocus) {
5099        if (oldFocus != null && mAttachInfo != null) {
5100            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5101        }
5102    }
5103
5104    boolean rootViewRequestFocus() {
5105        final View root = getRootView();
5106        return root != null && root.requestFocus();
5107    }
5108
5109    /**
5110     * Called internally by the view system when a new view is getting focus.
5111     * This is what clears the old focus.
5112     * <p>
5113     * <b>NOTE:</b> The parent view's focused child must be updated manually
5114     * after calling this method. Otherwise, the view hierarchy may be left in
5115     * an inconstent state.
5116     */
5117    void unFocus(View focused) {
5118        if (DBG) {
5119            System.out.println(this + " unFocus()");
5120        }
5121
5122        clearFocusInternal(focused, false, false);
5123    }
5124
5125    /**
5126     * Returns true if this view has focus iteself, or is the ancestor of the
5127     * view that has focus.
5128     *
5129     * @return True if this view has or contains focus, false otherwise.
5130     */
5131    @ViewDebug.ExportedProperty(category = "focus")
5132    public boolean hasFocus() {
5133        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5134    }
5135
5136    /**
5137     * Returns true if this view is focusable or if it contains a reachable View
5138     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5139     * is a View whose parents do not block descendants focus.
5140     *
5141     * Only {@link #VISIBLE} views are considered focusable.
5142     *
5143     * @return True if the view is focusable or if the view contains a focusable
5144     *         View, false otherwise.
5145     *
5146     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5147     * @see ViewGroup#getTouchscreenBlocksFocus()
5148     */
5149    public boolean hasFocusable() {
5150        if (!isFocusableInTouchMode()) {
5151            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5152                final ViewGroup g = (ViewGroup) p;
5153                if (g.shouldBlockFocusForTouchscreen()) {
5154                    return false;
5155                }
5156            }
5157        }
5158        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5159    }
5160
5161    /**
5162     * Called by the view system when the focus state of this view changes.
5163     * When the focus change event is caused by directional navigation, direction
5164     * and previouslyFocusedRect provide insight into where the focus is coming from.
5165     * When overriding, be sure to call up through to the super class so that
5166     * the standard focus handling will occur.
5167     *
5168     * @param gainFocus True if the View has focus; false otherwise.
5169     * @param direction The direction focus has moved when requestFocus()
5170     *                  is called to give this view focus. Values are
5171     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5172     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5173     *                  It may not always apply, in which case use the default.
5174     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5175     *        system, of the previously focused view.  If applicable, this will be
5176     *        passed in as finer grained information about where the focus is coming
5177     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5178     */
5179    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5180            @Nullable Rect previouslyFocusedRect) {
5181        if (gainFocus) {
5182            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5183        } else {
5184            notifyViewAccessibilityStateChangedIfNeeded(
5185                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5186        }
5187
5188        InputMethodManager imm = InputMethodManager.peekInstance();
5189        if (!gainFocus) {
5190            if (isPressed()) {
5191                setPressed(false);
5192            }
5193            if (imm != null && mAttachInfo != null
5194                    && mAttachInfo.mHasWindowFocus) {
5195                imm.focusOut(this);
5196            }
5197            onFocusLost();
5198        } else if (imm != null && mAttachInfo != null
5199                && mAttachInfo.mHasWindowFocus) {
5200            imm.focusIn(this);
5201        }
5202
5203        invalidate(true);
5204        ListenerInfo li = mListenerInfo;
5205        if (li != null && li.mOnFocusChangeListener != null) {
5206            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5207        }
5208
5209        if (mAttachInfo != null) {
5210            mAttachInfo.mKeyDispatchState.reset(this);
5211        }
5212    }
5213
5214    /**
5215     * Sends an accessibility event of the given type. If accessibility is
5216     * not enabled this method has no effect. The default implementation calls
5217     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5218     * to populate information about the event source (this View), then calls
5219     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5220     * populate the text content of the event source including its descendants,
5221     * and last calls
5222     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5223     * on its parent to resuest sending of the event to interested parties.
5224     * <p>
5225     * If an {@link AccessibilityDelegate} has been specified via calling
5226     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5227     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5228     * responsible for handling this call.
5229     * </p>
5230     *
5231     * @param eventType The type of the event to send, as defined by several types from
5232     * {@link android.view.accessibility.AccessibilityEvent}, such as
5233     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5234     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5235     *
5236     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5237     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5238     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5239     * @see AccessibilityDelegate
5240     */
5241    public void sendAccessibilityEvent(int eventType) {
5242        if (mAccessibilityDelegate != null) {
5243            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5244        } else {
5245            sendAccessibilityEventInternal(eventType);
5246        }
5247    }
5248
5249    /**
5250     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5251     * {@link AccessibilityEvent} to make an announcement which is related to some
5252     * sort of a context change for which none of the events representing UI transitions
5253     * is a good fit. For example, announcing a new page in a book. If accessibility
5254     * is not enabled this method does nothing.
5255     *
5256     * @param text The announcement text.
5257     */
5258    public void announceForAccessibility(CharSequence text) {
5259        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5260            AccessibilityEvent event = AccessibilityEvent.obtain(
5261                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5262            onInitializeAccessibilityEvent(event);
5263            event.getText().add(text);
5264            event.setContentDescription(null);
5265            mParent.requestSendAccessibilityEvent(this, event);
5266        }
5267    }
5268
5269    /**
5270     * @see #sendAccessibilityEvent(int)
5271     *
5272     * Note: Called from the default {@link AccessibilityDelegate}.
5273     */
5274    void sendAccessibilityEventInternal(int eventType) {
5275        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5276            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5277        }
5278    }
5279
5280    /**
5281     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5282     * takes as an argument an empty {@link AccessibilityEvent} and does not
5283     * perform a check whether accessibility is enabled.
5284     * <p>
5285     * If an {@link AccessibilityDelegate} has been specified via calling
5286     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5287     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5288     * is responsible for handling this call.
5289     * </p>
5290     *
5291     * @param event The event to send.
5292     *
5293     * @see #sendAccessibilityEvent(int)
5294     */
5295    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5296        if (mAccessibilityDelegate != null) {
5297            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5298        } else {
5299            sendAccessibilityEventUncheckedInternal(event);
5300        }
5301    }
5302
5303    /**
5304     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5305     *
5306     * Note: Called from the default {@link AccessibilityDelegate}.
5307     */
5308    void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5309        if (!isShown()) {
5310            return;
5311        }
5312        onInitializeAccessibilityEvent(event);
5313        // Only a subset of accessibility events populates text content.
5314        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5315            dispatchPopulateAccessibilityEvent(event);
5316        }
5317        // In the beginning we called #isShown(), so we know that getParent() is not null.
5318        getParent().requestSendAccessibilityEvent(this, event);
5319    }
5320
5321    /**
5322     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5323     * to its children for adding their text content to the event. Note that the
5324     * event text is populated in a separate dispatch path since we add to the
5325     * event not only the text of the source but also the text of all its descendants.
5326     * A typical implementation will call
5327     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5328     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5329     * on each child. Override this method if custom population of the event text
5330     * content is required.
5331     * <p>
5332     * If an {@link AccessibilityDelegate} has been specified via calling
5333     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5334     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5335     * is responsible for handling this call.
5336     * </p>
5337     * <p>
5338     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5339     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5340     * </p>
5341     *
5342     * @param event The event.
5343     *
5344     * @return True if the event population was completed.
5345     */
5346    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5347        if (mAccessibilityDelegate != null) {
5348            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5349        } else {
5350            return dispatchPopulateAccessibilityEventInternal(event);
5351        }
5352    }
5353
5354    /**
5355     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5356     *
5357     * Note: Called from the default {@link AccessibilityDelegate}.
5358     */
5359    boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5360        onPopulateAccessibilityEvent(event);
5361        return false;
5362    }
5363
5364    /**
5365     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5366     * giving a chance to this View to populate the accessibility event with its
5367     * text content. While this method is free to modify event
5368     * attributes other than text content, doing so should normally be performed in
5369     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5370     * <p>
5371     * Example: Adding formatted date string to an accessibility event in addition
5372     *          to the text added by the super implementation:
5373     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5374     *     super.onPopulateAccessibilityEvent(event);
5375     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5376     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5377     *         mCurrentDate.getTimeInMillis(), flags);
5378     *     event.getText().add(selectedDateUtterance);
5379     * }</pre>
5380     * <p>
5381     * If an {@link AccessibilityDelegate} has been specified via calling
5382     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5383     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5384     * is responsible for handling this call.
5385     * </p>
5386     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5387     * information to the event, in case the default implementation has basic information to add.
5388     * </p>
5389     *
5390     * @param event The accessibility event which to populate.
5391     *
5392     * @see #sendAccessibilityEvent(int)
5393     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5394     */
5395    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5396        if (mAccessibilityDelegate != null) {
5397            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5398        } else {
5399            onPopulateAccessibilityEventInternal(event);
5400        }
5401    }
5402
5403    /**
5404     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5405     *
5406     * Note: Called from the default {@link AccessibilityDelegate}.
5407     */
5408    void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5409    }
5410
5411    /**
5412     * Initializes an {@link AccessibilityEvent} with information about
5413     * this View which is the event source. In other words, the source of
5414     * an accessibility event is the view whose state change triggered firing
5415     * the event.
5416     * <p>
5417     * Example: Setting the password property of an event in addition
5418     *          to properties set by the super implementation:
5419     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5420     *     super.onInitializeAccessibilityEvent(event);
5421     *     event.setPassword(true);
5422     * }</pre>
5423     * <p>
5424     * If an {@link AccessibilityDelegate} has been specified via calling
5425     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5426     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5427     * is responsible for handling this call.
5428     * </p>
5429     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5430     * information to the event, in case the default implementation has basic information to add.
5431     * </p>
5432     * @param event The event to initialize.
5433     *
5434     * @see #sendAccessibilityEvent(int)
5435     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5436     */
5437    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5438        if (mAccessibilityDelegate != null) {
5439            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5440        } else {
5441            onInitializeAccessibilityEventInternal(event);
5442        }
5443    }
5444
5445    /**
5446     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5447     *
5448     * Note: Called from the default {@link AccessibilityDelegate}.
5449     */
5450    void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5451        event.setSource(this);
5452        event.setClassName(View.class.getName());
5453        event.setPackageName(getContext().getPackageName());
5454        event.setEnabled(isEnabled());
5455        event.setContentDescription(mContentDescription);
5456
5457        switch (event.getEventType()) {
5458            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5459                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5460                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5461                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5462                event.setItemCount(focusablesTempList.size());
5463                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5464                if (mAttachInfo != null) {
5465                    focusablesTempList.clear();
5466                }
5467            } break;
5468            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5469                CharSequence text = getIterableTextForAccessibility();
5470                if (text != null && text.length() > 0) {
5471                    event.setFromIndex(getAccessibilitySelectionStart());
5472                    event.setToIndex(getAccessibilitySelectionEnd());
5473                    event.setItemCount(text.length());
5474                }
5475            } break;
5476        }
5477    }
5478
5479    /**
5480     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5481     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5482     * This method is responsible for obtaining an accessibility node info from a
5483     * pool of reusable instances and calling
5484     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5485     * initialize the former.
5486     * <p>
5487     * Note: The client is responsible for recycling the obtained instance by calling
5488     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5489     * </p>
5490     *
5491     * @return A populated {@link AccessibilityNodeInfo}.
5492     *
5493     * @see AccessibilityNodeInfo
5494     */
5495    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5496        if (mAccessibilityDelegate != null) {
5497            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5498        } else {
5499            return createAccessibilityNodeInfoInternal();
5500        }
5501    }
5502
5503    /**
5504     * @see #createAccessibilityNodeInfo()
5505     */
5506    AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5507        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5508        if (provider != null) {
5509            return provider.createAccessibilityNodeInfo(View.NO_ID);
5510        } else {
5511            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5512            onInitializeAccessibilityNodeInfo(info);
5513            return info;
5514        }
5515    }
5516
5517    /**
5518     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5519     * The base implementation sets:
5520     * <ul>
5521     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5522     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5523     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5524     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5525     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5526     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5527     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5528     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5529     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5530     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5531     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5532     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5533     * </ul>
5534     * <p>
5535     * Subclasses should override this method, call the super implementation,
5536     * and set additional attributes.
5537     * </p>
5538     * <p>
5539     * If an {@link AccessibilityDelegate} has been specified via calling
5540     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5541     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5542     * is responsible for handling this call.
5543     * </p>
5544     *
5545     * @param info The instance to initialize.
5546     */
5547    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5548        if (mAccessibilityDelegate != null) {
5549            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5550        } else {
5551            onInitializeAccessibilityNodeInfoInternal(info);
5552        }
5553    }
5554
5555    /**
5556     * Gets the location of this view in screen coordinates.
5557     *
5558     * @param outRect The output location
5559     * @hide
5560     */
5561    public void getBoundsOnScreen(Rect outRect) {
5562        getBoundsOnScreen(outRect, false);
5563    }
5564
5565    /**
5566     * Gets the location of this view in screen coordinates.
5567     *
5568     * @param outRect The output location
5569     * @param clipToParent Whether to clip child bounds to the parent ones.
5570     * @hide
5571     */
5572    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
5573        if (mAttachInfo == null) {
5574            return;
5575        }
5576
5577        RectF position = mAttachInfo.mTmpTransformRect;
5578        position.set(0, 0, mRight - mLeft, mBottom - mTop);
5579
5580        if (!hasIdentityMatrix()) {
5581            getMatrix().mapRect(position);
5582        }
5583
5584        position.offset(mLeft, mTop);
5585
5586        ViewParent parent = mParent;
5587        while (parent instanceof View) {
5588            View parentView = (View) parent;
5589
5590            position.offset(-parentView.mScrollX, -parentView.mScrollY);
5591
5592            if (clipToParent) {
5593                position.left = Math.max(position.left, 0);
5594                position.top = Math.max(position.top, 0);
5595                position.right = Math.min(position.right, parentView.getWidth());
5596                position.bottom = Math.min(position.bottom, parentView.getHeight());
5597            }
5598
5599            if (!parentView.hasIdentityMatrix()) {
5600                parentView.getMatrix().mapRect(position);
5601            }
5602
5603            position.offset(parentView.mLeft, parentView.mTop);
5604
5605            parent = parentView.mParent;
5606        }
5607
5608        if (parent instanceof ViewRootImpl) {
5609            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5610            position.offset(0, -viewRootImpl.mCurScrollY);
5611        }
5612
5613        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5614
5615        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5616                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5617    }
5618
5619    /**
5620     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5621     *
5622     * Note: Called from the default {@link AccessibilityDelegate}.
5623     */
5624    void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5625        Rect bounds = mAttachInfo.mTmpInvalRect;
5626
5627        getDrawingRect(bounds);
5628        info.setBoundsInParent(bounds);
5629
5630        getBoundsOnScreen(bounds, true);
5631        info.setBoundsInScreen(bounds);
5632
5633        ViewParent parent = getParentForAccessibility();
5634        if (parent instanceof View) {
5635            info.setParent((View) parent);
5636        }
5637
5638        if (mID != View.NO_ID) {
5639            View rootView = getRootView();
5640            if (rootView == null) {
5641                rootView = this;
5642            }
5643
5644            View label = rootView.findLabelForView(this, mID);
5645            if (label != null) {
5646                info.setLabeledBy(label);
5647            }
5648
5649            if ((mAttachInfo.mAccessibilityFetchFlags
5650                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5651                    && Resources.resourceHasPackage(mID)) {
5652                try {
5653                    String viewId = getResources().getResourceName(mID);
5654                    info.setViewIdResourceName(viewId);
5655                } catch (Resources.NotFoundException nfe) {
5656                    /* ignore */
5657                }
5658            }
5659        }
5660
5661        if (mLabelForId != View.NO_ID) {
5662            View rootView = getRootView();
5663            if (rootView == null) {
5664                rootView = this;
5665            }
5666            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5667            if (labeled != null) {
5668                info.setLabelFor(labeled);
5669            }
5670        }
5671
5672        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
5673            View rootView = getRootView();
5674            if (rootView == null) {
5675                rootView = this;
5676            }
5677            View next = rootView.findViewInsideOutShouldExist(this,
5678                    mAccessibilityTraversalBeforeId);
5679            if (next != null) {
5680                info.setTraversalBefore(next);
5681            }
5682        }
5683
5684        if (mAccessibilityTraversalAfterId != View.NO_ID) {
5685            View rootView = getRootView();
5686            if (rootView == null) {
5687                rootView = this;
5688            }
5689            View next = rootView.findViewInsideOutShouldExist(this,
5690                    mAccessibilityTraversalAfterId);
5691            if (next != null) {
5692                info.setTraversalAfter(next);
5693            }
5694        }
5695
5696        info.setVisibleToUser(isVisibleToUser());
5697
5698        info.setPackageName(mContext.getPackageName());
5699        info.setClassName(View.class.getName());
5700        info.setContentDescription(getContentDescription());
5701
5702        info.setEnabled(isEnabled());
5703        info.setClickable(isClickable());
5704        info.setFocusable(isFocusable());
5705        info.setFocused(isFocused());
5706        info.setAccessibilityFocused(isAccessibilityFocused());
5707        info.setSelected(isSelected());
5708        info.setLongClickable(isLongClickable());
5709        info.setLiveRegion(getAccessibilityLiveRegion());
5710
5711        // TODO: These make sense only if we are in an AdapterView but all
5712        // views can be selected. Maybe from accessibility perspective
5713        // we should report as selectable view in an AdapterView.
5714        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5715        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5716
5717        if (isFocusable()) {
5718            if (isFocused()) {
5719                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5720            } else {
5721                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5722            }
5723        }
5724
5725        if (!isAccessibilityFocused()) {
5726            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5727        } else {
5728            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5729        }
5730
5731        if (isClickable() && isEnabled()) {
5732            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5733        }
5734
5735        if (isLongClickable() && isEnabled()) {
5736            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5737        }
5738
5739        CharSequence text = getIterableTextForAccessibility();
5740        if (text != null && text.length() > 0) {
5741            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5742
5743            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5744            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5745            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5746            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5747                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5748                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5749        }
5750    }
5751
5752    private View findLabelForView(View view, int labeledId) {
5753        if (mMatchLabelForPredicate == null) {
5754            mMatchLabelForPredicate = new MatchLabelForPredicate();
5755        }
5756        mMatchLabelForPredicate.mLabeledId = labeledId;
5757        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5758    }
5759
5760    /**
5761     * Computes whether this view is visible to the user. Such a view is
5762     * attached, visible, all its predecessors are visible, it is not clipped
5763     * entirely by its predecessors, and has an alpha greater than zero.
5764     *
5765     * @return Whether the view is visible on the screen.
5766     *
5767     * @hide
5768     */
5769    protected boolean isVisibleToUser() {
5770        return isVisibleToUser(null);
5771    }
5772
5773    /**
5774     * Computes whether the given portion of this view is visible to the user.
5775     * Such a view is attached, visible, all its predecessors are visible,
5776     * has an alpha greater than zero, and the specified portion is not
5777     * clipped entirely by its predecessors.
5778     *
5779     * @param boundInView the portion of the view to test; coordinates should be relative; may be
5780     *                    <code>null</code>, and the entire view will be tested in this case.
5781     *                    When <code>true</code> is returned by the function, the actual visible
5782     *                    region will be stored in this parameter; that is, if boundInView is fully
5783     *                    contained within the view, no modification will be made, otherwise regions
5784     *                    outside of the visible area of the view will be clipped.
5785     *
5786     * @return Whether the specified portion of the view is visible on the screen.
5787     *
5788     * @hide
5789     */
5790    protected boolean isVisibleToUser(Rect boundInView) {
5791        if (mAttachInfo != null) {
5792            // Attached to invisible window means this view is not visible.
5793            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
5794                return false;
5795            }
5796            // An invisible predecessor or one with alpha zero means
5797            // that this view is not visible to the user.
5798            Object current = this;
5799            while (current instanceof View) {
5800                View view = (View) current;
5801                // We have attach info so this view is attached and there is no
5802                // need to check whether we reach to ViewRootImpl on the way up.
5803                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
5804                        view.getVisibility() != VISIBLE) {
5805                    return false;
5806                }
5807                current = view.mParent;
5808            }
5809            // Check if the view is entirely covered by its predecessors.
5810            Rect visibleRect = mAttachInfo.mTmpInvalRect;
5811            Point offset = mAttachInfo.mPoint;
5812            if (!getGlobalVisibleRect(visibleRect, offset)) {
5813                return false;
5814            }
5815            // Check if the visible portion intersects the rectangle of interest.
5816            if (boundInView != null) {
5817                visibleRect.offset(-offset.x, -offset.y);
5818                return boundInView.intersect(visibleRect);
5819            }
5820            return true;
5821        }
5822        return false;
5823    }
5824
5825    /**
5826     * Returns the delegate for implementing accessibility support via
5827     * composition. For more details see {@link AccessibilityDelegate}.
5828     *
5829     * @return The delegate, or null if none set.
5830     *
5831     * @hide
5832     */
5833    public AccessibilityDelegate getAccessibilityDelegate() {
5834        return mAccessibilityDelegate;
5835    }
5836
5837    /**
5838     * Sets a delegate for implementing accessibility support via composition as
5839     * opposed to inheritance. The delegate's primary use is for implementing
5840     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
5841     *
5842     * @param delegate The delegate instance.
5843     *
5844     * @see AccessibilityDelegate
5845     */
5846    public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
5847        mAccessibilityDelegate = delegate;
5848    }
5849
5850    /**
5851     * Gets the provider for managing a virtual view hierarchy rooted at this View
5852     * and reported to {@link android.accessibilityservice.AccessibilityService}s
5853     * that explore the window content.
5854     * <p>
5855     * If this method returns an instance, this instance is responsible for managing
5856     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
5857     * View including the one representing the View itself. Similarly the returned
5858     * instance is responsible for performing accessibility actions on any virtual
5859     * view or the root view itself.
5860     * </p>
5861     * <p>
5862     * If an {@link AccessibilityDelegate} has been specified via calling
5863     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5864     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
5865     * is responsible for handling this call.
5866     * </p>
5867     *
5868     * @return The provider.
5869     *
5870     * @see AccessibilityNodeProvider
5871     */
5872    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
5873        if (mAccessibilityDelegate != null) {
5874            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
5875        } else {
5876            return null;
5877        }
5878    }
5879
5880    /**
5881     * Gets the unique identifier of this view on the screen for accessibility purposes.
5882     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5883     *
5884     * @return The view accessibility id.
5885     *
5886     * @hide
5887     */
5888    public int getAccessibilityViewId() {
5889        if (mAccessibilityViewId == NO_ID) {
5890            mAccessibilityViewId = sNextAccessibilityViewId++;
5891        }
5892        return mAccessibilityViewId;
5893    }
5894
5895    /**
5896     * Gets the unique identifier of the window in which this View reseides.
5897     *
5898     * @return The window accessibility id.
5899     *
5900     * @hide
5901     */
5902    public int getAccessibilityWindowId() {
5903        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
5904                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
5905    }
5906
5907    /**
5908     * Gets the {@link View} description. It briefly describes the view and is
5909     * primarily used for accessibility support. Set this property to enable
5910     * better accessibility support for your application. This is especially
5911     * true for views that do not have textual representation (For example,
5912     * ImageButton).
5913     *
5914     * @return The content description.
5915     *
5916     * @attr ref android.R.styleable#View_contentDescription
5917     */
5918    @ViewDebug.ExportedProperty(category = "accessibility")
5919    public CharSequence getContentDescription() {
5920        return mContentDescription;
5921    }
5922
5923    /**
5924     * Sets the {@link View} description. It briefly describes the view and is
5925     * primarily used for accessibility support. Set this property to enable
5926     * better accessibility support for your application. This is especially
5927     * true for views that do not have textual representation (For example,
5928     * ImageButton).
5929     *
5930     * @param contentDescription The content description.
5931     *
5932     * @attr ref android.R.styleable#View_contentDescription
5933     */
5934    @RemotableViewMethod
5935    public void setContentDescription(CharSequence contentDescription) {
5936        if (mContentDescription == null) {
5937            if (contentDescription == null) {
5938                return;
5939            }
5940        } else if (mContentDescription.equals(contentDescription)) {
5941            return;
5942        }
5943        mContentDescription = contentDescription;
5944        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5945        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5946            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5947            notifySubtreeAccessibilityStateChangedIfNeeded();
5948        } else {
5949            notifyViewAccessibilityStateChangedIfNeeded(
5950                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
5951        }
5952    }
5953
5954    /**
5955     * Sets the id of a view before which this one is visited in accessibility traversal.
5956     * A screen-reader must visit the content of this view before the content of the one
5957     * it precedes. For example, if view B is set to be before view A, then a screen-reader
5958     * will traverse the entire content of B before traversing the entire content of A,
5959     * regardles of what traversal strategy it is using.
5960     * <p>
5961     * Views that do not have specified before/after relationships are traversed in order
5962     * determined by the screen-reader.
5963     * </p>
5964     * <p>
5965     * Setting that this view is before a view that is not important for accessibility
5966     * or if this view is not important for accessibility will have no effect as the
5967     * screen-reader is not aware of unimportant views.
5968     * </p>
5969     *
5970     * @param beforeId The id of a view this one precedes in accessibility traversal.
5971     *
5972     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
5973     *
5974     * @see #setImportantForAccessibility(int)
5975     */
5976    @RemotableViewMethod
5977    public void setAccessibilityTraversalBefore(int beforeId) {
5978        if (mAccessibilityTraversalBeforeId == beforeId) {
5979            return;
5980        }
5981        mAccessibilityTraversalBeforeId = beforeId;
5982        notifyViewAccessibilityStateChangedIfNeeded(
5983                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5984    }
5985
5986    /**
5987     * Gets the id of a view before which this one is visited in accessibility traversal.
5988     *
5989     * @return The id of a view this one precedes in accessibility traversal if
5990     *         specified, otherwise {@link #NO_ID}.
5991     *
5992     * @see #setAccessibilityTraversalBefore(int)
5993     */
5994    public int getAccessibilityTraversalBefore() {
5995        return mAccessibilityTraversalBeforeId;
5996    }
5997
5998    /**
5999     * Sets the id of a view after which this one is visited in accessibility traversal.
6000     * A screen-reader must visit the content of the other view before the content of this
6001     * one. For example, if view B is set to be after view A, then a screen-reader
6002     * will traverse the entire content of A before traversing the entire content of B,
6003     * regardles of what traversal strategy it is using.
6004     * <p>
6005     * Views that do not have specified before/after relationships are traversed in order
6006     * determined by the screen-reader.
6007     * </p>
6008     * <p>
6009     * Setting that this view is after a view that is not important for accessibility
6010     * or if this view is not important for accessibility will have no effect as the
6011     * screen-reader is not aware of unimportant views.
6012     * </p>
6013     *
6014     * @param afterId The id of a view this one succedees in accessibility traversal.
6015     *
6016     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6017     *
6018     * @see #setImportantForAccessibility(int)
6019     */
6020    @RemotableViewMethod
6021    public void setAccessibilityTraversalAfter(int afterId) {
6022        if (mAccessibilityTraversalAfterId == afterId) {
6023            return;
6024        }
6025        mAccessibilityTraversalAfterId = afterId;
6026        notifyViewAccessibilityStateChangedIfNeeded(
6027                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6028    }
6029
6030    /**
6031     * Gets the id of a view after which this one is visited in accessibility traversal.
6032     *
6033     * @return The id of a view this one succeedes in accessibility traversal if
6034     *         specified, otherwise {@link #NO_ID}.
6035     *
6036     * @see #setAccessibilityTraversalAfter(int)
6037     */
6038    public int getAccessibilityTraversalAfter() {
6039        return mAccessibilityTraversalAfterId;
6040    }
6041
6042    /**
6043     * Gets the id of a view for which this view serves as a label for
6044     * accessibility purposes.
6045     *
6046     * @return The labeled view id.
6047     */
6048    @ViewDebug.ExportedProperty(category = "accessibility")
6049    public int getLabelFor() {
6050        return mLabelForId;
6051    }
6052
6053    /**
6054     * Sets the id of a view for which this view serves as a label for
6055     * accessibility purposes.
6056     *
6057     * @param id The labeled view id.
6058     */
6059    @RemotableViewMethod
6060    public void setLabelFor(int id) {
6061        if (mLabelForId == id) {
6062            return;
6063        }
6064        mLabelForId = id;
6065        if (mLabelForId != View.NO_ID
6066                && mID == View.NO_ID) {
6067            mID = generateViewId();
6068        }
6069        notifyViewAccessibilityStateChangedIfNeeded(
6070                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6071    }
6072
6073    /**
6074     * Invoked whenever this view loses focus, either by losing window focus or by losing
6075     * focus within its window. This method can be used to clear any state tied to the
6076     * focus. For instance, if a button is held pressed with the trackball and the window
6077     * loses focus, this method can be used to cancel the press.
6078     *
6079     * Subclasses of View overriding this method should always call super.onFocusLost().
6080     *
6081     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6082     * @see #onWindowFocusChanged(boolean)
6083     *
6084     * @hide pending API council approval
6085     */
6086    protected void onFocusLost() {
6087        resetPressedState();
6088    }
6089
6090    private void resetPressedState() {
6091        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6092            return;
6093        }
6094
6095        if (isPressed()) {
6096            setPressed(false);
6097
6098            if (!mHasPerformedLongPress) {
6099                removeLongPressCallback();
6100            }
6101        }
6102    }
6103
6104    /**
6105     * Returns true if this view has focus
6106     *
6107     * @return True if this view has focus, false otherwise.
6108     */
6109    @ViewDebug.ExportedProperty(category = "focus")
6110    public boolean isFocused() {
6111        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6112    }
6113
6114    /**
6115     * Find the view in the hierarchy rooted at this view that currently has
6116     * focus.
6117     *
6118     * @return The view that currently has focus, or null if no focused view can
6119     *         be found.
6120     */
6121    public View findFocus() {
6122        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6123    }
6124
6125    /**
6126     * Indicates whether this view is one of the set of scrollable containers in
6127     * its window.
6128     *
6129     * @return whether this view is one of the set of scrollable containers in
6130     * its window
6131     *
6132     * @attr ref android.R.styleable#View_isScrollContainer
6133     */
6134    public boolean isScrollContainer() {
6135        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6136    }
6137
6138    /**
6139     * Change whether this view is one of the set of scrollable containers in
6140     * its window.  This will be used to determine whether the window can
6141     * resize or must pan when a soft input area is open -- scrollable
6142     * containers allow the window to use resize mode since the container
6143     * will appropriately shrink.
6144     *
6145     * @attr ref android.R.styleable#View_isScrollContainer
6146     */
6147    public void setScrollContainer(boolean isScrollContainer) {
6148        if (isScrollContainer) {
6149            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6150                mAttachInfo.mScrollContainers.add(this);
6151                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6152            }
6153            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6154        } else {
6155            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6156                mAttachInfo.mScrollContainers.remove(this);
6157            }
6158            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6159        }
6160    }
6161
6162    /**
6163     * Returns the quality of the drawing cache.
6164     *
6165     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6166     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6167     *
6168     * @see #setDrawingCacheQuality(int)
6169     * @see #setDrawingCacheEnabled(boolean)
6170     * @see #isDrawingCacheEnabled()
6171     *
6172     * @attr ref android.R.styleable#View_drawingCacheQuality
6173     */
6174    @DrawingCacheQuality
6175    public int getDrawingCacheQuality() {
6176        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6177    }
6178
6179    /**
6180     * Set the drawing cache quality of this view. This value is used only when the
6181     * drawing cache is enabled
6182     *
6183     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6184     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6185     *
6186     * @see #getDrawingCacheQuality()
6187     * @see #setDrawingCacheEnabled(boolean)
6188     * @see #isDrawingCacheEnabled()
6189     *
6190     * @attr ref android.R.styleable#View_drawingCacheQuality
6191     */
6192    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6193        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6194    }
6195
6196    /**
6197     * Returns whether the screen should remain on, corresponding to the current
6198     * value of {@link #KEEP_SCREEN_ON}.
6199     *
6200     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6201     *
6202     * @see #setKeepScreenOn(boolean)
6203     *
6204     * @attr ref android.R.styleable#View_keepScreenOn
6205     */
6206    public boolean getKeepScreenOn() {
6207        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6208    }
6209
6210    /**
6211     * Controls whether the screen should remain on, modifying the
6212     * value of {@link #KEEP_SCREEN_ON}.
6213     *
6214     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6215     *
6216     * @see #getKeepScreenOn()
6217     *
6218     * @attr ref android.R.styleable#View_keepScreenOn
6219     */
6220    public void setKeepScreenOn(boolean keepScreenOn) {
6221        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6222    }
6223
6224    /**
6225     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6226     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6227     *
6228     * @attr ref android.R.styleable#View_nextFocusLeft
6229     */
6230    public int getNextFocusLeftId() {
6231        return mNextFocusLeftId;
6232    }
6233
6234    /**
6235     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6236     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6237     * decide automatically.
6238     *
6239     * @attr ref android.R.styleable#View_nextFocusLeft
6240     */
6241    public void setNextFocusLeftId(int nextFocusLeftId) {
6242        mNextFocusLeftId = nextFocusLeftId;
6243    }
6244
6245    /**
6246     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6247     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6248     *
6249     * @attr ref android.R.styleable#View_nextFocusRight
6250     */
6251    public int getNextFocusRightId() {
6252        return mNextFocusRightId;
6253    }
6254
6255    /**
6256     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6257     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6258     * decide automatically.
6259     *
6260     * @attr ref android.R.styleable#View_nextFocusRight
6261     */
6262    public void setNextFocusRightId(int nextFocusRightId) {
6263        mNextFocusRightId = nextFocusRightId;
6264    }
6265
6266    /**
6267     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6268     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6269     *
6270     * @attr ref android.R.styleable#View_nextFocusUp
6271     */
6272    public int getNextFocusUpId() {
6273        return mNextFocusUpId;
6274    }
6275
6276    /**
6277     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6278     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6279     * decide automatically.
6280     *
6281     * @attr ref android.R.styleable#View_nextFocusUp
6282     */
6283    public void setNextFocusUpId(int nextFocusUpId) {
6284        mNextFocusUpId = nextFocusUpId;
6285    }
6286
6287    /**
6288     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6289     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6290     *
6291     * @attr ref android.R.styleable#View_nextFocusDown
6292     */
6293    public int getNextFocusDownId() {
6294        return mNextFocusDownId;
6295    }
6296
6297    /**
6298     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6299     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6300     * decide automatically.
6301     *
6302     * @attr ref android.R.styleable#View_nextFocusDown
6303     */
6304    public void setNextFocusDownId(int nextFocusDownId) {
6305        mNextFocusDownId = nextFocusDownId;
6306    }
6307
6308    /**
6309     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6310     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6311     *
6312     * @attr ref android.R.styleable#View_nextFocusForward
6313     */
6314    public int getNextFocusForwardId() {
6315        return mNextFocusForwardId;
6316    }
6317
6318    /**
6319     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6320     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6321     * decide automatically.
6322     *
6323     * @attr ref android.R.styleable#View_nextFocusForward
6324     */
6325    public void setNextFocusForwardId(int nextFocusForwardId) {
6326        mNextFocusForwardId = nextFocusForwardId;
6327    }
6328
6329    /**
6330     * Returns the visibility of this view and all of its ancestors
6331     *
6332     * @return True if this view and all of its ancestors are {@link #VISIBLE}
6333     */
6334    public boolean isShown() {
6335        View current = this;
6336        //noinspection ConstantConditions
6337        do {
6338            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6339                return false;
6340            }
6341            ViewParent parent = current.mParent;
6342            if (parent == null) {
6343                return false; // We are not attached to the view root
6344            }
6345            if (!(parent instanceof View)) {
6346                return true;
6347            }
6348            current = (View) parent;
6349        } while (current != null);
6350
6351        return false;
6352    }
6353
6354    /**
6355     * Called by the view hierarchy when the content insets for a window have
6356     * changed, to allow it to adjust its content to fit within those windows.
6357     * The content insets tell you the space that the status bar, input method,
6358     * and other system windows infringe on the application's window.
6359     *
6360     * <p>You do not normally need to deal with this function, since the default
6361     * window decoration given to applications takes care of applying it to the
6362     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6363     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6364     * and your content can be placed under those system elements.  You can then
6365     * use this method within your view hierarchy if you have parts of your UI
6366     * which you would like to ensure are not being covered.
6367     *
6368     * <p>The default implementation of this method simply applies the content
6369     * insets to the view's padding, consuming that content (modifying the
6370     * insets to be 0), and returning true.  This behavior is off by default, but can
6371     * be enabled through {@link #setFitsSystemWindows(boolean)}.
6372     *
6373     * <p>This function's traversal down the hierarchy is depth-first.  The same content
6374     * insets object is propagated down the hierarchy, so any changes made to it will
6375     * be seen by all following views (including potentially ones above in
6376     * the hierarchy since this is a depth-first traversal).  The first view
6377     * that returns true will abort the entire traversal.
6378     *
6379     * <p>The default implementation works well for a situation where it is
6380     * used with a container that covers the entire window, allowing it to
6381     * apply the appropriate insets to its content on all edges.  If you need
6382     * a more complicated layout (such as two different views fitting system
6383     * windows, one on the top of the window, and one on the bottom),
6384     * you can override the method and handle the insets however you would like.
6385     * Note that the insets provided by the framework are always relative to the
6386     * far edges of the window, not accounting for the location of the called view
6387     * within that window.  (In fact when this method is called you do not yet know
6388     * where the layout will place the view, as it is done before layout happens.)
6389     *
6390     * <p>Note: unlike many View methods, there is no dispatch phase to this
6391     * call.  If you are overriding it in a ViewGroup and want to allow the
6392     * call to continue to your children, you must be sure to call the super
6393     * implementation.
6394     *
6395     * <p>Here is a sample layout that makes use of fitting system windows
6396     * to have controls for a video view placed inside of the window decorations
6397     * that it hides and shows.  This can be used with code like the second
6398     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6399     *
6400     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6401     *
6402     * @param insets Current content insets of the window.  Prior to
6403     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6404     * the insets or else you and Android will be unhappy.
6405     *
6406     * @return {@code true} if this view applied the insets and it should not
6407     * continue propagating further down the hierarchy, {@code false} otherwise.
6408     * @see #getFitsSystemWindows()
6409     * @see #setFitsSystemWindows(boolean)
6410     * @see #setSystemUiVisibility(int)
6411     *
6412     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6413     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6414     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6415     * to implement handling their own insets.
6416     */
6417    protected boolean fitSystemWindows(Rect insets) {
6418        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6419            if (insets == null) {
6420                // Null insets by definition have already been consumed.
6421                // This call cannot apply insets since there are none to apply,
6422                // so return false.
6423                return false;
6424            }
6425            // If we're not in the process of dispatching the newer apply insets call,
6426            // that means we're not in the compatibility path. Dispatch into the newer
6427            // apply insets path and take things from there.
6428            try {
6429                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6430                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6431            } finally {
6432                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6433            }
6434        } else {
6435            // We're being called from the newer apply insets path.
6436            // Perform the standard fallback behavior.
6437            return fitSystemWindowsInt(insets);
6438        }
6439    }
6440
6441    private boolean fitSystemWindowsInt(Rect insets) {
6442        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6443            mUserPaddingStart = UNDEFINED_PADDING;
6444            mUserPaddingEnd = UNDEFINED_PADDING;
6445            Rect localInsets = sThreadLocal.get();
6446            if (localInsets == null) {
6447                localInsets = new Rect();
6448                sThreadLocal.set(localInsets);
6449            }
6450            boolean res = computeFitSystemWindows(insets, localInsets);
6451            mUserPaddingLeftInitial = localInsets.left;
6452            mUserPaddingRightInitial = localInsets.right;
6453            internalSetPadding(localInsets.left, localInsets.top,
6454                    localInsets.right, localInsets.bottom);
6455            return res;
6456        }
6457        return false;
6458    }
6459
6460    /**
6461     * Called when the view should apply {@link WindowInsets} according to its internal policy.
6462     *
6463     * <p>This method should be overridden by views that wish to apply a policy different from or
6464     * in addition to the default behavior. Clients that wish to force a view subtree
6465     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6466     *
6467     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6468     * it will be called during dispatch instead of this method. The listener may optionally
6469     * call this method from its own implementation if it wishes to apply the view's default
6470     * insets policy in addition to its own.</p>
6471     *
6472     * <p>Implementations of this method should either return the insets parameter unchanged
6473     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6474     * that this view applied itself. This allows new inset types added in future platform
6475     * versions to pass through existing implementations unchanged without being erroneously
6476     * consumed.</p>
6477     *
6478     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6479     * property is set then the view will consume the system window insets and apply them
6480     * as padding for the view.</p>
6481     *
6482     * @param insets Insets to apply
6483     * @return The supplied insets with any applied insets consumed
6484     */
6485    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6486        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6487            // We weren't called from within a direct call to fitSystemWindows,
6488            // call into it as a fallback in case we're in a class that overrides it
6489            // and has logic to perform.
6490            if (fitSystemWindows(insets.getSystemWindowInsets())) {
6491                return insets.consumeSystemWindowInsets();
6492            }
6493        } else {
6494            // We were called from within a direct call to fitSystemWindows.
6495            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6496                return insets.consumeSystemWindowInsets();
6497            }
6498        }
6499        return insets;
6500    }
6501
6502    /**
6503     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6504     * window insets to this view. The listener's
6505     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6506     * method will be called instead of the view's
6507     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6508     *
6509     * @param listener Listener to set
6510     *
6511     * @see #onApplyWindowInsets(WindowInsets)
6512     */
6513    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6514        getListenerInfo().mOnApplyWindowInsetsListener = listener;
6515    }
6516
6517    /**
6518     * Request to apply the given window insets to this view or another view in its subtree.
6519     *
6520     * <p>This method should be called by clients wishing to apply insets corresponding to areas
6521     * obscured by window decorations or overlays. This can include the status and navigation bars,
6522     * action bars, input methods and more. New inset categories may be added in the future.
6523     * The method returns the insets provided minus any that were applied by this view or its
6524     * children.</p>
6525     *
6526     * <p>Clients wishing to provide custom behavior should override the
6527     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6528     * {@link OnApplyWindowInsetsListener} via the
6529     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6530     * method.</p>
6531     *
6532     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6533     * </p>
6534     *
6535     * @param insets Insets to apply
6536     * @return The provided insets minus the insets that were consumed
6537     */
6538    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6539        try {
6540            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6541            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6542                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6543            } else {
6544                return onApplyWindowInsets(insets);
6545            }
6546        } finally {
6547            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6548        }
6549    }
6550
6551    /**
6552     * @hide Compute the insets that should be consumed by this view and the ones
6553     * that should propagate to those under it.
6554     */
6555    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6556        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6557                || mAttachInfo == null
6558                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6559                        && !mAttachInfo.mOverscanRequested)) {
6560            outLocalInsets.set(inoutInsets);
6561            inoutInsets.set(0, 0, 0, 0);
6562            return true;
6563        } else {
6564            // The application wants to take care of fitting system window for
6565            // the content...  however we still need to take care of any overscan here.
6566            final Rect overscan = mAttachInfo.mOverscanInsets;
6567            outLocalInsets.set(overscan);
6568            inoutInsets.left -= overscan.left;
6569            inoutInsets.top -= overscan.top;
6570            inoutInsets.right -= overscan.right;
6571            inoutInsets.bottom -= overscan.bottom;
6572            return false;
6573        }
6574    }
6575
6576    /**
6577     * Compute insets that should be consumed by this view and the ones that should propagate
6578     * to those under it.
6579     *
6580     * @param in Insets currently being processed by this View, likely received as a parameter
6581     *           to {@link #onApplyWindowInsets(WindowInsets)}.
6582     * @param outLocalInsets A Rect that will receive the insets that should be consumed
6583     *                       by this view
6584     * @return Insets that should be passed along to views under this one
6585     */
6586    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6587        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6588                || mAttachInfo == null
6589                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6590            outLocalInsets.set(in.getSystemWindowInsets());
6591            return in.consumeSystemWindowInsets();
6592        } else {
6593            outLocalInsets.set(0, 0, 0, 0);
6594            return in;
6595        }
6596    }
6597
6598    /**
6599     * Sets whether or not this view should account for system screen decorations
6600     * such as the status bar and inset its content; that is, controlling whether
6601     * the default implementation of {@link #fitSystemWindows(Rect)} will be
6602     * executed.  See that method for more details.
6603     *
6604     * <p>Note that if you are providing your own implementation of
6605     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6606     * flag to true -- your implementation will be overriding the default
6607     * implementation that checks this flag.
6608     *
6609     * @param fitSystemWindows If true, then the default implementation of
6610     * {@link #fitSystemWindows(Rect)} will be executed.
6611     *
6612     * @attr ref android.R.styleable#View_fitsSystemWindows
6613     * @see #getFitsSystemWindows()
6614     * @see #fitSystemWindows(Rect)
6615     * @see #setSystemUiVisibility(int)
6616     */
6617    public void setFitsSystemWindows(boolean fitSystemWindows) {
6618        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6619    }
6620
6621    /**
6622     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6623     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6624     * will be executed.
6625     *
6626     * @return {@code true} if the default implementation of
6627     * {@link #fitSystemWindows(Rect)} will be executed.
6628     *
6629     * @attr ref android.R.styleable#View_fitsSystemWindows
6630     * @see #setFitsSystemWindows(boolean)
6631     * @see #fitSystemWindows(Rect)
6632     * @see #setSystemUiVisibility(int)
6633     */
6634    @ViewDebug.ExportedProperty
6635    public boolean getFitsSystemWindows() {
6636        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6637    }
6638
6639    /** @hide */
6640    public boolean fitsSystemWindows() {
6641        return getFitsSystemWindows();
6642    }
6643
6644    /**
6645     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6646     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6647     */
6648    public void requestFitSystemWindows() {
6649        if (mParent != null) {
6650            mParent.requestFitSystemWindows();
6651        }
6652    }
6653
6654    /**
6655     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6656     */
6657    public void requestApplyInsets() {
6658        requestFitSystemWindows();
6659    }
6660
6661    /**
6662     * For use by PhoneWindow to make its own system window fitting optional.
6663     * @hide
6664     */
6665    public void makeOptionalFitsSystemWindows() {
6666        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6667    }
6668
6669    /**
6670     * Returns the visibility status for this view.
6671     *
6672     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6673     * @attr ref android.R.styleable#View_visibility
6674     */
6675    @ViewDebug.ExportedProperty(mapping = {
6676        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6677        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6678        @ViewDebug.IntToString(from = GONE,      to = "GONE")
6679    })
6680    @Visibility
6681    public int getVisibility() {
6682        return mViewFlags & VISIBILITY_MASK;
6683    }
6684
6685    /**
6686     * Set the enabled state of this view.
6687     *
6688     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6689     * @attr ref android.R.styleable#View_visibility
6690     */
6691    @RemotableViewMethod
6692    public void setVisibility(@Visibility int visibility) {
6693        setFlags(visibility, VISIBILITY_MASK);
6694        if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
6695    }
6696
6697    /**
6698     * Returns the enabled status for this view. The interpretation of the
6699     * enabled state varies by subclass.
6700     *
6701     * @return True if this view is enabled, false otherwise.
6702     */
6703    @ViewDebug.ExportedProperty
6704    public boolean isEnabled() {
6705        return (mViewFlags & ENABLED_MASK) == ENABLED;
6706    }
6707
6708    /**
6709     * Set the enabled state of this view. The interpretation of the enabled
6710     * state varies by subclass.
6711     *
6712     * @param enabled True if this view is enabled, false otherwise.
6713     */
6714    @RemotableViewMethod
6715    public void setEnabled(boolean enabled) {
6716        if (enabled == isEnabled()) return;
6717
6718        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6719
6720        /*
6721         * The View most likely has to change its appearance, so refresh
6722         * the drawable state.
6723         */
6724        refreshDrawableState();
6725
6726        // Invalidate too, since the default behavior for views is to be
6727        // be drawn at 50% alpha rather than to change the drawable.
6728        invalidate(true);
6729
6730        if (!enabled) {
6731            cancelPendingInputEvents();
6732        }
6733    }
6734
6735    /**
6736     * Set whether this view can receive the focus.
6737     *
6738     * Setting this to false will also ensure that this view is not focusable
6739     * in touch mode.
6740     *
6741     * @param focusable If true, this view can receive the focus.
6742     *
6743     * @see #setFocusableInTouchMode(boolean)
6744     * @attr ref android.R.styleable#View_focusable
6745     */
6746    public void setFocusable(boolean focusable) {
6747        if (!focusable) {
6748            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6749        }
6750        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6751    }
6752
6753    /**
6754     * Set whether this view can receive focus while in touch mode.
6755     *
6756     * Setting this to true will also ensure that this view is focusable.
6757     *
6758     * @param focusableInTouchMode If true, this view can receive the focus while
6759     *   in touch mode.
6760     *
6761     * @see #setFocusable(boolean)
6762     * @attr ref android.R.styleable#View_focusableInTouchMode
6763     */
6764    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6765        // Focusable in touch mode should always be set before the focusable flag
6766        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6767        // which, in touch mode, will not successfully request focus on this view
6768        // because the focusable in touch mode flag is not set
6769        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6770        if (focusableInTouchMode) {
6771            setFlags(FOCUSABLE, FOCUSABLE_MASK);
6772        }
6773    }
6774
6775    /**
6776     * Set whether this view should have sound effects enabled for events such as
6777     * clicking and touching.
6778     *
6779     * <p>You may wish to disable sound effects for a view if you already play sounds,
6780     * for instance, a dial key that plays dtmf tones.
6781     *
6782     * @param soundEffectsEnabled whether sound effects are enabled for this view.
6783     * @see #isSoundEffectsEnabled()
6784     * @see #playSoundEffect(int)
6785     * @attr ref android.R.styleable#View_soundEffectsEnabled
6786     */
6787    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
6788        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
6789    }
6790
6791    /**
6792     * @return whether this view should have sound effects enabled for events such as
6793     *     clicking and touching.
6794     *
6795     * @see #setSoundEffectsEnabled(boolean)
6796     * @see #playSoundEffect(int)
6797     * @attr ref android.R.styleable#View_soundEffectsEnabled
6798     */
6799    @ViewDebug.ExportedProperty
6800    public boolean isSoundEffectsEnabled() {
6801        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
6802    }
6803
6804    /**
6805     * Set whether this view should have haptic feedback for events such as
6806     * long presses.
6807     *
6808     * <p>You may wish to disable haptic feedback if your view already controls
6809     * its own haptic feedback.
6810     *
6811     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
6812     * @see #isHapticFeedbackEnabled()
6813     * @see #performHapticFeedback(int)
6814     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6815     */
6816    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
6817        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
6818    }
6819
6820    /**
6821     * @return whether this view should have haptic feedback enabled for events
6822     * long presses.
6823     *
6824     * @see #setHapticFeedbackEnabled(boolean)
6825     * @see #performHapticFeedback(int)
6826     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
6827     */
6828    @ViewDebug.ExportedProperty
6829    public boolean isHapticFeedbackEnabled() {
6830        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
6831    }
6832
6833    /**
6834     * Returns the layout direction for this view.
6835     *
6836     * @return One of {@link #LAYOUT_DIRECTION_LTR},
6837     *   {@link #LAYOUT_DIRECTION_RTL},
6838     *   {@link #LAYOUT_DIRECTION_INHERIT} or
6839     *   {@link #LAYOUT_DIRECTION_LOCALE}.
6840     *
6841     * @attr ref android.R.styleable#View_layoutDirection
6842     *
6843     * @hide
6844     */
6845    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6846        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
6847        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
6848        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
6849        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
6850    })
6851    @LayoutDir
6852    public int getRawLayoutDirection() {
6853        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
6854    }
6855
6856    /**
6857     * Set the layout direction for this view. This will propagate a reset of layout direction
6858     * resolution to the view's children and resolve layout direction for this view.
6859     *
6860     * @param layoutDirection the layout direction to set. Should be one of:
6861     *
6862     * {@link #LAYOUT_DIRECTION_LTR},
6863     * {@link #LAYOUT_DIRECTION_RTL},
6864     * {@link #LAYOUT_DIRECTION_INHERIT},
6865     * {@link #LAYOUT_DIRECTION_LOCALE}.
6866     *
6867     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
6868     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
6869     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
6870     *
6871     * @attr ref android.R.styleable#View_layoutDirection
6872     */
6873    @RemotableViewMethod
6874    public void setLayoutDirection(@LayoutDir int layoutDirection) {
6875        if (getRawLayoutDirection() != layoutDirection) {
6876            // Reset the current layout direction and the resolved one
6877            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
6878            resetRtlProperties();
6879            // Set the new layout direction (filtered)
6880            mPrivateFlags2 |=
6881                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
6882            // We need to resolve all RTL properties as they all depend on layout direction
6883            resolveRtlPropertiesIfNeeded();
6884            requestLayout();
6885            invalidate(true);
6886        }
6887    }
6888
6889    /**
6890     * Returns the resolved layout direction for this view.
6891     *
6892     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
6893     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
6894     *
6895     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
6896     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
6897     *
6898     * @attr ref android.R.styleable#View_layoutDirection
6899     */
6900    @ViewDebug.ExportedProperty(category = "layout", mapping = {
6901        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
6902        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
6903    })
6904    @ResolvedLayoutDir
6905    public int getLayoutDirection() {
6906        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
6907        if (targetSdkVersion < JELLY_BEAN_MR1) {
6908            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
6909            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
6910        }
6911        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
6912                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
6913    }
6914
6915    /**
6916     * Indicates whether or not this view's layout is right-to-left. This is resolved from
6917     * layout attribute and/or the inherited value from the parent
6918     *
6919     * @return true if the layout is right-to-left.
6920     *
6921     * @hide
6922     */
6923    @ViewDebug.ExportedProperty(category = "layout")
6924    public boolean isLayoutRtl() {
6925        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
6926    }
6927
6928    /**
6929     * Indicates whether the view is currently tracking transient state that the
6930     * app should not need to concern itself with saving and restoring, but that
6931     * the framework should take special note to preserve when possible.
6932     *
6933     * <p>A view with transient state cannot be trivially rebound from an external
6934     * data source, such as an adapter binding item views in a list. This may be
6935     * because the view is performing an animation, tracking user selection
6936     * of content, or similar.</p>
6937     *
6938     * @return true if the view has transient state
6939     */
6940    @ViewDebug.ExportedProperty(category = "layout")
6941    public boolean hasTransientState() {
6942        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
6943    }
6944
6945    /**
6946     * Set whether this view is currently tracking transient state that the
6947     * framework should attempt to preserve when possible. This flag is reference counted,
6948     * so every call to setHasTransientState(true) should be paired with a later call
6949     * to setHasTransientState(false).
6950     *
6951     * <p>A view with transient state cannot be trivially rebound from an external
6952     * data source, such as an adapter binding item views in a list. This may be
6953     * because the view is performing an animation, tracking user selection
6954     * of content, or similar.</p>
6955     *
6956     * @param hasTransientState true if this view has transient state
6957     */
6958    public void setHasTransientState(boolean hasTransientState) {
6959        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
6960                mTransientStateCount - 1;
6961        if (mTransientStateCount < 0) {
6962            mTransientStateCount = 0;
6963            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
6964                    "unmatched pair of setHasTransientState calls");
6965        } else if ((hasTransientState && mTransientStateCount == 1) ||
6966                (!hasTransientState && mTransientStateCount == 0)) {
6967            // update flag if we've just incremented up from 0 or decremented down to 0
6968            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
6969                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
6970            if (mParent != null) {
6971                try {
6972                    mParent.childHasTransientStateChanged(this, hasTransientState);
6973                } catch (AbstractMethodError e) {
6974                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
6975                            " does not fully implement ViewParent", e);
6976                }
6977            }
6978        }
6979    }
6980
6981    /**
6982     * Returns true if this view is currently attached to a window.
6983     */
6984    public boolean isAttachedToWindow() {
6985        return mAttachInfo != null;
6986    }
6987
6988    /**
6989     * Returns true if this view has been through at least one layout since it
6990     * was last attached to or detached from a window.
6991     */
6992    public boolean isLaidOut() {
6993        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
6994    }
6995
6996    /**
6997     * If this view doesn't do any drawing on its own, set this flag to
6998     * allow further optimizations. By default, this flag is not set on
6999     * View, but could be set on some View subclasses such as ViewGroup.
7000     *
7001     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7002     * you should clear this flag.
7003     *
7004     * @param willNotDraw whether or not this View draw on its own
7005     */
7006    public void setWillNotDraw(boolean willNotDraw) {
7007        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7008    }
7009
7010    /**
7011     * Returns whether or not this View draws on its own.
7012     *
7013     * @return true if this view has nothing to draw, false otherwise
7014     */
7015    @ViewDebug.ExportedProperty(category = "drawing")
7016    public boolean willNotDraw() {
7017        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7018    }
7019
7020    /**
7021     * When a View's drawing cache is enabled, drawing is redirected to an
7022     * offscreen bitmap. Some views, like an ImageView, must be able to
7023     * bypass this mechanism if they already draw a single bitmap, to avoid
7024     * unnecessary usage of the memory.
7025     *
7026     * @param willNotCacheDrawing true if this view does not cache its
7027     *        drawing, false otherwise
7028     */
7029    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7030        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7031    }
7032
7033    /**
7034     * Returns whether or not this View can cache its drawing or not.
7035     *
7036     * @return true if this view does not cache its drawing, false otherwise
7037     */
7038    @ViewDebug.ExportedProperty(category = "drawing")
7039    public boolean willNotCacheDrawing() {
7040        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7041    }
7042
7043    /**
7044     * Indicates whether this view reacts to click events or not.
7045     *
7046     * @return true if the view is clickable, false otherwise
7047     *
7048     * @see #setClickable(boolean)
7049     * @attr ref android.R.styleable#View_clickable
7050     */
7051    @ViewDebug.ExportedProperty
7052    public boolean isClickable() {
7053        return (mViewFlags & CLICKABLE) == CLICKABLE;
7054    }
7055
7056    /**
7057     * Enables or disables click events for this view. When a view
7058     * is clickable it will change its state to "pressed" on every click.
7059     * Subclasses should set the view clickable to visually react to
7060     * user's clicks.
7061     *
7062     * @param clickable true to make the view clickable, false otherwise
7063     *
7064     * @see #isClickable()
7065     * @attr ref android.R.styleable#View_clickable
7066     */
7067    public void setClickable(boolean clickable) {
7068        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7069    }
7070
7071    /**
7072     * Indicates whether this view reacts to long click events or not.
7073     *
7074     * @return true if the view is long clickable, false otherwise
7075     *
7076     * @see #setLongClickable(boolean)
7077     * @attr ref android.R.styleable#View_longClickable
7078     */
7079    public boolean isLongClickable() {
7080        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7081    }
7082
7083    /**
7084     * Enables or disables long click events for this view. When a view is long
7085     * clickable it reacts to the user holding down the button for a longer
7086     * duration than a tap. This event can either launch the listener or a
7087     * context menu.
7088     *
7089     * @param longClickable true to make the view long clickable, false otherwise
7090     * @see #isLongClickable()
7091     * @attr ref android.R.styleable#View_longClickable
7092     */
7093    public void setLongClickable(boolean longClickable) {
7094        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7095    }
7096
7097    /**
7098     * Sets the pressed state for this view and provides a touch coordinate for
7099     * animation hinting.
7100     *
7101     * @param pressed Pass true to set the View's internal state to "pressed",
7102     *            or false to reverts the View's internal state from a
7103     *            previously set "pressed" state.
7104     * @param x The x coordinate of the touch that caused the press
7105     * @param y The y coordinate of the touch that caused the press
7106     */
7107    private void setPressed(boolean pressed, float x, float y) {
7108        if (pressed) {
7109            drawableHotspotChanged(x, y);
7110        }
7111
7112        setPressed(pressed);
7113    }
7114
7115    /**
7116     * Sets the pressed state for this view.
7117     *
7118     * @see #isClickable()
7119     * @see #setClickable(boolean)
7120     *
7121     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7122     *        the View's internal state from a previously set "pressed" state.
7123     */
7124    public void setPressed(boolean pressed) {
7125        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7126
7127        if (pressed) {
7128            mPrivateFlags |= PFLAG_PRESSED;
7129        } else {
7130            mPrivateFlags &= ~PFLAG_PRESSED;
7131        }
7132
7133        if (needsRefresh) {
7134            refreshDrawableState();
7135        }
7136        dispatchSetPressed(pressed);
7137    }
7138
7139    /**
7140     * Dispatch setPressed to all of this View's children.
7141     *
7142     * @see #setPressed(boolean)
7143     *
7144     * @param pressed The new pressed state
7145     */
7146    protected void dispatchSetPressed(boolean pressed) {
7147    }
7148
7149    /**
7150     * Indicates whether the view is currently in pressed state. Unless
7151     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7152     * the pressed state.
7153     *
7154     * @see #setPressed(boolean)
7155     * @see #isClickable()
7156     * @see #setClickable(boolean)
7157     *
7158     * @return true if the view is currently pressed, false otherwise
7159     */
7160    @ViewDebug.ExportedProperty
7161    public boolean isPressed() {
7162        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7163    }
7164
7165    /**
7166     * Indicates whether this view will save its state (that is,
7167     * whether its {@link #onSaveInstanceState} method will be called).
7168     *
7169     * @return Returns true if the view state saving is enabled, else false.
7170     *
7171     * @see #setSaveEnabled(boolean)
7172     * @attr ref android.R.styleable#View_saveEnabled
7173     */
7174    public boolean isSaveEnabled() {
7175        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7176    }
7177
7178    /**
7179     * Controls whether the saving of this view's state is
7180     * enabled (that is, whether its {@link #onSaveInstanceState} method
7181     * will be called).  Note that even if freezing is enabled, the
7182     * view still must have an id assigned to it (via {@link #setId(int)})
7183     * for its state to be saved.  This flag can only disable the
7184     * saving of this view; any child views may still have their state saved.
7185     *
7186     * @param enabled Set to false to <em>disable</em> state saving, or true
7187     * (the default) to allow it.
7188     *
7189     * @see #isSaveEnabled()
7190     * @see #setId(int)
7191     * @see #onSaveInstanceState()
7192     * @attr ref android.R.styleable#View_saveEnabled
7193     */
7194    public void setSaveEnabled(boolean enabled) {
7195        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7196    }
7197
7198    /**
7199     * Gets whether the framework should discard touches when the view's
7200     * window is obscured by another visible window.
7201     * Refer to the {@link View} security documentation for more details.
7202     *
7203     * @return True if touch filtering is enabled.
7204     *
7205     * @see #setFilterTouchesWhenObscured(boolean)
7206     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7207     */
7208    @ViewDebug.ExportedProperty
7209    public boolean getFilterTouchesWhenObscured() {
7210        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7211    }
7212
7213    /**
7214     * Sets whether the framework should discard touches when the view's
7215     * window is obscured by another visible window.
7216     * Refer to the {@link View} security documentation for more details.
7217     *
7218     * @param enabled True if touch filtering should be enabled.
7219     *
7220     * @see #getFilterTouchesWhenObscured
7221     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7222     */
7223    public void setFilterTouchesWhenObscured(boolean enabled) {
7224        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7225                FILTER_TOUCHES_WHEN_OBSCURED);
7226    }
7227
7228    /**
7229     * Indicates whether the entire hierarchy under this view will save its
7230     * state when a state saving traversal occurs from its parent.  The default
7231     * is true; if false, these views will not be saved unless
7232     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7233     *
7234     * @return Returns true if the view state saving from parent is enabled, else false.
7235     *
7236     * @see #setSaveFromParentEnabled(boolean)
7237     */
7238    public boolean isSaveFromParentEnabled() {
7239        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7240    }
7241
7242    /**
7243     * Controls whether the entire hierarchy under this view will save its
7244     * state when a state saving traversal occurs from its parent.  The default
7245     * is true; if false, these views will not be saved unless
7246     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7247     *
7248     * @param enabled Set to false to <em>disable</em> state saving, or true
7249     * (the default) to allow it.
7250     *
7251     * @see #isSaveFromParentEnabled()
7252     * @see #setId(int)
7253     * @see #onSaveInstanceState()
7254     */
7255    public void setSaveFromParentEnabled(boolean enabled) {
7256        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7257    }
7258
7259
7260    /**
7261     * Returns whether this View is able to take focus.
7262     *
7263     * @return True if this view can take focus, or false otherwise.
7264     * @attr ref android.R.styleable#View_focusable
7265     */
7266    @ViewDebug.ExportedProperty(category = "focus")
7267    public final boolean isFocusable() {
7268        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7269    }
7270
7271    /**
7272     * When a view is focusable, it may not want to take focus when in touch mode.
7273     * For example, a button would like focus when the user is navigating via a D-pad
7274     * so that the user can click on it, but once the user starts touching the screen,
7275     * the button shouldn't take focus
7276     * @return Whether the view is focusable in touch mode.
7277     * @attr ref android.R.styleable#View_focusableInTouchMode
7278     */
7279    @ViewDebug.ExportedProperty
7280    public final boolean isFocusableInTouchMode() {
7281        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7282    }
7283
7284    /**
7285     * Find the nearest view in the specified direction that can take focus.
7286     * This does not actually give focus to that view.
7287     *
7288     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7289     *
7290     * @return The nearest focusable in the specified direction, or null if none
7291     *         can be found.
7292     */
7293    public View focusSearch(@FocusRealDirection int direction) {
7294        if (mParent != null) {
7295            return mParent.focusSearch(this, direction);
7296        } else {
7297            return null;
7298        }
7299    }
7300
7301    /**
7302     * This method is the last chance for the focused view and its ancestors to
7303     * respond to an arrow key. This is called when the focused view did not
7304     * consume the key internally, nor could the view system find a new view in
7305     * the requested direction to give focus to.
7306     *
7307     * @param focused The currently focused view.
7308     * @param direction The direction focus wants to move. One of FOCUS_UP,
7309     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7310     * @return True if the this view consumed this unhandled move.
7311     */
7312    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7313        return false;
7314    }
7315
7316    /**
7317     * If a user manually specified the next view id for a particular direction,
7318     * use the root to look up the view.
7319     * @param root The root view of the hierarchy containing this view.
7320     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7321     * or FOCUS_BACKWARD.
7322     * @return The user specified next view, or null if there is none.
7323     */
7324    View findUserSetNextFocus(View root, @FocusDirection int direction) {
7325        switch (direction) {
7326            case FOCUS_LEFT:
7327                if (mNextFocusLeftId == View.NO_ID) return null;
7328                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7329            case FOCUS_RIGHT:
7330                if (mNextFocusRightId == View.NO_ID) return null;
7331                return findViewInsideOutShouldExist(root, mNextFocusRightId);
7332            case FOCUS_UP:
7333                if (mNextFocusUpId == View.NO_ID) return null;
7334                return findViewInsideOutShouldExist(root, mNextFocusUpId);
7335            case FOCUS_DOWN:
7336                if (mNextFocusDownId == View.NO_ID) return null;
7337                return findViewInsideOutShouldExist(root, mNextFocusDownId);
7338            case FOCUS_FORWARD:
7339                if (mNextFocusForwardId == View.NO_ID) return null;
7340                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7341            case FOCUS_BACKWARD: {
7342                if (mID == View.NO_ID) return null;
7343                final int id = mID;
7344                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7345                    @Override
7346                    public boolean apply(View t) {
7347                        return t.mNextFocusForwardId == id;
7348                    }
7349                });
7350            }
7351        }
7352        return null;
7353    }
7354
7355    private View findViewInsideOutShouldExist(View root, int id) {
7356        if (mMatchIdPredicate == null) {
7357            mMatchIdPredicate = new MatchIdPredicate();
7358        }
7359        mMatchIdPredicate.mId = id;
7360        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7361        if (result == null) {
7362            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7363        }
7364        return result;
7365    }
7366
7367    /**
7368     * Find and return all focusable views that are descendants of this view,
7369     * possibly including this view if it is focusable itself.
7370     *
7371     * @param direction The direction of the focus
7372     * @return A list of focusable views
7373     */
7374    public ArrayList<View> getFocusables(@FocusDirection int direction) {
7375        ArrayList<View> result = new ArrayList<View>(24);
7376        addFocusables(result, direction);
7377        return result;
7378    }
7379
7380    /**
7381     * Add any focusable views that are descendants of this view (possibly
7382     * including this view if it is focusable itself) to views.  If we are in touch mode,
7383     * only add views that are also focusable in touch mode.
7384     *
7385     * @param views Focusable views found so far
7386     * @param direction The direction of the focus
7387     */
7388    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7389        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7390    }
7391
7392    /**
7393     * Adds any focusable views that are descendants of this view (possibly
7394     * including this view if it is focusable itself) to views. This method
7395     * adds all focusable views regardless if we are in touch mode or
7396     * only views focusable in touch mode if we are in touch mode or
7397     * only views that can take accessibility focus if accessibility is enabeld
7398     * depending on the focusable mode paramater.
7399     *
7400     * @param views Focusable views found so far or null if all we are interested is
7401     *        the number of focusables.
7402     * @param direction The direction of the focus.
7403     * @param focusableMode The type of focusables to be added.
7404     *
7405     * @see #FOCUSABLES_ALL
7406     * @see #FOCUSABLES_TOUCH_MODE
7407     */
7408    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7409            @FocusableMode int focusableMode) {
7410        if (views == null) {
7411            return;
7412        }
7413        if (!isFocusable()) {
7414            return;
7415        }
7416        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7417                && isInTouchMode() && !isFocusableInTouchMode()) {
7418            return;
7419        }
7420        views.add(this);
7421    }
7422
7423    /**
7424     * Finds the Views that contain given text. The containment is case insensitive.
7425     * The search is performed by either the text that the View renders or the content
7426     * description that describes the view for accessibility purposes and the view does
7427     * not render or both. Clients can specify how the search is to be performed via
7428     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7429     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7430     *
7431     * @param outViews The output list of matching Views.
7432     * @param searched The text to match against.
7433     *
7434     * @see #FIND_VIEWS_WITH_TEXT
7435     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7436     * @see #setContentDescription(CharSequence)
7437     */
7438    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7439            @FindViewFlags int flags) {
7440        if (getAccessibilityNodeProvider() != null) {
7441            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7442                outViews.add(this);
7443            }
7444        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7445                && (searched != null && searched.length() > 0)
7446                && (mContentDescription != null && mContentDescription.length() > 0)) {
7447            String searchedLowerCase = searched.toString().toLowerCase();
7448            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7449            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7450                outViews.add(this);
7451            }
7452        }
7453    }
7454
7455    /**
7456     * Find and return all touchable views that are descendants of this view,
7457     * possibly including this view if it is touchable itself.
7458     *
7459     * @return A list of touchable views
7460     */
7461    public ArrayList<View> getTouchables() {
7462        ArrayList<View> result = new ArrayList<View>();
7463        addTouchables(result);
7464        return result;
7465    }
7466
7467    /**
7468     * Add any touchable views that are descendants of this view (possibly
7469     * including this view if it is touchable itself) to views.
7470     *
7471     * @param views Touchable views found so far
7472     */
7473    public void addTouchables(ArrayList<View> views) {
7474        final int viewFlags = mViewFlags;
7475
7476        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7477                && (viewFlags & ENABLED_MASK) == ENABLED) {
7478            views.add(this);
7479        }
7480    }
7481
7482    /**
7483     * Returns whether this View is accessibility focused.
7484     *
7485     * @return True if this View is accessibility focused.
7486     */
7487    public boolean isAccessibilityFocused() {
7488        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7489    }
7490
7491    /**
7492     * Call this to try to give accessibility focus to this view.
7493     *
7494     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7495     * returns false or the view is no visible or the view already has accessibility
7496     * focus.
7497     *
7498     * See also {@link #focusSearch(int)}, which is what you call to say that you
7499     * have focus, and you want your parent to look for the next one.
7500     *
7501     * @return Whether this view actually took accessibility focus.
7502     *
7503     * @hide
7504     */
7505    public boolean requestAccessibilityFocus() {
7506        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7507        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7508            return false;
7509        }
7510        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7511            return false;
7512        }
7513        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7514            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7515            ViewRootImpl viewRootImpl = getViewRootImpl();
7516            if (viewRootImpl != null) {
7517                viewRootImpl.setAccessibilityFocus(this, null);
7518            }
7519            invalidate();
7520            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7521            return true;
7522        }
7523        return false;
7524    }
7525
7526    /**
7527     * Call this to try to clear accessibility focus of this view.
7528     *
7529     * See also {@link #focusSearch(int)}, which is what you call to say that you
7530     * have focus, and you want your parent to look for the next one.
7531     *
7532     * @hide
7533     */
7534    public void clearAccessibilityFocus() {
7535        clearAccessibilityFocusNoCallbacks();
7536        // Clear the global reference of accessibility focus if this
7537        // view or any of its descendants had accessibility focus.
7538        ViewRootImpl viewRootImpl = getViewRootImpl();
7539        if (viewRootImpl != null) {
7540            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7541            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7542                viewRootImpl.setAccessibilityFocus(null, null);
7543            }
7544        }
7545    }
7546
7547    private void sendAccessibilityHoverEvent(int eventType) {
7548        // Since we are not delivering to a client accessibility events from not
7549        // important views (unless the clinet request that) we need to fire the
7550        // event from the deepest view exposed to the client. As a consequence if
7551        // the user crosses a not exposed view the client will see enter and exit
7552        // of the exposed predecessor followed by and enter and exit of that same
7553        // predecessor when entering and exiting the not exposed descendant. This
7554        // is fine since the client has a clear idea which view is hovered at the
7555        // price of a couple more events being sent. This is a simple and
7556        // working solution.
7557        View source = this;
7558        while (true) {
7559            if (source.includeForAccessibility()) {
7560                source.sendAccessibilityEvent(eventType);
7561                return;
7562            }
7563            ViewParent parent = source.getParent();
7564            if (parent instanceof View) {
7565                source = (View) parent;
7566            } else {
7567                return;
7568            }
7569        }
7570    }
7571
7572    /**
7573     * Clears accessibility focus without calling any callback methods
7574     * normally invoked in {@link #clearAccessibilityFocus()}. This method
7575     * is used for clearing accessibility focus when giving this focus to
7576     * another view.
7577     */
7578    void clearAccessibilityFocusNoCallbacks() {
7579        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7580            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7581            invalidate();
7582            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7583        }
7584    }
7585
7586    /**
7587     * Call this to try to give focus to a specific view or to one of its
7588     * descendants.
7589     *
7590     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7591     * false), or if it is focusable and it is not focusable in touch mode
7592     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7593     *
7594     * See also {@link #focusSearch(int)}, which is what you call to say that you
7595     * have focus, and you want your parent to look for the next one.
7596     *
7597     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7598     * {@link #FOCUS_DOWN} and <code>null</code>.
7599     *
7600     * @return Whether this view or one of its descendants actually took focus.
7601     */
7602    public final boolean requestFocus() {
7603        return requestFocus(View.FOCUS_DOWN);
7604    }
7605
7606    /**
7607     * Call this to try to give focus to a specific view or to one of its
7608     * descendants and give it a hint about what direction focus is heading.
7609     *
7610     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7611     * false), or if it is focusable and it is not focusable in touch mode
7612     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7613     *
7614     * See also {@link #focusSearch(int)}, which is what you call to say that you
7615     * have focus, and you want your parent to look for the next one.
7616     *
7617     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7618     * <code>null</code> set for the previously focused rectangle.
7619     *
7620     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7621     * @return Whether this view or one of its descendants actually took focus.
7622     */
7623    public final boolean requestFocus(int direction) {
7624        return requestFocus(direction, null);
7625    }
7626
7627    /**
7628     * Call this to try to give focus to a specific view or to one of its descendants
7629     * and give it hints about the direction and a specific rectangle that the focus
7630     * is coming from.  The rectangle can help give larger views a finer grained hint
7631     * about where focus is coming from, and therefore, where to show selection, or
7632     * forward focus change internally.
7633     *
7634     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7635     * false), or if it is focusable and it is not focusable in touch mode
7636     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7637     *
7638     * A View will not take focus if it is not visible.
7639     *
7640     * A View will not take focus if one of its parents has
7641     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7642     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7643     *
7644     * See also {@link #focusSearch(int)}, which is what you call to say that you
7645     * have focus, and you want your parent to look for the next one.
7646     *
7647     * You may wish to override this method if your custom {@link View} has an internal
7648     * {@link View} that it wishes to forward the request to.
7649     *
7650     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7651     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7652     *        to give a finer grained hint about where focus is coming from.  May be null
7653     *        if there is no hint.
7654     * @return Whether this view or one of its descendants actually took focus.
7655     */
7656    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7657        return requestFocusNoSearch(direction, previouslyFocusedRect);
7658    }
7659
7660    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7661        // need to be focusable
7662        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7663                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7664            return false;
7665        }
7666
7667        // need to be focusable in touch mode if in touch mode
7668        if (isInTouchMode() &&
7669            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7670               return false;
7671        }
7672
7673        // need to not have any parents blocking us
7674        if (hasAncestorThatBlocksDescendantFocus()) {
7675            return false;
7676        }
7677
7678        handleFocusGainInternal(direction, previouslyFocusedRect);
7679        return true;
7680    }
7681
7682    /**
7683     * Call this to try to give focus to a specific view or to one of its descendants. This is a
7684     * special variant of {@link #requestFocus() } that will allow views that are not focuable in
7685     * touch mode to request focus when they are touched.
7686     *
7687     * @return Whether this view or one of its descendants actually took focus.
7688     *
7689     * @see #isInTouchMode()
7690     *
7691     */
7692    public final boolean requestFocusFromTouch() {
7693        // Leave touch mode if we need to
7694        if (isInTouchMode()) {
7695            ViewRootImpl viewRoot = getViewRootImpl();
7696            if (viewRoot != null) {
7697                viewRoot.ensureTouchMode(false);
7698            }
7699        }
7700        return requestFocus(View.FOCUS_DOWN);
7701    }
7702
7703    /**
7704     * @return Whether any ancestor of this view blocks descendant focus.
7705     */
7706    private boolean hasAncestorThatBlocksDescendantFocus() {
7707        final boolean focusableInTouchMode = isFocusableInTouchMode();
7708        ViewParent ancestor = mParent;
7709        while (ancestor instanceof ViewGroup) {
7710            final ViewGroup vgAncestor = (ViewGroup) ancestor;
7711            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7712                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
7713                return true;
7714            } else {
7715                ancestor = vgAncestor.getParent();
7716            }
7717        }
7718        return false;
7719    }
7720
7721    /**
7722     * Gets the mode for determining whether this View is important for accessibility
7723     * which is if it fires accessibility events and if it is reported to
7724     * accessibility services that query the screen.
7725     *
7726     * @return The mode for determining whether a View is important for accessibility.
7727     *
7728     * @attr ref android.R.styleable#View_importantForAccessibility
7729     *
7730     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7731     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7732     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7733     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7734     */
7735    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7736            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7737            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7738            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7739            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7740                    to = "noHideDescendants")
7741        })
7742    public int getImportantForAccessibility() {
7743        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7744                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7745    }
7746
7747    /**
7748     * Sets the live region mode for this view. This indicates to accessibility
7749     * services whether they should automatically notify the user about changes
7750     * to the view's content description or text, or to the content descriptions
7751     * or text of the view's children (where applicable).
7752     * <p>
7753     * For example, in a login screen with a TextView that displays an "incorrect
7754     * password" notification, that view should be marked as a live region with
7755     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7756     * <p>
7757     * To disable change notifications for this view, use
7758     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7759     * mode for most views.
7760     * <p>
7761     * To indicate that the user should be notified of changes, use
7762     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7763     * <p>
7764     * If the view's changes should interrupt ongoing speech and notify the user
7765     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7766     *
7767     * @param mode The live region mode for this view, one of:
7768     *        <ul>
7769     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7770     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7771     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7772     *        </ul>
7773     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7774     */
7775    public void setAccessibilityLiveRegion(int mode) {
7776        if (mode != getAccessibilityLiveRegion()) {
7777            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7778            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7779                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7780            notifyViewAccessibilityStateChangedIfNeeded(
7781                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7782        }
7783    }
7784
7785    /**
7786     * Gets the live region mode for this View.
7787     *
7788     * @return The live region mode for the view.
7789     *
7790     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7791     *
7792     * @see #setAccessibilityLiveRegion(int)
7793     */
7794    public int getAccessibilityLiveRegion() {
7795        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
7796                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
7797    }
7798
7799    /**
7800     * Sets how to determine whether this view is important for accessibility
7801     * which is if it fires accessibility events and if it is reported to
7802     * accessibility services that query the screen.
7803     *
7804     * @param mode How to determine whether this view is important for accessibility.
7805     *
7806     * @attr ref android.R.styleable#View_importantForAccessibility
7807     *
7808     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7809     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7810     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7811     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7812     */
7813    public void setImportantForAccessibility(int mode) {
7814        final int oldMode = getImportantForAccessibility();
7815        if (mode != oldMode) {
7816            // If we're moving between AUTO and another state, we might not need
7817            // to send a subtree changed notification. We'll store the computed
7818            // importance, since we'll need to check it later to make sure.
7819            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
7820                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
7821            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
7822            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7823            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
7824                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
7825            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
7826                notifySubtreeAccessibilityStateChangedIfNeeded();
7827            } else {
7828                notifyViewAccessibilityStateChangedIfNeeded(
7829                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
7830            }
7831        }
7832    }
7833
7834    /**
7835     * Computes whether this view should be exposed for accessibility. In
7836     * general, views that are interactive or provide information are exposed
7837     * while views that serve only as containers are hidden.
7838     * <p>
7839     * If an ancestor of this view has importance
7840     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
7841     * returns <code>false</code>.
7842     * <p>
7843     * Otherwise, the value is computed according to the view's
7844     * {@link #getImportantForAccessibility()} value:
7845     * <ol>
7846     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
7847     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
7848     * </code>
7849     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
7850     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
7851     * view satisfies any of the following:
7852     * <ul>
7853     * <li>Is actionable, e.g. {@link #isClickable()},
7854     * {@link #isLongClickable()}, or {@link #isFocusable()}
7855     * <li>Has an {@link AccessibilityDelegate}
7856     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
7857     * {@link OnKeyListener}, etc.
7858     * <li>Is an accessibility live region, e.g.
7859     * {@link #getAccessibilityLiveRegion()} is not
7860     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
7861     * </ul>
7862     * </ol>
7863     *
7864     * @return Whether the view is exposed for accessibility.
7865     * @see #setImportantForAccessibility(int)
7866     * @see #getImportantForAccessibility()
7867     */
7868    public boolean isImportantForAccessibility() {
7869        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7870                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7871        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
7872                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7873            return false;
7874        }
7875
7876        // Check parent mode to ensure we're not hidden.
7877        ViewParent parent = mParent;
7878        while (parent instanceof View) {
7879            if (((View) parent).getImportantForAccessibility()
7880                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
7881                return false;
7882            }
7883            parent = parent.getParent();
7884        }
7885
7886        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
7887                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
7888                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
7889    }
7890
7891    /**
7892     * Gets the parent for accessibility purposes. Note that the parent for
7893     * accessibility is not necessary the immediate parent. It is the first
7894     * predecessor that is important for accessibility.
7895     *
7896     * @return The parent for accessibility purposes.
7897     */
7898    public ViewParent getParentForAccessibility() {
7899        if (mParent instanceof View) {
7900            View parentView = (View) mParent;
7901            if (parentView.includeForAccessibility()) {
7902                return mParent;
7903            } else {
7904                return mParent.getParentForAccessibility();
7905            }
7906        }
7907        return null;
7908    }
7909
7910    /**
7911     * Adds the children of a given View for accessibility. Since some Views are
7912     * not important for accessibility the children for accessibility are not
7913     * necessarily direct children of the view, rather they are the first level of
7914     * descendants important for accessibility.
7915     *
7916     * @param children The list of children for accessibility.
7917     */
7918    public void addChildrenForAccessibility(ArrayList<View> children) {
7919
7920    }
7921
7922    /**
7923     * Whether to regard this view for accessibility. A view is regarded for
7924     * accessibility if it is important for accessibility or the querying
7925     * accessibility service has explicitly requested that view not
7926     * important for accessibility are regarded.
7927     *
7928     * @return Whether to regard the view for accessibility.
7929     *
7930     * @hide
7931     */
7932    public boolean includeForAccessibility() {
7933        if (mAttachInfo != null) {
7934            return (mAttachInfo.mAccessibilityFetchFlags
7935                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
7936                    || isImportantForAccessibility();
7937        }
7938        return false;
7939    }
7940
7941    /**
7942     * Returns whether the View is considered actionable from
7943     * accessibility perspective. Such view are important for
7944     * accessibility.
7945     *
7946     * @return True if the view is actionable for accessibility.
7947     *
7948     * @hide
7949     */
7950    public boolean isActionableForAccessibility() {
7951        return (isClickable() || isLongClickable() || isFocusable());
7952    }
7953
7954    /**
7955     * Returns whether the View has registered callbacks which makes it
7956     * important for accessibility.
7957     *
7958     * @return True if the view is actionable for accessibility.
7959     */
7960    private boolean hasListenersForAccessibility() {
7961        ListenerInfo info = getListenerInfo();
7962        return mTouchDelegate != null || info.mOnKeyListener != null
7963                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
7964                || info.mOnHoverListener != null || info.mOnDragListener != null;
7965    }
7966
7967    /**
7968     * Notifies that the accessibility state of this view changed. The change
7969     * is local to this view and does not represent structural changes such
7970     * as children and parent. For example, the view became focusable. The
7971     * notification is at at most once every
7972     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7973     * to avoid unnecessary load to the system. Also once a view has a pending
7974     * notification this method is a NOP until the notification has been sent.
7975     *
7976     * @hide
7977     */
7978    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
7979        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
7980            return;
7981        }
7982        if (mSendViewStateChangedAccessibilityEvent == null) {
7983            mSendViewStateChangedAccessibilityEvent =
7984                    new SendViewStateChangedAccessibilityEvent();
7985        }
7986        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
7987    }
7988
7989    /**
7990     * Notifies that the accessibility state of this view changed. The change
7991     * is *not* local to this view and does represent structural changes such
7992     * as children and parent. For example, the view size changed. The
7993     * notification is at at most once every
7994     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
7995     * to avoid unnecessary load to the system. Also once a view has a pending
7996     * notification this method is a NOP until the notification has been sent.
7997     *
7998     * @hide
7999     */
8000    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8001        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8002            return;
8003        }
8004        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8005            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8006            if (mParent != null) {
8007                try {
8008                    mParent.notifySubtreeAccessibilityStateChanged(
8009                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8010                } catch (AbstractMethodError e) {
8011                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8012                            " does not fully implement ViewParent", e);
8013                }
8014            }
8015        }
8016    }
8017
8018    /**
8019     * Reset the flag indicating the accessibility state of the subtree rooted
8020     * at this view changed.
8021     */
8022    void resetSubtreeAccessibilityStateChanged() {
8023        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8024    }
8025
8026    /**
8027     * Report an accessibility action to this view's parents for delegated processing.
8028     *
8029     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8030     * call this method to delegate an accessibility action to a supporting parent. If the parent
8031     * returns true from its
8032     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8033     * method this method will return true to signify that the action was consumed.</p>
8034     *
8035     * <p>This method is useful for implementing nested scrolling child views. If
8036     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8037     * a custom view implementation may invoke this method to allow a parent to consume the
8038     * scroll first. If this method returns true the custom view should skip its own scrolling
8039     * behavior.</p>
8040     *
8041     * @param action Accessibility action to delegate
8042     * @param arguments Optional action arguments
8043     * @return true if the action was consumed by a parent
8044     */
8045    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8046        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8047            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8048                return true;
8049            }
8050        }
8051        return false;
8052    }
8053
8054    /**
8055     * Performs the specified accessibility action on the view. For
8056     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8057     * <p>
8058     * If an {@link AccessibilityDelegate} has been specified via calling
8059     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8060     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8061     * is responsible for handling this call.
8062     * </p>
8063     *
8064     * <p>The default implementation will delegate
8065     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8066     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8067     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8068     *
8069     * @param action The action to perform.
8070     * @param arguments Optional action arguments.
8071     * @return Whether the action was performed.
8072     */
8073    public boolean performAccessibilityAction(int action, Bundle arguments) {
8074      if (mAccessibilityDelegate != null) {
8075          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8076      } else {
8077          return performAccessibilityActionInternal(action, arguments);
8078      }
8079    }
8080
8081   /**
8082    * @see #performAccessibilityAction(int, Bundle)
8083    *
8084    * Note: Called from the default {@link AccessibilityDelegate}.
8085    *
8086    * @hide Until we've refactored all accessibility delegation methods.
8087    */
8088    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8089        if (isNestedScrollingEnabled()
8090                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8091                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
8092            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8093                return true;
8094            }
8095        }
8096
8097        switch (action) {
8098            case AccessibilityNodeInfo.ACTION_CLICK: {
8099                if (isClickable()) {
8100                    performClick();
8101                    return true;
8102                }
8103            } break;
8104            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8105                if (isLongClickable()) {
8106                    performLongClick();
8107                    return true;
8108                }
8109            } break;
8110            case AccessibilityNodeInfo.ACTION_FOCUS: {
8111                if (!hasFocus()) {
8112                    // Get out of touch mode since accessibility
8113                    // wants to move focus around.
8114                    getViewRootImpl().ensureTouchMode(false);
8115                    return requestFocus();
8116                }
8117            } break;
8118            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8119                if (hasFocus()) {
8120                    clearFocus();
8121                    return !isFocused();
8122                }
8123            } break;
8124            case AccessibilityNodeInfo.ACTION_SELECT: {
8125                if (!isSelected()) {
8126                    setSelected(true);
8127                    return isSelected();
8128                }
8129            } break;
8130            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8131                if (isSelected()) {
8132                    setSelected(false);
8133                    return !isSelected();
8134                }
8135            } break;
8136            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8137                if (!isAccessibilityFocused()) {
8138                    return requestAccessibilityFocus();
8139                }
8140            } break;
8141            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8142                if (isAccessibilityFocused()) {
8143                    clearAccessibilityFocus();
8144                    return true;
8145                }
8146            } break;
8147            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8148                if (arguments != null) {
8149                    final int granularity = arguments.getInt(
8150                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8151                    final boolean extendSelection = arguments.getBoolean(
8152                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8153                    return traverseAtGranularity(granularity, true, extendSelection);
8154                }
8155            } break;
8156            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8157                if (arguments != null) {
8158                    final int granularity = arguments.getInt(
8159                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8160                    final boolean extendSelection = arguments.getBoolean(
8161                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8162                    return traverseAtGranularity(granularity, false, extendSelection);
8163                }
8164            } break;
8165            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8166                CharSequence text = getIterableTextForAccessibility();
8167                if (text == null) {
8168                    return false;
8169                }
8170                final int start = (arguments != null) ? arguments.getInt(
8171                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8172                final int end = (arguments != null) ? arguments.getInt(
8173                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8174                // Only cursor position can be specified (selection length == 0)
8175                if ((getAccessibilitySelectionStart() != start
8176                        || getAccessibilitySelectionEnd() != end)
8177                        && (start == end)) {
8178                    setAccessibilitySelection(start, end);
8179                    notifyViewAccessibilityStateChangedIfNeeded(
8180                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8181                    return true;
8182                }
8183            } break;
8184        }
8185        return false;
8186    }
8187
8188    private boolean traverseAtGranularity(int granularity, boolean forward,
8189            boolean extendSelection) {
8190        CharSequence text = getIterableTextForAccessibility();
8191        if (text == null || text.length() == 0) {
8192            return false;
8193        }
8194        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8195        if (iterator == null) {
8196            return false;
8197        }
8198        int current = getAccessibilitySelectionEnd();
8199        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8200            current = forward ? 0 : text.length();
8201        }
8202        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8203        if (range == null) {
8204            return false;
8205        }
8206        final int segmentStart = range[0];
8207        final int segmentEnd = range[1];
8208        int selectionStart;
8209        int selectionEnd;
8210        if (extendSelection && isAccessibilitySelectionExtendable()) {
8211            selectionStart = getAccessibilitySelectionStart();
8212            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8213                selectionStart = forward ? segmentStart : segmentEnd;
8214            }
8215            selectionEnd = forward ? segmentEnd : segmentStart;
8216        } else {
8217            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8218        }
8219        setAccessibilitySelection(selectionStart, selectionEnd);
8220        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8221                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8222        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8223        return true;
8224    }
8225
8226    /**
8227     * Gets the text reported for accessibility purposes.
8228     *
8229     * @return The accessibility text.
8230     *
8231     * @hide
8232     */
8233    public CharSequence getIterableTextForAccessibility() {
8234        return getContentDescription();
8235    }
8236
8237    /**
8238     * Gets whether accessibility selection can be extended.
8239     *
8240     * @return If selection is extensible.
8241     *
8242     * @hide
8243     */
8244    public boolean isAccessibilitySelectionExtendable() {
8245        return false;
8246    }
8247
8248    /**
8249     * @hide
8250     */
8251    public int getAccessibilitySelectionStart() {
8252        return mAccessibilityCursorPosition;
8253    }
8254
8255    /**
8256     * @hide
8257     */
8258    public int getAccessibilitySelectionEnd() {
8259        return getAccessibilitySelectionStart();
8260    }
8261
8262    /**
8263     * @hide
8264     */
8265    public void setAccessibilitySelection(int start, int end) {
8266        if (start ==  end && end == mAccessibilityCursorPosition) {
8267            return;
8268        }
8269        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8270            mAccessibilityCursorPosition = start;
8271        } else {
8272            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8273        }
8274        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8275    }
8276
8277    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8278            int fromIndex, int toIndex) {
8279        if (mParent == null) {
8280            return;
8281        }
8282        AccessibilityEvent event = AccessibilityEvent.obtain(
8283                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8284        onInitializeAccessibilityEvent(event);
8285        onPopulateAccessibilityEvent(event);
8286        event.setFromIndex(fromIndex);
8287        event.setToIndex(toIndex);
8288        event.setAction(action);
8289        event.setMovementGranularity(granularity);
8290        mParent.requestSendAccessibilityEvent(this, event);
8291    }
8292
8293    /**
8294     * @hide
8295     */
8296    public TextSegmentIterator getIteratorForGranularity(int granularity) {
8297        switch (granularity) {
8298            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8299                CharSequence text = getIterableTextForAccessibility();
8300                if (text != null && text.length() > 0) {
8301                    CharacterTextSegmentIterator iterator =
8302                        CharacterTextSegmentIterator.getInstance(
8303                                mContext.getResources().getConfiguration().locale);
8304                    iterator.initialize(text.toString());
8305                    return iterator;
8306                }
8307            } break;
8308            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8309                CharSequence text = getIterableTextForAccessibility();
8310                if (text != null && text.length() > 0) {
8311                    WordTextSegmentIterator iterator =
8312                        WordTextSegmentIterator.getInstance(
8313                                mContext.getResources().getConfiguration().locale);
8314                    iterator.initialize(text.toString());
8315                    return iterator;
8316                }
8317            } break;
8318            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8319                CharSequence text = getIterableTextForAccessibility();
8320                if (text != null && text.length() > 0) {
8321                    ParagraphTextSegmentIterator iterator =
8322                        ParagraphTextSegmentIterator.getInstance();
8323                    iterator.initialize(text.toString());
8324                    return iterator;
8325                }
8326            } break;
8327        }
8328        return null;
8329    }
8330
8331    /**
8332     * @hide
8333     */
8334    public void dispatchStartTemporaryDetach() {
8335        onStartTemporaryDetach();
8336    }
8337
8338    /**
8339     * This is called when a container is going to temporarily detach a child, with
8340     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8341     * It will either be followed by {@link #onFinishTemporaryDetach()} or
8342     * {@link #onDetachedFromWindow()} when the container is done.
8343     */
8344    public void onStartTemporaryDetach() {
8345        removeUnsetPressCallback();
8346        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8347    }
8348
8349    /**
8350     * @hide
8351     */
8352    public void dispatchFinishTemporaryDetach() {
8353        onFinishTemporaryDetach();
8354    }
8355
8356    /**
8357     * Called after {@link #onStartTemporaryDetach} when the container is done
8358     * changing the view.
8359     */
8360    public void onFinishTemporaryDetach() {
8361    }
8362
8363    /**
8364     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8365     * for this view's window.  Returns null if the view is not currently attached
8366     * to the window.  Normally you will not need to use this directly, but
8367     * just use the standard high-level event callbacks like
8368     * {@link #onKeyDown(int, KeyEvent)}.
8369     */
8370    public KeyEvent.DispatcherState getKeyDispatcherState() {
8371        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8372    }
8373
8374    /**
8375     * Dispatch a key event before it is processed by any input method
8376     * associated with the view hierarchy.  This can be used to intercept
8377     * key events in special situations before the IME consumes them; a
8378     * typical example would be handling the BACK key to update the application's
8379     * UI instead of allowing the IME to see it and close itself.
8380     *
8381     * @param event The key event to be dispatched.
8382     * @return True if the event was handled, false otherwise.
8383     */
8384    public boolean dispatchKeyEventPreIme(KeyEvent event) {
8385        return onKeyPreIme(event.getKeyCode(), event);
8386    }
8387
8388    /**
8389     * Dispatch a key event to the next view on the focus path. This path runs
8390     * from the top of the view tree down to the currently focused view. If this
8391     * view has focus, it will dispatch to itself. Otherwise it will dispatch
8392     * the next node down the focus path. This method also fires any key
8393     * listeners.
8394     *
8395     * @param event The key event to be dispatched.
8396     * @return True if the event was handled, false otherwise.
8397     */
8398    public boolean dispatchKeyEvent(KeyEvent event) {
8399        if (mInputEventConsistencyVerifier != null) {
8400            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8401        }
8402
8403        // Give any attached key listener a first crack at the event.
8404        //noinspection SimplifiableIfStatement
8405        ListenerInfo li = mListenerInfo;
8406        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8407                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8408            return true;
8409        }
8410
8411        if (event.dispatch(this, mAttachInfo != null
8412                ? mAttachInfo.mKeyDispatchState : null, this)) {
8413            return true;
8414        }
8415
8416        if (mInputEventConsistencyVerifier != null) {
8417            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8418        }
8419        return false;
8420    }
8421
8422    /**
8423     * Dispatches a key shortcut event.
8424     *
8425     * @param event The key event to be dispatched.
8426     * @return True if the event was handled by the view, false otherwise.
8427     */
8428    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8429        return onKeyShortcut(event.getKeyCode(), event);
8430    }
8431
8432    /**
8433     * Pass the touch screen motion event down to the target view, or this
8434     * view if it is the target.
8435     *
8436     * @param event The motion event to be dispatched.
8437     * @return True if the event was handled by the view, false otherwise.
8438     */
8439    public boolean dispatchTouchEvent(MotionEvent event) {
8440        // If the event should be handled by accessibility focus first.
8441        if (event.isTargetAccessibilityFocus()) {
8442            // We don't have focus or no virtual descendant has it, do not handle the event.
8443            if (!isAccessibilityFocusedViewOrHost()) {
8444                return false;
8445            }
8446            // We have focus and got the event, then use normal event dispatch.
8447            event.setTargetAccessibilityFocus(false);
8448        }
8449
8450        boolean result = false;
8451
8452        if (mInputEventConsistencyVerifier != null) {
8453            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8454        }
8455
8456        final int actionMasked = event.getActionMasked();
8457        if (actionMasked == MotionEvent.ACTION_DOWN) {
8458            // Defensive cleanup for new gesture
8459            stopNestedScroll();
8460        }
8461
8462        if (onFilterTouchEventForSecurity(event)) {
8463            //noinspection SimplifiableIfStatement
8464            ListenerInfo li = mListenerInfo;
8465            if (li != null && li.mOnTouchListener != null
8466                    && (mViewFlags & ENABLED_MASK) == ENABLED
8467                    && li.mOnTouchListener.onTouch(this, event)) {
8468                result = true;
8469            }
8470
8471            if (!result && onTouchEvent(event)) {
8472                result = true;
8473            }
8474        }
8475
8476        if (!result && mInputEventConsistencyVerifier != null) {
8477            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8478        }
8479
8480        // Clean up after nested scrolls if this is the end of a gesture;
8481        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8482        // of the gesture.
8483        if (actionMasked == MotionEvent.ACTION_UP ||
8484                actionMasked == MotionEvent.ACTION_CANCEL ||
8485                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8486            stopNestedScroll();
8487        }
8488
8489        return result;
8490    }
8491
8492    boolean isAccessibilityFocusedViewOrHost() {
8493        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
8494                .getAccessibilityFocusedHost() == this);
8495    }
8496
8497    /**
8498     * Filter the touch event to apply security policies.
8499     *
8500     * @param event The motion event to be filtered.
8501     * @return True if the event should be dispatched, false if the event should be dropped.
8502     *
8503     * @see #getFilterTouchesWhenObscured
8504     */
8505    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8506        //noinspection RedundantIfStatement
8507        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8508                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8509            // Window is obscured, drop this touch.
8510            return false;
8511        }
8512        return true;
8513    }
8514
8515    /**
8516     * Pass a trackball motion event down to the focused view.
8517     *
8518     * @param event The motion event to be dispatched.
8519     * @return True if the event was handled by the view, false otherwise.
8520     */
8521    public boolean dispatchTrackballEvent(MotionEvent event) {
8522        if (mInputEventConsistencyVerifier != null) {
8523            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8524        }
8525
8526        return onTrackballEvent(event);
8527    }
8528
8529    /**
8530     * Dispatch a generic motion event.
8531     * <p>
8532     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8533     * are delivered to the view under the pointer.  All other generic motion events are
8534     * delivered to the focused view.  Hover events are handled specially and are delivered
8535     * to {@link #onHoverEvent(MotionEvent)}.
8536     * </p>
8537     *
8538     * @param event The motion event to be dispatched.
8539     * @return True if the event was handled by the view, false otherwise.
8540     */
8541    public boolean dispatchGenericMotionEvent(MotionEvent event) {
8542        if (mInputEventConsistencyVerifier != null) {
8543            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8544        }
8545
8546        final int source = event.getSource();
8547        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8548            final int action = event.getAction();
8549            if (action == MotionEvent.ACTION_HOVER_ENTER
8550                    || action == MotionEvent.ACTION_HOVER_MOVE
8551                    || action == MotionEvent.ACTION_HOVER_EXIT) {
8552                if (dispatchHoverEvent(event)) {
8553                    return true;
8554                }
8555            } else if (dispatchGenericPointerEvent(event)) {
8556                return true;
8557            }
8558        } else if (dispatchGenericFocusedEvent(event)) {
8559            return true;
8560        }
8561
8562        if (dispatchGenericMotionEventInternal(event)) {
8563            return true;
8564        }
8565
8566        if (mInputEventConsistencyVerifier != null) {
8567            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8568        }
8569        return false;
8570    }
8571
8572    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8573        //noinspection SimplifiableIfStatement
8574        ListenerInfo li = mListenerInfo;
8575        if (li != null && li.mOnGenericMotionListener != null
8576                && (mViewFlags & ENABLED_MASK) == ENABLED
8577                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8578            return true;
8579        }
8580
8581        if (onGenericMotionEvent(event)) {
8582            return true;
8583        }
8584
8585        if (mInputEventConsistencyVerifier != null) {
8586            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8587        }
8588        return false;
8589    }
8590
8591    /**
8592     * Dispatch a hover event.
8593     * <p>
8594     * Do not call this method directly.
8595     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8596     * </p>
8597     *
8598     * @param event The motion event to be dispatched.
8599     * @return True if the event was handled by the view, false otherwise.
8600     */
8601    protected boolean dispatchHoverEvent(MotionEvent event) {
8602        ListenerInfo li = mListenerInfo;
8603        //noinspection SimplifiableIfStatement
8604        if (li != null && li.mOnHoverListener != null
8605                && (mViewFlags & ENABLED_MASK) == ENABLED
8606                && li.mOnHoverListener.onHover(this, event)) {
8607            return true;
8608        }
8609
8610        return onHoverEvent(event);
8611    }
8612
8613    /**
8614     * Returns true if the view has a child to which it has recently sent
8615     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8616     * it does not have a hovered child, then it must be the innermost hovered view.
8617     * @hide
8618     */
8619    protected boolean hasHoveredChild() {
8620        return false;
8621    }
8622
8623    /**
8624     * Dispatch a generic motion event to the view under the first pointer.
8625     * <p>
8626     * Do not call this method directly.
8627     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8628     * </p>
8629     *
8630     * @param event The motion event to be dispatched.
8631     * @return True if the event was handled by the view, false otherwise.
8632     */
8633    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8634        return false;
8635    }
8636
8637    /**
8638     * Dispatch a generic motion event to the currently focused view.
8639     * <p>
8640     * Do not call this method directly.
8641     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8642     * </p>
8643     *
8644     * @param event The motion event to be dispatched.
8645     * @return True if the event was handled by the view, false otherwise.
8646     */
8647    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8648        return false;
8649    }
8650
8651    /**
8652     * Dispatch a pointer event.
8653     * <p>
8654     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8655     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
8656     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8657     * and should not be expected to handle other pointing device features.
8658     * </p>
8659     *
8660     * @param event The motion event to be dispatched.
8661     * @return True if the event was handled by the view, false otherwise.
8662     * @hide
8663     */
8664    public final boolean dispatchPointerEvent(MotionEvent event) {
8665        if (event.isTouchEvent()) {
8666            return dispatchTouchEvent(event);
8667        } else {
8668            return dispatchGenericMotionEvent(event);
8669        }
8670    }
8671
8672    /**
8673     * Called when the window containing this view gains or loses window focus.
8674     * ViewGroups should override to route to their children.
8675     *
8676     * @param hasFocus True if the window containing this view now has focus,
8677     *        false otherwise.
8678     */
8679    public void dispatchWindowFocusChanged(boolean hasFocus) {
8680        onWindowFocusChanged(hasFocus);
8681    }
8682
8683    /**
8684     * Called when the window containing this view gains or loses focus.  Note
8685     * that this is separate from view focus: to receive key events, both
8686     * your view and its window must have focus.  If a window is displayed
8687     * on top of yours that takes input focus, then your own window will lose
8688     * focus but the view focus will remain unchanged.
8689     *
8690     * @param hasWindowFocus True if the window containing this view now has
8691     *        focus, false otherwise.
8692     */
8693    public void onWindowFocusChanged(boolean hasWindowFocus) {
8694        InputMethodManager imm = InputMethodManager.peekInstance();
8695        if (!hasWindowFocus) {
8696            if (isPressed()) {
8697                setPressed(false);
8698            }
8699            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8700                imm.focusOut(this);
8701            }
8702            removeLongPressCallback();
8703            removeTapCallback();
8704            onFocusLost();
8705        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8706            imm.focusIn(this);
8707        }
8708        refreshDrawableState();
8709    }
8710
8711    /**
8712     * Returns true if this view is in a window that currently has window focus.
8713     * Note that this is not the same as the view itself having focus.
8714     *
8715     * @return True if this view is in a window that currently has window focus.
8716     */
8717    public boolean hasWindowFocus() {
8718        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8719    }
8720
8721    /**
8722     * Dispatch a view visibility change down the view hierarchy.
8723     * ViewGroups should override to route to their children.
8724     * @param changedView The view whose visibility changed. Could be 'this' or
8725     * an ancestor view.
8726     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8727     * {@link #INVISIBLE} or {@link #GONE}.
8728     */
8729    protected void dispatchVisibilityChanged(@NonNull View changedView,
8730            @Visibility int visibility) {
8731        onVisibilityChanged(changedView, visibility);
8732    }
8733
8734    /**
8735     * Called when the visibility of the view or an ancestor of the view is changed.
8736     * @param changedView The view whose visibility changed. Could be 'this' or
8737     * an ancestor view.
8738     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8739     * {@link #INVISIBLE} or {@link #GONE}.
8740     */
8741    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8742        if (visibility == VISIBLE) {
8743            if (mAttachInfo != null) {
8744                initialAwakenScrollBars();
8745            } else {
8746                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8747            }
8748        }
8749    }
8750
8751    /**
8752     * Dispatch a hint about whether this view is displayed. For instance, when
8753     * a View moves out of the screen, it might receives a display hint indicating
8754     * the view is not displayed. Applications should not <em>rely</em> on this hint
8755     * as there is no guarantee that they will receive one.
8756     *
8757     * @param hint A hint about whether or not this view is displayed:
8758     * {@link #VISIBLE} or {@link #INVISIBLE}.
8759     */
8760    public void dispatchDisplayHint(@Visibility int hint) {
8761        onDisplayHint(hint);
8762    }
8763
8764    /**
8765     * Gives this view a hint about whether is displayed or not. For instance, when
8766     * a View moves out of the screen, it might receives a display hint indicating
8767     * the view is not displayed. Applications should not <em>rely</em> on this hint
8768     * as there is no guarantee that they will receive one.
8769     *
8770     * @param hint A hint about whether or not this view is displayed:
8771     * {@link #VISIBLE} or {@link #INVISIBLE}.
8772     */
8773    protected void onDisplayHint(@Visibility int hint) {
8774    }
8775
8776    /**
8777     * Dispatch a window visibility change down the view hierarchy.
8778     * ViewGroups should override to route to their children.
8779     *
8780     * @param visibility The new visibility of the window.
8781     *
8782     * @see #onWindowVisibilityChanged(int)
8783     */
8784    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
8785        onWindowVisibilityChanged(visibility);
8786    }
8787
8788    /**
8789     * Called when the window containing has change its visibility
8790     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
8791     * that this tells you whether or not your window is being made visible
8792     * to the window manager; this does <em>not</em> tell you whether or not
8793     * your window is obscured by other windows on the screen, even if it
8794     * is itself visible.
8795     *
8796     * @param visibility The new visibility of the window.
8797     */
8798    protected void onWindowVisibilityChanged(@Visibility int visibility) {
8799        if (visibility == VISIBLE) {
8800            initialAwakenScrollBars();
8801        }
8802    }
8803
8804    /**
8805     * Returns the current visibility of the window this view is attached to
8806     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
8807     *
8808     * @return Returns the current visibility of the view's window.
8809     */
8810    @Visibility
8811    public int getWindowVisibility() {
8812        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
8813    }
8814
8815    /**
8816     * Retrieve the overall visible display size in which the window this view is
8817     * attached to has been positioned in.  This takes into account screen
8818     * decorations above the window, for both cases where the window itself
8819     * is being position inside of them or the window is being placed under
8820     * then and covered insets are used for the window to position its content
8821     * inside.  In effect, this tells you the available area where content can
8822     * be placed and remain visible to users.
8823     *
8824     * <p>This function requires an IPC back to the window manager to retrieve
8825     * the requested information, so should not be used in performance critical
8826     * code like drawing.
8827     *
8828     * @param outRect Filled in with the visible display frame.  If the view
8829     * is not attached to a window, this is simply the raw display size.
8830     */
8831    public void getWindowVisibleDisplayFrame(Rect outRect) {
8832        if (mAttachInfo != null) {
8833            try {
8834                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
8835            } catch (RemoteException e) {
8836                return;
8837            }
8838            // XXX This is really broken, and probably all needs to be done
8839            // in the window manager, and we need to know more about whether
8840            // we want the area behind or in front of the IME.
8841            final Rect insets = mAttachInfo.mVisibleInsets;
8842            outRect.left += insets.left;
8843            outRect.top += insets.top;
8844            outRect.right -= insets.right;
8845            outRect.bottom -= insets.bottom;
8846            return;
8847        }
8848        // The view is not attached to a display so we don't have a context.
8849        // Make a best guess about the display size.
8850        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
8851        d.getRectSize(outRect);
8852    }
8853
8854    /**
8855     * Dispatch a notification about a resource configuration change down
8856     * the view hierarchy.
8857     * ViewGroups should override to route to their children.
8858     *
8859     * @param newConfig The new resource configuration.
8860     *
8861     * @see #onConfigurationChanged(android.content.res.Configuration)
8862     */
8863    public void dispatchConfigurationChanged(Configuration newConfig) {
8864        onConfigurationChanged(newConfig);
8865    }
8866
8867    /**
8868     * Called when the current configuration of the resources being used
8869     * by the application have changed.  You can use this to decide when
8870     * to reload resources that can changed based on orientation and other
8871     * configuration characterstics.  You only need to use this if you are
8872     * not relying on the normal {@link android.app.Activity} mechanism of
8873     * recreating the activity instance upon a configuration change.
8874     *
8875     * @param newConfig The new resource configuration.
8876     */
8877    protected void onConfigurationChanged(Configuration newConfig) {
8878    }
8879
8880    /**
8881     * Private function to aggregate all per-view attributes in to the view
8882     * root.
8883     */
8884    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8885        performCollectViewAttributes(attachInfo, visibility);
8886    }
8887
8888    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
8889        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
8890            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
8891                attachInfo.mKeepScreenOn = true;
8892            }
8893            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
8894            ListenerInfo li = mListenerInfo;
8895            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
8896                attachInfo.mHasSystemUiListeners = true;
8897            }
8898        }
8899    }
8900
8901    void needGlobalAttributesUpdate(boolean force) {
8902        final AttachInfo ai = mAttachInfo;
8903        if (ai != null && !ai.mRecomputeGlobalAttributes) {
8904            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
8905                    || ai.mHasSystemUiListeners) {
8906                ai.mRecomputeGlobalAttributes = true;
8907            }
8908        }
8909    }
8910
8911    /**
8912     * Returns whether the device is currently in touch mode.  Touch mode is entered
8913     * once the user begins interacting with the device by touch, and affects various
8914     * things like whether focus is always visible to the user.
8915     *
8916     * @return Whether the device is in touch mode.
8917     */
8918    @ViewDebug.ExportedProperty
8919    public boolean isInTouchMode() {
8920        if (mAttachInfo != null) {
8921            return mAttachInfo.mInTouchMode;
8922        } else {
8923            return ViewRootImpl.isInTouchMode();
8924        }
8925    }
8926
8927    /**
8928     * Returns the context the view is running in, through which it can
8929     * access the current theme, resources, etc.
8930     *
8931     * @return The view's Context.
8932     */
8933    @ViewDebug.CapturedViewProperty
8934    public final Context getContext() {
8935        return mContext;
8936    }
8937
8938    /**
8939     * Handle a key event before it is processed by any input method
8940     * associated with the view hierarchy.  This can be used to intercept
8941     * key events in special situations before the IME consumes them; a
8942     * typical example would be handling the BACK key to update the application's
8943     * UI instead of allowing the IME to see it and close itself.
8944     *
8945     * @param keyCode The value in event.getKeyCode().
8946     * @param event Description of the key event.
8947     * @return If you handled the event, return true. If you want to allow the
8948     *         event to be handled by the next receiver, return false.
8949     */
8950    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
8951        return false;
8952    }
8953
8954    /**
8955     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
8956     * KeyEvent.Callback.onKeyDown()}: perform press of the view
8957     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
8958     * is released, if the view is enabled and clickable.
8959     *
8960     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8961     * although some may elect to do so in some situations. Do not rely on this to
8962     * catch software key presses.
8963     *
8964     * @param keyCode A key code that represents the button pressed, from
8965     *                {@link android.view.KeyEvent}.
8966     * @param event   The KeyEvent object that defines the button action.
8967     */
8968    public boolean onKeyDown(int keyCode, KeyEvent event) {
8969        boolean result = false;
8970
8971        if (KeyEvent.isConfirmKey(keyCode)) {
8972            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
8973                return true;
8974            }
8975            // Long clickable items don't necessarily have to be clickable
8976            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
8977                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
8978                    (event.getRepeatCount() == 0)) {
8979                setPressed(true);
8980                checkForLongClick(0);
8981                return true;
8982            }
8983        }
8984        return result;
8985    }
8986
8987    /**
8988     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
8989     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
8990     * the event).
8991     * <p>Key presses in software keyboards will generally NOT trigger this listener,
8992     * although some may elect to do so in some situations. Do not rely on this to
8993     * catch software key presses.
8994     */
8995    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
8996        return false;
8997    }
8998
8999    /**
9000     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9001     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9002     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9003     * {@link KeyEvent#KEYCODE_ENTER} is released.
9004     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9005     * although some may elect to do so in some situations. Do not rely on this to
9006     * catch software key presses.
9007     *
9008     * @param keyCode A key code that represents the button pressed, from
9009     *                {@link android.view.KeyEvent}.
9010     * @param event   The KeyEvent object that defines the button action.
9011     */
9012    public boolean onKeyUp(int keyCode, KeyEvent event) {
9013        if (KeyEvent.isConfirmKey(keyCode)) {
9014            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9015                return true;
9016            }
9017            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9018                setPressed(false);
9019
9020                if (!mHasPerformedLongPress) {
9021                    // This is a tap, so remove the longpress check
9022                    removeLongPressCallback();
9023                    return performClick();
9024                }
9025            }
9026        }
9027        return false;
9028    }
9029
9030    /**
9031     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9032     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9033     * the event).
9034     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9035     * although some may elect to do so in some situations. Do not rely on this to
9036     * catch software key presses.
9037     *
9038     * @param keyCode     A key code that represents the button pressed, from
9039     *                    {@link android.view.KeyEvent}.
9040     * @param repeatCount The number of times the action was made.
9041     * @param event       The KeyEvent object that defines the button action.
9042     */
9043    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9044        return false;
9045    }
9046
9047    /**
9048     * Called on the focused view when a key shortcut event is not handled.
9049     * Override this method to implement local key shortcuts for the View.
9050     * Key shortcuts can also be implemented by setting the
9051     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9052     *
9053     * @param keyCode The value in event.getKeyCode().
9054     * @param event Description of the key event.
9055     * @return If you handled the event, return true. If you want to allow the
9056     *         event to be handled by the next receiver, return false.
9057     */
9058    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9059        return false;
9060    }
9061
9062    /**
9063     * Check whether the called view is a text editor, in which case it
9064     * would make sense to automatically display a soft input window for
9065     * it.  Subclasses should override this if they implement
9066     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9067     * a call on that method would return a non-null InputConnection, and
9068     * they are really a first-class editor that the user would normally
9069     * start typing on when the go into a window containing your view.
9070     *
9071     * <p>The default implementation always returns false.  This does
9072     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9073     * will not be called or the user can not otherwise perform edits on your
9074     * view; it is just a hint to the system that this is not the primary
9075     * purpose of this view.
9076     *
9077     * @return Returns true if this view is a text editor, else false.
9078     */
9079    public boolean onCheckIsTextEditor() {
9080        return false;
9081    }
9082
9083    /**
9084     * Create a new InputConnection for an InputMethod to interact
9085     * with the view.  The default implementation returns null, since it doesn't
9086     * support input methods.  You can override this to implement such support.
9087     * This is only needed for views that take focus and text input.
9088     *
9089     * <p>When implementing this, you probably also want to implement
9090     * {@link #onCheckIsTextEditor()} to indicate you will return a
9091     * non-null InputConnection.</p>
9092     *
9093     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9094     * object correctly and in its entirety, so that the connected IME can rely
9095     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9096     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9097     * must be filled in with the correct cursor position for IMEs to work correctly
9098     * with your application.</p>
9099     *
9100     * @param outAttrs Fill in with attribute information about the connection.
9101     */
9102    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9103        return null;
9104    }
9105
9106    /**
9107     * Called by the {@link android.view.inputmethod.InputMethodManager}
9108     * when a view who is not the current
9109     * input connection target is trying to make a call on the manager.  The
9110     * default implementation returns false; you can override this to return
9111     * true for certain views if you are performing InputConnection proxying
9112     * to them.
9113     * @param view The View that is making the InputMethodManager call.
9114     * @return Return true to allow the call, false to reject.
9115     */
9116    public boolean checkInputConnectionProxy(View view) {
9117        return false;
9118    }
9119
9120    /**
9121     * Show the context menu for this view. It is not safe to hold on to the
9122     * menu after returning from this method.
9123     *
9124     * You should normally not overload this method. Overload
9125     * {@link #onCreateContextMenu(ContextMenu)} or define an
9126     * {@link OnCreateContextMenuListener} to add items to the context menu.
9127     *
9128     * @param menu The context menu to populate
9129     */
9130    public void createContextMenu(ContextMenu menu) {
9131        ContextMenuInfo menuInfo = getContextMenuInfo();
9132
9133        // Sets the current menu info so all items added to menu will have
9134        // my extra info set.
9135        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9136
9137        onCreateContextMenu(menu);
9138        ListenerInfo li = mListenerInfo;
9139        if (li != null && li.mOnCreateContextMenuListener != null) {
9140            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9141        }
9142
9143        // Clear the extra information so subsequent items that aren't mine don't
9144        // have my extra info.
9145        ((MenuBuilder)menu).setCurrentMenuInfo(null);
9146
9147        if (mParent != null) {
9148            mParent.createContextMenu(menu);
9149        }
9150    }
9151
9152    /**
9153     * Views should implement this if they have extra information to associate
9154     * with the context menu. The return result is supplied as a parameter to
9155     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9156     * callback.
9157     *
9158     * @return Extra information about the item for which the context menu
9159     *         should be shown. This information will vary across different
9160     *         subclasses of View.
9161     */
9162    protected ContextMenuInfo getContextMenuInfo() {
9163        return null;
9164    }
9165
9166    /**
9167     * Views should implement this if the view itself is going to add items to
9168     * the context menu.
9169     *
9170     * @param menu the context menu to populate
9171     */
9172    protected void onCreateContextMenu(ContextMenu menu) {
9173    }
9174
9175    /**
9176     * Implement this method to handle trackball motion events.  The
9177     * <em>relative</em> movement of the trackball since the last event
9178     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9179     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
9180     * that a movement of 1 corresponds to the user pressing one DPAD key (so
9181     * they will often be fractional values, representing the more fine-grained
9182     * movement information available from a trackball).
9183     *
9184     * @param event The motion event.
9185     * @return True if the event was handled, false otherwise.
9186     */
9187    public boolean onTrackballEvent(MotionEvent event) {
9188        return false;
9189    }
9190
9191    /**
9192     * Implement this method to handle generic motion events.
9193     * <p>
9194     * Generic motion events describe joystick movements, mouse hovers, track pad
9195     * touches, scroll wheel movements and other input events.  The
9196     * {@link MotionEvent#getSource() source} of the motion event specifies
9197     * the class of input that was received.  Implementations of this method
9198     * must examine the bits in the source before processing the event.
9199     * The following code example shows how this is done.
9200     * </p><p>
9201     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9202     * are delivered to the view under the pointer.  All other generic motion events are
9203     * delivered to the focused view.
9204     * </p>
9205     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9206     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9207     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
9208     *             // process the joystick movement...
9209     *             return true;
9210     *         }
9211     *     }
9212     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9213     *         switch (event.getAction()) {
9214     *             case MotionEvent.ACTION_HOVER_MOVE:
9215     *                 // process the mouse hover movement...
9216     *                 return true;
9217     *             case MotionEvent.ACTION_SCROLL:
9218     *                 // process the scroll wheel movement...
9219     *                 return true;
9220     *         }
9221     *     }
9222     *     return super.onGenericMotionEvent(event);
9223     * }</pre>
9224     *
9225     * @param event The generic motion event being processed.
9226     * @return True if the event was handled, false otherwise.
9227     */
9228    public boolean onGenericMotionEvent(MotionEvent event) {
9229        return false;
9230    }
9231
9232    /**
9233     * Implement this method to handle hover events.
9234     * <p>
9235     * This method is called whenever a pointer is hovering into, over, or out of the
9236     * bounds of a view and the view is not currently being touched.
9237     * Hover events are represented as pointer events with action
9238     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9239     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9240     * </p>
9241     * <ul>
9242     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9243     * when the pointer enters the bounds of the view.</li>
9244     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9245     * when the pointer has already entered the bounds of the view and has moved.</li>
9246     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9247     * when the pointer has exited the bounds of the view or when the pointer is
9248     * about to go down due to a button click, tap, or similar user action that
9249     * causes the view to be touched.</li>
9250     * </ul>
9251     * <p>
9252     * The view should implement this method to return true to indicate that it is
9253     * handling the hover event, such as by changing its drawable state.
9254     * </p><p>
9255     * The default implementation calls {@link #setHovered} to update the hovered state
9256     * of the view when a hover enter or hover exit event is received, if the view
9257     * is enabled and is clickable.  The default implementation also sends hover
9258     * accessibility events.
9259     * </p>
9260     *
9261     * @param event The motion event that describes the hover.
9262     * @return True if the view handled the hover event.
9263     *
9264     * @see #isHovered
9265     * @see #setHovered
9266     * @see #onHoverChanged
9267     */
9268    public boolean onHoverEvent(MotionEvent event) {
9269        // The root view may receive hover (or touch) events that are outside the bounds of
9270        // the window.  This code ensures that we only send accessibility events for
9271        // hovers that are actually within the bounds of the root view.
9272        final int action = event.getActionMasked();
9273        if (!mSendingHoverAccessibilityEvents) {
9274            if ((action == MotionEvent.ACTION_HOVER_ENTER
9275                    || action == MotionEvent.ACTION_HOVER_MOVE)
9276                    && !hasHoveredChild()
9277                    && pointInView(event.getX(), event.getY())) {
9278                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9279                mSendingHoverAccessibilityEvents = true;
9280            }
9281        } else {
9282            if (action == MotionEvent.ACTION_HOVER_EXIT
9283                    || (action == MotionEvent.ACTION_MOVE
9284                            && !pointInView(event.getX(), event.getY()))) {
9285                mSendingHoverAccessibilityEvents = false;
9286                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9287            }
9288        }
9289
9290        if (isHoverable()) {
9291            switch (action) {
9292                case MotionEvent.ACTION_HOVER_ENTER:
9293                    setHovered(true);
9294                    break;
9295                case MotionEvent.ACTION_HOVER_EXIT:
9296                    setHovered(false);
9297                    break;
9298            }
9299
9300            // Dispatch the event to onGenericMotionEvent before returning true.
9301            // This is to provide compatibility with existing applications that
9302            // handled HOVER_MOVE events in onGenericMotionEvent and that would
9303            // break because of the new default handling for hoverable views
9304            // in onHoverEvent.
9305            // Note that onGenericMotionEvent will be called by default when
9306            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9307            dispatchGenericMotionEventInternal(event);
9308            // The event was already handled by calling setHovered(), so always
9309            // return true.
9310            return true;
9311        }
9312
9313        return false;
9314    }
9315
9316    /**
9317     * Returns true if the view should handle {@link #onHoverEvent}
9318     * by calling {@link #setHovered} to change its hovered state.
9319     *
9320     * @return True if the view is hoverable.
9321     */
9322    private boolean isHoverable() {
9323        final int viewFlags = mViewFlags;
9324        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9325            return false;
9326        }
9327
9328        return (viewFlags & CLICKABLE) == CLICKABLE
9329                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9330    }
9331
9332    /**
9333     * Returns true if the view is currently hovered.
9334     *
9335     * @return True if the view is currently hovered.
9336     *
9337     * @see #setHovered
9338     * @see #onHoverChanged
9339     */
9340    @ViewDebug.ExportedProperty
9341    public boolean isHovered() {
9342        return (mPrivateFlags & PFLAG_HOVERED) != 0;
9343    }
9344
9345    /**
9346     * Sets whether the view is currently hovered.
9347     * <p>
9348     * Calling this method also changes the drawable state of the view.  This
9349     * enables the view to react to hover by using different drawable resources
9350     * to change its appearance.
9351     * </p><p>
9352     * The {@link #onHoverChanged} method is called when the hovered state changes.
9353     * </p>
9354     *
9355     * @param hovered True if the view is hovered.
9356     *
9357     * @see #isHovered
9358     * @see #onHoverChanged
9359     */
9360    public void setHovered(boolean hovered) {
9361        if (hovered) {
9362            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9363                mPrivateFlags |= PFLAG_HOVERED;
9364                refreshDrawableState();
9365                onHoverChanged(true);
9366            }
9367        } else {
9368            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9369                mPrivateFlags &= ~PFLAG_HOVERED;
9370                refreshDrawableState();
9371                onHoverChanged(false);
9372            }
9373        }
9374    }
9375
9376    /**
9377     * Implement this method to handle hover state changes.
9378     * <p>
9379     * This method is called whenever the hover state changes as a result of a
9380     * call to {@link #setHovered}.
9381     * </p>
9382     *
9383     * @param hovered The current hover state, as returned by {@link #isHovered}.
9384     *
9385     * @see #isHovered
9386     * @see #setHovered
9387     */
9388    public void onHoverChanged(boolean hovered) {
9389    }
9390
9391    /**
9392     * Implement this method to handle touch screen motion events.
9393     * <p>
9394     * If this method is used to detect click actions, it is recommended that
9395     * the actions be performed by implementing and calling
9396     * {@link #performClick()}. This will ensure consistent system behavior,
9397     * including:
9398     * <ul>
9399     * <li>obeying click sound preferences
9400     * <li>dispatching OnClickListener calls
9401     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9402     * accessibility features are enabled
9403     * </ul>
9404     *
9405     * @param event The motion event.
9406     * @return True if the event was handled, false otherwise.
9407     */
9408    public boolean onTouchEvent(MotionEvent event) {
9409        final float x = event.getX();
9410        final float y = event.getY();
9411        final int viewFlags = mViewFlags;
9412
9413        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9414            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9415                setPressed(false);
9416            }
9417            // A disabled view that is clickable still consumes the touch
9418            // events, it just doesn't respond to them.
9419            return (((viewFlags & CLICKABLE) == CLICKABLE ||
9420                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9421        }
9422
9423        if (mTouchDelegate != null) {
9424            if (mTouchDelegate.onTouchEvent(event)) {
9425                return true;
9426            }
9427        }
9428
9429        if (((viewFlags & CLICKABLE) == CLICKABLE ||
9430                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9431            switch (event.getAction()) {
9432                case MotionEvent.ACTION_UP:
9433                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9434                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9435                        // take focus if we don't have it already and we should in
9436                        // touch mode.
9437                        boolean focusTaken = false;
9438                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9439                            focusTaken = requestFocus();
9440                        }
9441
9442                        if (prepressed) {
9443                            // The button is being released before we actually
9444                            // showed it as pressed.  Make it show the pressed
9445                            // state now (before scheduling the click) to ensure
9446                            // the user sees it.
9447                            setPressed(true, x, y);
9448                       }
9449
9450                        if (!mHasPerformedLongPress) {
9451                            // This is a tap, so remove the longpress check
9452                            removeLongPressCallback();
9453
9454                            // Only perform take click actions if we were in the pressed state
9455                            if (!focusTaken) {
9456                                // Use a Runnable and post this rather than calling
9457                                // performClick directly. This lets other visual state
9458                                // of the view update before click actions start.
9459                                if (mPerformClick == null) {
9460                                    mPerformClick = new PerformClick();
9461                                }
9462                                if (!post(mPerformClick)) {
9463                                    performClick();
9464                                }
9465                            }
9466                        }
9467
9468                        if (mUnsetPressedState == null) {
9469                            mUnsetPressedState = new UnsetPressedState();
9470                        }
9471
9472                        if (prepressed) {
9473                            postDelayed(mUnsetPressedState,
9474                                    ViewConfiguration.getPressedStateDuration());
9475                        } else if (!post(mUnsetPressedState)) {
9476                            // If the post failed, unpress right now
9477                            mUnsetPressedState.run();
9478                        }
9479
9480                        removeTapCallback();
9481                    }
9482                    break;
9483
9484                case MotionEvent.ACTION_DOWN:
9485                    mHasPerformedLongPress = false;
9486
9487                    if (performButtonActionOnTouchDown(event)) {
9488                        break;
9489                    }
9490
9491                    // Walk up the hierarchy to determine if we're inside a scrolling container.
9492                    boolean isInScrollingContainer = isInScrollingContainer();
9493
9494                    // For views inside a scrolling container, delay the pressed feedback for
9495                    // a short period in case this is a scroll.
9496                    if (isInScrollingContainer) {
9497                        mPrivateFlags |= PFLAG_PREPRESSED;
9498                        if (mPendingCheckForTap == null) {
9499                            mPendingCheckForTap = new CheckForTap();
9500                        }
9501                        mPendingCheckForTap.x = event.getX();
9502                        mPendingCheckForTap.y = event.getY();
9503                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9504                    } else {
9505                        // Not inside a scrolling container, so show the feedback right away
9506                        setPressed(true, x, y);
9507                        checkForLongClick(0);
9508                    }
9509                    break;
9510
9511                case MotionEvent.ACTION_CANCEL:
9512                    setPressed(false);
9513                    removeTapCallback();
9514                    removeLongPressCallback();
9515                    break;
9516
9517                case MotionEvent.ACTION_MOVE:
9518                    drawableHotspotChanged(x, y);
9519
9520                    // Be lenient about moving outside of buttons
9521                    if (!pointInView(x, y, mTouchSlop)) {
9522                        // Outside button
9523                        removeTapCallback();
9524                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9525                            // Remove any future long press/tap checks
9526                            removeLongPressCallback();
9527
9528                            setPressed(false);
9529                        }
9530                    }
9531                    break;
9532            }
9533
9534            return true;
9535        }
9536
9537        return false;
9538    }
9539
9540    /**
9541     * @hide
9542     */
9543    public boolean isInScrollingContainer() {
9544        ViewParent p = getParent();
9545        while (p != null && p instanceof ViewGroup) {
9546            if (((ViewGroup) p).shouldDelayChildPressedState()) {
9547                return true;
9548            }
9549            p = p.getParent();
9550        }
9551        return false;
9552    }
9553
9554    /**
9555     * Remove the longpress detection timer.
9556     */
9557    private void removeLongPressCallback() {
9558        if (mPendingCheckForLongPress != null) {
9559          removeCallbacks(mPendingCheckForLongPress);
9560        }
9561    }
9562
9563    /**
9564     * Remove the pending click action
9565     */
9566    private void removePerformClickCallback() {
9567        if (mPerformClick != null) {
9568            removeCallbacks(mPerformClick);
9569        }
9570    }
9571
9572    /**
9573     * Remove the prepress detection timer.
9574     */
9575    private void removeUnsetPressCallback() {
9576        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9577            setPressed(false);
9578            removeCallbacks(mUnsetPressedState);
9579        }
9580    }
9581
9582    /**
9583     * Remove the tap detection timer.
9584     */
9585    private void removeTapCallback() {
9586        if (mPendingCheckForTap != null) {
9587            mPrivateFlags &= ~PFLAG_PREPRESSED;
9588            removeCallbacks(mPendingCheckForTap);
9589        }
9590    }
9591
9592    /**
9593     * Cancels a pending long press.  Your subclass can use this if you
9594     * want the context menu to come up if the user presses and holds
9595     * at the same place, but you don't want it to come up if they press
9596     * and then move around enough to cause scrolling.
9597     */
9598    public void cancelLongPress() {
9599        removeLongPressCallback();
9600
9601        /*
9602         * The prepressed state handled by the tap callback is a display
9603         * construct, but the tap callback will post a long press callback
9604         * less its own timeout. Remove it here.
9605         */
9606        removeTapCallback();
9607    }
9608
9609    /**
9610     * Remove the pending callback for sending a
9611     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9612     */
9613    private void removeSendViewScrolledAccessibilityEventCallback() {
9614        if (mSendViewScrolledAccessibilityEvent != null) {
9615            removeCallbacks(mSendViewScrolledAccessibilityEvent);
9616            mSendViewScrolledAccessibilityEvent.mIsPending = false;
9617        }
9618    }
9619
9620    /**
9621     * Sets the TouchDelegate for this View.
9622     */
9623    public void setTouchDelegate(TouchDelegate delegate) {
9624        mTouchDelegate = delegate;
9625    }
9626
9627    /**
9628     * Gets the TouchDelegate for this View.
9629     */
9630    public TouchDelegate getTouchDelegate() {
9631        return mTouchDelegate;
9632    }
9633
9634    /**
9635     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9636     *
9637     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9638     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9639     * available. This method should only be called for touch events.
9640     *
9641     * <p class="note">This api is not intended for most applications. Buffered dispatch
9642     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9643     * streams will not improve your input latency. Side effects include: increased latency,
9644     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9645     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9646     * you.</p>
9647     */
9648    public final void requestUnbufferedDispatch(MotionEvent event) {
9649        final int action = event.getAction();
9650        if (mAttachInfo == null
9651                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9652                || !event.isTouchEvent()) {
9653            return;
9654        }
9655        mAttachInfo.mUnbufferedDispatchRequested = true;
9656    }
9657
9658    /**
9659     * Set flags controlling behavior of this view.
9660     *
9661     * @param flags Constant indicating the value which should be set
9662     * @param mask Constant indicating the bit range that should be changed
9663     */
9664    void setFlags(int flags, int mask) {
9665        final boolean accessibilityEnabled =
9666                AccessibilityManager.getInstance(mContext).isEnabled();
9667        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9668
9669        int old = mViewFlags;
9670        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9671
9672        int changed = mViewFlags ^ old;
9673        if (changed == 0) {
9674            return;
9675        }
9676        int privateFlags = mPrivateFlags;
9677
9678        /* Check if the FOCUSABLE bit has changed */
9679        if (((changed & FOCUSABLE_MASK) != 0) &&
9680                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9681            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9682                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9683                /* Give up focus if we are no longer focusable */
9684                clearFocus();
9685            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9686                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9687                /*
9688                 * Tell the view system that we are now available to take focus
9689                 * if no one else already has it.
9690                 */
9691                if (mParent != null) mParent.focusableViewAvailable(this);
9692            }
9693        }
9694
9695        final int newVisibility = flags & VISIBILITY_MASK;
9696        if (newVisibility == VISIBLE) {
9697            if ((changed & VISIBILITY_MASK) != 0) {
9698                /*
9699                 * If this view is becoming visible, invalidate it in case it changed while
9700                 * it was not visible. Marking it drawn ensures that the invalidation will
9701                 * go through.
9702                 */
9703                mPrivateFlags |= PFLAG_DRAWN;
9704                invalidate(true);
9705
9706                needGlobalAttributesUpdate(true);
9707
9708                // a view becoming visible is worth notifying the parent
9709                // about in case nothing has focus.  even if this specific view
9710                // isn't focusable, it may contain something that is, so let
9711                // the root view try to give this focus if nothing else does.
9712                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9713                    mParent.focusableViewAvailable(this);
9714                }
9715            }
9716        }
9717
9718        /* Check if the GONE bit has changed */
9719        if ((changed & GONE) != 0) {
9720            needGlobalAttributesUpdate(false);
9721            requestLayout();
9722
9723            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9724                if (hasFocus()) clearFocus();
9725                clearAccessibilityFocus();
9726                destroyDrawingCache();
9727                if (mParent instanceof View) {
9728                    // GONE views noop invalidation, so invalidate the parent
9729                    ((View) mParent).invalidate(true);
9730                }
9731                // Mark the view drawn to ensure that it gets invalidated properly the next
9732                // time it is visible and gets invalidated
9733                mPrivateFlags |= PFLAG_DRAWN;
9734            }
9735            if (mAttachInfo != null) {
9736                mAttachInfo.mViewVisibilityChanged = true;
9737            }
9738        }
9739
9740        /* Check if the VISIBLE bit has changed */
9741        if ((changed & INVISIBLE) != 0) {
9742            needGlobalAttributesUpdate(false);
9743            /*
9744             * If this view is becoming invisible, set the DRAWN flag so that
9745             * the next invalidate() will not be skipped.
9746             */
9747            mPrivateFlags |= PFLAG_DRAWN;
9748
9749            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9750                // root view becoming invisible shouldn't clear focus and accessibility focus
9751                if (getRootView() != this) {
9752                    if (hasFocus()) clearFocus();
9753                    clearAccessibilityFocus();
9754                }
9755            }
9756            if (mAttachInfo != null) {
9757                mAttachInfo.mViewVisibilityChanged = true;
9758            }
9759        }
9760
9761        if ((changed & VISIBILITY_MASK) != 0) {
9762            // If the view is invisible, cleanup its display list to free up resources
9763            if (newVisibility != VISIBLE && mAttachInfo != null) {
9764                cleanupDraw();
9765            }
9766
9767            if (mParent instanceof ViewGroup) {
9768                ((ViewGroup) mParent).onChildVisibilityChanged(this,
9769                        (changed & VISIBILITY_MASK), newVisibility);
9770                ((View) mParent).invalidate(true);
9771            } else if (mParent != null) {
9772                mParent.invalidateChild(this, null);
9773            }
9774            dispatchVisibilityChanged(this, newVisibility);
9775
9776            notifySubtreeAccessibilityStateChangedIfNeeded();
9777        }
9778
9779        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
9780            destroyDrawingCache();
9781        }
9782
9783        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
9784            destroyDrawingCache();
9785            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9786            invalidateParentCaches();
9787        }
9788
9789        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
9790            destroyDrawingCache();
9791            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
9792        }
9793
9794        if ((changed & DRAW_MASK) != 0) {
9795            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
9796                if (mBackground != null) {
9797                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9798                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
9799                } else {
9800                    mPrivateFlags |= PFLAG_SKIP_DRAW;
9801                }
9802            } else {
9803                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
9804            }
9805            requestLayout();
9806            invalidate(true);
9807        }
9808
9809        if ((changed & KEEP_SCREEN_ON) != 0) {
9810            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
9811                mParent.recomputeViewAttributes(this);
9812            }
9813        }
9814
9815        if (accessibilityEnabled) {
9816            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
9817                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
9818                if (oldIncludeForAccessibility != includeForAccessibility()) {
9819                    notifySubtreeAccessibilityStateChangedIfNeeded();
9820                } else {
9821                    notifyViewAccessibilityStateChangedIfNeeded(
9822                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9823                }
9824            } else if ((changed & ENABLED_MASK) != 0) {
9825                notifyViewAccessibilityStateChangedIfNeeded(
9826                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9827            }
9828        }
9829    }
9830
9831    /**
9832     * Change the view's z order in the tree, so it's on top of other sibling
9833     * views. This ordering change may affect layout, if the parent container
9834     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
9835     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
9836     * method should be followed by calls to {@link #requestLayout()} and
9837     * {@link View#invalidate()} on the view's parent to force the parent to redraw
9838     * with the new child ordering.
9839     *
9840     * @see ViewGroup#bringChildToFront(View)
9841     */
9842    public void bringToFront() {
9843        if (mParent != null) {
9844            mParent.bringChildToFront(this);
9845        }
9846    }
9847
9848    /**
9849     * This is called in response to an internal scroll in this view (i.e., the
9850     * view scrolled its own contents). This is typically as a result of
9851     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
9852     * called.
9853     *
9854     * @param l Current horizontal scroll origin.
9855     * @param t Current vertical scroll origin.
9856     * @param oldl Previous horizontal scroll origin.
9857     * @param oldt Previous vertical scroll origin.
9858     */
9859    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
9860        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
9861            postSendViewScrolledAccessibilityEventCallback();
9862        }
9863
9864        mBackgroundSizeChanged = true;
9865
9866        final AttachInfo ai = mAttachInfo;
9867        if (ai != null) {
9868            ai.mViewScrollChanged = true;
9869        }
9870
9871        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
9872            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
9873        }
9874    }
9875
9876    /**
9877     * Interface definition for a callback to be invoked when the scroll
9878     * position of a view changes.
9879     *
9880     * @hide Only used internally.
9881     */
9882    public interface OnScrollChangeListener {
9883        /**
9884         * Called when the scroll position of a view changes.
9885         *
9886         * @param v The view whose scroll position has changed.
9887         * @param scrollX Current horizontal scroll origin.
9888         * @param scrollY Current vertical scroll origin.
9889         * @param oldScrollX Previous horizontal scroll origin.
9890         * @param oldScrollY Previous vertical scroll origin.
9891         */
9892        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
9893    }
9894
9895    /**
9896     * Interface definition for a callback to be invoked when the layout bounds of a view
9897     * changes due to layout processing.
9898     */
9899    public interface OnLayoutChangeListener {
9900        /**
9901         * Called when the layout bounds of a view changes due to layout processing.
9902         *
9903         * @param v The view whose bounds have changed.
9904         * @param left The new value of the view's left property.
9905         * @param top The new value of the view's top property.
9906         * @param right The new value of the view's right property.
9907         * @param bottom The new value of the view's bottom property.
9908         * @param oldLeft The previous value of the view's left property.
9909         * @param oldTop The previous value of the view's top property.
9910         * @param oldRight The previous value of the view's right property.
9911         * @param oldBottom The previous value of the view's bottom property.
9912         */
9913        void onLayoutChange(View v, int left, int top, int right, int bottom,
9914            int oldLeft, int oldTop, int oldRight, int oldBottom);
9915    }
9916
9917    /**
9918     * This is called during layout when the size of this view has changed. If
9919     * you were just added to the view hierarchy, you're called with the old
9920     * values of 0.
9921     *
9922     * @param w Current width of this view.
9923     * @param h Current height of this view.
9924     * @param oldw Old width of this view.
9925     * @param oldh Old height of this view.
9926     */
9927    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
9928    }
9929
9930    /**
9931     * Called by draw to draw the child views. This may be overridden
9932     * by derived classes to gain control just before its children are drawn
9933     * (but after its own view has been drawn).
9934     * @param canvas the canvas on which to draw the view
9935     */
9936    protected void dispatchDraw(Canvas canvas) {
9937
9938    }
9939
9940    /**
9941     * Gets the parent of this view. Note that the parent is a
9942     * ViewParent and not necessarily a View.
9943     *
9944     * @return Parent of this view.
9945     */
9946    public final ViewParent getParent() {
9947        return mParent;
9948    }
9949
9950    /**
9951     * Set the horizontal scrolled position of your view. This will cause a call to
9952     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9953     * invalidated.
9954     * @param value the x position to scroll to
9955     */
9956    public void setScrollX(int value) {
9957        scrollTo(value, mScrollY);
9958    }
9959
9960    /**
9961     * Set the vertical scrolled position of your view. This will cause a call to
9962     * {@link #onScrollChanged(int, int, int, int)} and the view will be
9963     * invalidated.
9964     * @param value the y position to scroll to
9965     */
9966    public void setScrollY(int value) {
9967        scrollTo(mScrollX, value);
9968    }
9969
9970    /**
9971     * Return the scrolled left position of this view. This is the left edge of
9972     * the displayed part of your view. You do not need to draw any pixels
9973     * farther left, since those are outside of the frame of your view on
9974     * screen.
9975     *
9976     * @return The left edge of the displayed part of your view, in pixels.
9977     */
9978    public final int getScrollX() {
9979        return mScrollX;
9980    }
9981
9982    /**
9983     * Return the scrolled top position of this view. This is the top edge of
9984     * the displayed part of your view. You do not need to draw any pixels above
9985     * it, since those are outside of the frame of your view on screen.
9986     *
9987     * @return The top edge of the displayed part of your view, in pixels.
9988     */
9989    public final int getScrollY() {
9990        return mScrollY;
9991    }
9992
9993    /**
9994     * Return the width of the your view.
9995     *
9996     * @return The width of your view, in pixels.
9997     */
9998    @ViewDebug.ExportedProperty(category = "layout")
9999    public final int getWidth() {
10000        return mRight - mLeft;
10001    }
10002
10003    /**
10004     * Return the height of your view.
10005     *
10006     * @return The height of your view, in pixels.
10007     */
10008    @ViewDebug.ExportedProperty(category = "layout")
10009    public final int getHeight() {
10010        return mBottom - mTop;
10011    }
10012
10013    /**
10014     * Return the visible drawing bounds of your view. Fills in the output
10015     * rectangle with the values from getScrollX(), getScrollY(),
10016     * getWidth(), and getHeight(). These bounds do not account for any
10017     * transformation properties currently set on the view, such as
10018     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10019     *
10020     * @param outRect The (scrolled) drawing bounds of the view.
10021     */
10022    public void getDrawingRect(Rect outRect) {
10023        outRect.left = mScrollX;
10024        outRect.top = mScrollY;
10025        outRect.right = mScrollX + (mRight - mLeft);
10026        outRect.bottom = mScrollY + (mBottom - mTop);
10027    }
10028
10029    /**
10030     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10031     * raw width component (that is the result is masked by
10032     * {@link #MEASURED_SIZE_MASK}).
10033     *
10034     * @return The raw measured width of this view.
10035     */
10036    public final int getMeasuredWidth() {
10037        return mMeasuredWidth & MEASURED_SIZE_MASK;
10038    }
10039
10040    /**
10041     * Return the full width measurement information for this view as computed
10042     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10043     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10044     * This should be used during measurement and layout calculations only. Use
10045     * {@link #getWidth()} to see how wide a view is after layout.
10046     *
10047     * @return The measured width of this view as a bit mask.
10048     */
10049    public final int getMeasuredWidthAndState() {
10050        return mMeasuredWidth;
10051    }
10052
10053    /**
10054     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10055     * raw width component (that is the result is masked by
10056     * {@link #MEASURED_SIZE_MASK}).
10057     *
10058     * @return The raw measured height of this view.
10059     */
10060    public final int getMeasuredHeight() {
10061        return mMeasuredHeight & MEASURED_SIZE_MASK;
10062    }
10063
10064    /**
10065     * Return the full height measurement information for this view as computed
10066     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10067     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10068     * This should be used during measurement and layout calculations only. Use
10069     * {@link #getHeight()} to see how wide a view is after layout.
10070     *
10071     * @return The measured width of this view as a bit mask.
10072     */
10073    public final int getMeasuredHeightAndState() {
10074        return mMeasuredHeight;
10075    }
10076
10077    /**
10078     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10079     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10080     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10081     * and the height component is at the shifted bits
10082     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10083     */
10084    public final int getMeasuredState() {
10085        return (mMeasuredWidth&MEASURED_STATE_MASK)
10086                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10087                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10088    }
10089
10090    /**
10091     * The transform matrix of this view, which is calculated based on the current
10092     * rotation, scale, and pivot properties.
10093     *
10094     * @see #getRotation()
10095     * @see #getScaleX()
10096     * @see #getScaleY()
10097     * @see #getPivotX()
10098     * @see #getPivotY()
10099     * @return The current transform matrix for the view
10100     */
10101    public Matrix getMatrix() {
10102        ensureTransformationInfo();
10103        final Matrix matrix = mTransformationInfo.mMatrix;
10104        mRenderNode.getMatrix(matrix);
10105        return matrix;
10106    }
10107
10108    /**
10109     * Returns true if the transform matrix is the identity matrix.
10110     * Recomputes the matrix if necessary.
10111     *
10112     * @return True if the transform matrix is the identity matrix, false otherwise.
10113     */
10114    final boolean hasIdentityMatrix() {
10115        return mRenderNode.hasIdentityMatrix();
10116    }
10117
10118    void ensureTransformationInfo() {
10119        if (mTransformationInfo == null) {
10120            mTransformationInfo = new TransformationInfo();
10121        }
10122    }
10123
10124   /**
10125     * Utility method to retrieve the inverse of the current mMatrix property.
10126     * We cache the matrix to avoid recalculating it when transform properties
10127     * have not changed.
10128     *
10129     * @return The inverse of the current matrix of this view.
10130     * @hide
10131     */
10132    public final Matrix getInverseMatrix() {
10133        ensureTransformationInfo();
10134        if (mTransformationInfo.mInverseMatrix == null) {
10135            mTransformationInfo.mInverseMatrix = new Matrix();
10136        }
10137        final Matrix matrix = mTransformationInfo.mInverseMatrix;
10138        mRenderNode.getInverseMatrix(matrix);
10139        return matrix;
10140    }
10141
10142    /**
10143     * Gets the distance along the Z axis from the camera to this view.
10144     *
10145     * @see #setCameraDistance(float)
10146     *
10147     * @return The distance along the Z axis.
10148     */
10149    public float getCameraDistance() {
10150        final float dpi = mResources.getDisplayMetrics().densityDpi;
10151        return -(mRenderNode.getCameraDistance() * dpi);
10152    }
10153
10154    /**
10155     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10156     * views are drawn) from the camera to this view. The camera's distance
10157     * affects 3D transformations, for instance rotations around the X and Y
10158     * axis. If the rotationX or rotationY properties are changed and this view is
10159     * large (more than half the size of the screen), it is recommended to always
10160     * use a camera distance that's greater than the height (X axis rotation) or
10161     * the width (Y axis rotation) of this view.</p>
10162     *
10163     * <p>The distance of the camera from the view plane can have an affect on the
10164     * perspective distortion of the view when it is rotated around the x or y axis.
10165     * For example, a large distance will result in a large viewing angle, and there
10166     * will not be much perspective distortion of the view as it rotates. A short
10167     * distance may cause much more perspective distortion upon rotation, and can
10168     * also result in some drawing artifacts if the rotated view ends up partially
10169     * behind the camera (which is why the recommendation is to use a distance at
10170     * least as far as the size of the view, if the view is to be rotated.)</p>
10171     *
10172     * <p>The distance is expressed in "depth pixels." The default distance depends
10173     * on the screen density. For instance, on a medium density display, the
10174     * default distance is 1280. On a high density display, the default distance
10175     * is 1920.</p>
10176     *
10177     * <p>If you want to specify a distance that leads to visually consistent
10178     * results across various densities, use the following formula:</p>
10179     * <pre>
10180     * float scale = context.getResources().getDisplayMetrics().density;
10181     * view.setCameraDistance(distance * scale);
10182     * </pre>
10183     *
10184     * <p>The density scale factor of a high density display is 1.5,
10185     * and 1920 = 1280 * 1.5.</p>
10186     *
10187     * @param distance The distance in "depth pixels", if negative the opposite
10188     *        value is used
10189     *
10190     * @see #setRotationX(float)
10191     * @see #setRotationY(float)
10192     */
10193    public void setCameraDistance(float distance) {
10194        final float dpi = mResources.getDisplayMetrics().densityDpi;
10195
10196        invalidateViewProperty(true, false);
10197        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10198        invalidateViewProperty(false, false);
10199
10200        invalidateParentIfNeededAndWasQuickRejected();
10201    }
10202
10203    /**
10204     * The degrees that the view is rotated around the pivot point.
10205     *
10206     * @see #setRotation(float)
10207     * @see #getPivotX()
10208     * @see #getPivotY()
10209     *
10210     * @return The degrees of rotation.
10211     */
10212    @ViewDebug.ExportedProperty(category = "drawing")
10213    public float getRotation() {
10214        return mRenderNode.getRotation();
10215    }
10216
10217    /**
10218     * Sets the degrees that the view is rotated around the pivot point. Increasing values
10219     * result in clockwise rotation.
10220     *
10221     * @param rotation The degrees of rotation.
10222     *
10223     * @see #getRotation()
10224     * @see #getPivotX()
10225     * @see #getPivotY()
10226     * @see #setRotationX(float)
10227     * @see #setRotationY(float)
10228     *
10229     * @attr ref android.R.styleable#View_rotation
10230     */
10231    public void setRotation(float rotation) {
10232        if (rotation != getRotation()) {
10233            // Double-invalidation is necessary to capture view's old and new areas
10234            invalidateViewProperty(true, false);
10235            mRenderNode.setRotation(rotation);
10236            invalidateViewProperty(false, true);
10237
10238            invalidateParentIfNeededAndWasQuickRejected();
10239            notifySubtreeAccessibilityStateChangedIfNeeded();
10240        }
10241    }
10242
10243    /**
10244     * The degrees that the view is rotated around the vertical axis through the pivot point.
10245     *
10246     * @see #getPivotX()
10247     * @see #getPivotY()
10248     * @see #setRotationY(float)
10249     *
10250     * @return The degrees of Y rotation.
10251     */
10252    @ViewDebug.ExportedProperty(category = "drawing")
10253    public float getRotationY() {
10254        return mRenderNode.getRotationY();
10255    }
10256
10257    /**
10258     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10259     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10260     * down the y axis.
10261     *
10262     * When rotating large views, it is recommended to adjust the camera distance
10263     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10264     *
10265     * @param rotationY The degrees of Y rotation.
10266     *
10267     * @see #getRotationY()
10268     * @see #getPivotX()
10269     * @see #getPivotY()
10270     * @see #setRotation(float)
10271     * @see #setRotationX(float)
10272     * @see #setCameraDistance(float)
10273     *
10274     * @attr ref android.R.styleable#View_rotationY
10275     */
10276    public void setRotationY(float rotationY) {
10277        if (rotationY != getRotationY()) {
10278            invalidateViewProperty(true, false);
10279            mRenderNode.setRotationY(rotationY);
10280            invalidateViewProperty(false, true);
10281
10282            invalidateParentIfNeededAndWasQuickRejected();
10283            notifySubtreeAccessibilityStateChangedIfNeeded();
10284        }
10285    }
10286
10287    /**
10288     * The degrees that the view is rotated around the horizontal axis through the pivot point.
10289     *
10290     * @see #getPivotX()
10291     * @see #getPivotY()
10292     * @see #setRotationX(float)
10293     *
10294     * @return The degrees of X rotation.
10295     */
10296    @ViewDebug.ExportedProperty(category = "drawing")
10297    public float getRotationX() {
10298        return mRenderNode.getRotationX();
10299    }
10300
10301    /**
10302     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10303     * Increasing values result in clockwise rotation from the viewpoint of looking down the
10304     * x axis.
10305     *
10306     * When rotating large views, it is recommended to adjust the camera distance
10307     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10308     *
10309     * @param rotationX The degrees of X rotation.
10310     *
10311     * @see #getRotationX()
10312     * @see #getPivotX()
10313     * @see #getPivotY()
10314     * @see #setRotation(float)
10315     * @see #setRotationY(float)
10316     * @see #setCameraDistance(float)
10317     *
10318     * @attr ref android.R.styleable#View_rotationX
10319     */
10320    public void setRotationX(float rotationX) {
10321        if (rotationX != getRotationX()) {
10322            invalidateViewProperty(true, false);
10323            mRenderNode.setRotationX(rotationX);
10324            invalidateViewProperty(false, true);
10325
10326            invalidateParentIfNeededAndWasQuickRejected();
10327            notifySubtreeAccessibilityStateChangedIfNeeded();
10328        }
10329    }
10330
10331    /**
10332     * The amount that the view is scaled in x around the pivot point, as a proportion of
10333     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10334     *
10335     * <p>By default, this is 1.0f.
10336     *
10337     * @see #getPivotX()
10338     * @see #getPivotY()
10339     * @return The scaling factor.
10340     */
10341    @ViewDebug.ExportedProperty(category = "drawing")
10342    public float getScaleX() {
10343        return mRenderNode.getScaleX();
10344    }
10345
10346    /**
10347     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10348     * the view's unscaled width. A value of 1 means that no scaling is applied.
10349     *
10350     * @param scaleX The scaling factor.
10351     * @see #getPivotX()
10352     * @see #getPivotY()
10353     *
10354     * @attr ref android.R.styleable#View_scaleX
10355     */
10356    public void setScaleX(float scaleX) {
10357        if (scaleX != getScaleX()) {
10358            invalidateViewProperty(true, false);
10359            mRenderNode.setScaleX(scaleX);
10360            invalidateViewProperty(false, true);
10361
10362            invalidateParentIfNeededAndWasQuickRejected();
10363            notifySubtreeAccessibilityStateChangedIfNeeded();
10364        }
10365    }
10366
10367    /**
10368     * The amount that the view is scaled in y around the pivot point, as a proportion of
10369     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10370     *
10371     * <p>By default, this is 1.0f.
10372     *
10373     * @see #getPivotX()
10374     * @see #getPivotY()
10375     * @return The scaling factor.
10376     */
10377    @ViewDebug.ExportedProperty(category = "drawing")
10378    public float getScaleY() {
10379        return mRenderNode.getScaleY();
10380    }
10381
10382    /**
10383     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10384     * the view's unscaled width. A value of 1 means that no scaling is applied.
10385     *
10386     * @param scaleY The scaling factor.
10387     * @see #getPivotX()
10388     * @see #getPivotY()
10389     *
10390     * @attr ref android.R.styleable#View_scaleY
10391     */
10392    public void setScaleY(float scaleY) {
10393        if (scaleY != getScaleY()) {
10394            invalidateViewProperty(true, false);
10395            mRenderNode.setScaleY(scaleY);
10396            invalidateViewProperty(false, true);
10397
10398            invalidateParentIfNeededAndWasQuickRejected();
10399            notifySubtreeAccessibilityStateChangedIfNeeded();
10400        }
10401    }
10402
10403    /**
10404     * The x location of the point around which the view is {@link #setRotation(float) rotated}
10405     * and {@link #setScaleX(float) scaled}.
10406     *
10407     * @see #getRotation()
10408     * @see #getScaleX()
10409     * @see #getScaleY()
10410     * @see #getPivotY()
10411     * @return The x location of the pivot point.
10412     *
10413     * @attr ref android.R.styleable#View_transformPivotX
10414     */
10415    @ViewDebug.ExportedProperty(category = "drawing")
10416    public float getPivotX() {
10417        return mRenderNode.getPivotX();
10418    }
10419
10420    /**
10421     * Sets the x location of the point around which the view is
10422     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10423     * By default, the pivot point is centered on the object.
10424     * Setting this property disables this behavior and causes the view to use only the
10425     * explicitly set pivotX and pivotY values.
10426     *
10427     * @param pivotX The x location of the pivot point.
10428     * @see #getRotation()
10429     * @see #getScaleX()
10430     * @see #getScaleY()
10431     * @see #getPivotY()
10432     *
10433     * @attr ref android.R.styleable#View_transformPivotX
10434     */
10435    public void setPivotX(float pivotX) {
10436        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10437            invalidateViewProperty(true, false);
10438            mRenderNode.setPivotX(pivotX);
10439            invalidateViewProperty(false, true);
10440
10441            invalidateParentIfNeededAndWasQuickRejected();
10442        }
10443    }
10444
10445    /**
10446     * The y location of the point around which the view is {@link #setRotation(float) rotated}
10447     * and {@link #setScaleY(float) scaled}.
10448     *
10449     * @see #getRotation()
10450     * @see #getScaleX()
10451     * @see #getScaleY()
10452     * @see #getPivotY()
10453     * @return The y location of the pivot point.
10454     *
10455     * @attr ref android.R.styleable#View_transformPivotY
10456     */
10457    @ViewDebug.ExportedProperty(category = "drawing")
10458    public float getPivotY() {
10459        return mRenderNode.getPivotY();
10460    }
10461
10462    /**
10463     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10464     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10465     * Setting this property disables this behavior and causes the view to use only the
10466     * explicitly set pivotX and pivotY values.
10467     *
10468     * @param pivotY The y location of the pivot point.
10469     * @see #getRotation()
10470     * @see #getScaleX()
10471     * @see #getScaleY()
10472     * @see #getPivotY()
10473     *
10474     * @attr ref android.R.styleable#View_transformPivotY
10475     */
10476    public void setPivotY(float pivotY) {
10477        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10478            invalidateViewProperty(true, false);
10479            mRenderNode.setPivotY(pivotY);
10480            invalidateViewProperty(false, true);
10481
10482            invalidateParentIfNeededAndWasQuickRejected();
10483        }
10484    }
10485
10486    /**
10487     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10488     * completely transparent and 1 means the view is completely opaque.
10489     *
10490     * <p>By default this is 1.0f.
10491     * @return The opacity of the view.
10492     */
10493    @ViewDebug.ExportedProperty(category = "drawing")
10494    public float getAlpha() {
10495        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10496    }
10497
10498    /**
10499     * Returns whether this View has content which overlaps.
10500     *
10501     * <p>This function, intended to be overridden by specific View types, is an optimization when
10502     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10503     * an offscreen buffer and then composited into place, which can be expensive. If the view has
10504     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10505     * directly. An example of overlapping rendering is a TextView with a background image, such as
10506     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10507     * ImageView with only the foreground image. The default implementation returns true; subclasses
10508     * should override if they have cases which can be optimized.</p>
10509     *
10510     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10511     * necessitates that a View return true if it uses the methods internally without passing the
10512     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10513     *
10514     * @return true if the content in this view might overlap, false otherwise.
10515     */
10516    @ViewDebug.ExportedProperty(category = "drawing")
10517    public boolean hasOverlappingRendering() {
10518        return true;
10519    }
10520
10521    /**
10522     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10523     * completely transparent and 1 means the view is completely opaque.</p>
10524     *
10525     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10526     * performance implications, especially for large views. It is best to use the alpha property
10527     * sparingly and transiently, as in the case of fading animations.</p>
10528     *
10529     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10530     * strongly recommended for performance reasons to either override
10531     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10532     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10533     *
10534     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10535     * responsible for applying the opacity itself.</p>
10536     *
10537     * <p>Note that if the view is backed by a
10538     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10539     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10540     * 1.0 will supercede the alpha of the layer paint.</p>
10541     *
10542     * @param alpha The opacity of the view.
10543     *
10544     * @see #hasOverlappingRendering()
10545     * @see #setLayerType(int, android.graphics.Paint)
10546     *
10547     * @attr ref android.R.styleable#View_alpha
10548     */
10549    public void setAlpha(float alpha) {
10550        ensureTransformationInfo();
10551        if (mTransformationInfo.mAlpha != alpha) {
10552            mTransformationInfo.mAlpha = alpha;
10553            if (onSetAlpha((int) (alpha * 255))) {
10554                mPrivateFlags |= PFLAG_ALPHA_SET;
10555                // subclass is handling alpha - don't optimize rendering cache invalidation
10556                invalidateParentCaches();
10557                invalidate(true);
10558            } else {
10559                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10560                invalidateViewProperty(true, false);
10561                mRenderNode.setAlpha(getFinalAlpha());
10562                notifyViewAccessibilityStateChangedIfNeeded(
10563                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10564            }
10565        }
10566    }
10567
10568    /**
10569     * Faster version of setAlpha() which performs the same steps except there are
10570     * no calls to invalidate(). The caller of this function should perform proper invalidation
10571     * on the parent and this object. The return value indicates whether the subclass handles
10572     * alpha (the return value for onSetAlpha()).
10573     *
10574     * @param alpha The new value for the alpha property
10575     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10576     *         the new value for the alpha property is different from the old value
10577     */
10578    boolean setAlphaNoInvalidation(float alpha) {
10579        ensureTransformationInfo();
10580        if (mTransformationInfo.mAlpha != alpha) {
10581            mTransformationInfo.mAlpha = alpha;
10582            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10583            if (subclassHandlesAlpha) {
10584                mPrivateFlags |= PFLAG_ALPHA_SET;
10585                return true;
10586            } else {
10587                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10588                mRenderNode.setAlpha(getFinalAlpha());
10589            }
10590        }
10591        return false;
10592    }
10593
10594    /**
10595     * This property is hidden and intended only for use by the Fade transition, which
10596     * animates it to produce a visual translucency that does not side-effect (or get
10597     * affected by) the real alpha property. This value is composited with the other
10598     * alpha value (and the AlphaAnimation value, when that is present) to produce
10599     * a final visual translucency result, which is what is passed into the DisplayList.
10600     *
10601     * @hide
10602     */
10603    public void setTransitionAlpha(float alpha) {
10604        ensureTransformationInfo();
10605        if (mTransformationInfo.mTransitionAlpha != alpha) {
10606            mTransformationInfo.mTransitionAlpha = alpha;
10607            mPrivateFlags &= ~PFLAG_ALPHA_SET;
10608            invalidateViewProperty(true, false);
10609            mRenderNode.setAlpha(getFinalAlpha());
10610        }
10611    }
10612
10613    /**
10614     * Calculates the visual alpha of this view, which is a combination of the actual
10615     * alpha value and the transitionAlpha value (if set).
10616     */
10617    private float getFinalAlpha() {
10618        if (mTransformationInfo != null) {
10619            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10620        }
10621        return 1;
10622    }
10623
10624    /**
10625     * This property is hidden and intended only for use by the Fade transition, which
10626     * animates it to produce a visual translucency that does not side-effect (or get
10627     * affected by) the real alpha property. This value is composited with the other
10628     * alpha value (and the AlphaAnimation value, when that is present) to produce
10629     * a final visual translucency result, which is what is passed into the DisplayList.
10630     *
10631     * @hide
10632     */
10633    @ViewDebug.ExportedProperty(category = "drawing")
10634    public float getTransitionAlpha() {
10635        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10636    }
10637
10638    /**
10639     * Top position of this view relative to its parent.
10640     *
10641     * @return The top of this view, in pixels.
10642     */
10643    @ViewDebug.CapturedViewProperty
10644    public final int getTop() {
10645        return mTop;
10646    }
10647
10648    /**
10649     * Sets the top position of this view relative to its parent. This method is meant to be called
10650     * by the layout system and should not generally be called otherwise, because the property
10651     * may be changed at any time by the layout.
10652     *
10653     * @param top The top of this view, in pixels.
10654     */
10655    public final void setTop(int top) {
10656        if (top != mTop) {
10657            final boolean matrixIsIdentity = hasIdentityMatrix();
10658            if (matrixIsIdentity) {
10659                if (mAttachInfo != null) {
10660                    int minTop;
10661                    int yLoc;
10662                    if (top < mTop) {
10663                        minTop = top;
10664                        yLoc = top - mTop;
10665                    } else {
10666                        minTop = mTop;
10667                        yLoc = 0;
10668                    }
10669                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10670                }
10671            } else {
10672                // Double-invalidation is necessary to capture view's old and new areas
10673                invalidate(true);
10674            }
10675
10676            int width = mRight - mLeft;
10677            int oldHeight = mBottom - mTop;
10678
10679            mTop = top;
10680            mRenderNode.setTop(mTop);
10681
10682            sizeChange(width, mBottom - mTop, width, oldHeight);
10683
10684            if (!matrixIsIdentity) {
10685                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10686                invalidate(true);
10687            }
10688            mBackgroundSizeChanged = true;
10689            invalidateParentIfNeeded();
10690            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10691                // View was rejected last time it was drawn by its parent; this may have changed
10692                invalidateParentIfNeeded();
10693            }
10694        }
10695    }
10696
10697    /**
10698     * Bottom position of this view relative to its parent.
10699     *
10700     * @return The bottom of this view, in pixels.
10701     */
10702    @ViewDebug.CapturedViewProperty
10703    public final int getBottom() {
10704        return mBottom;
10705    }
10706
10707    /**
10708     * True if this view has changed since the last time being drawn.
10709     *
10710     * @return The dirty state of this view.
10711     */
10712    public boolean isDirty() {
10713        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10714    }
10715
10716    /**
10717     * Sets the bottom position of this view relative to its parent. This method is meant to be
10718     * called by the layout system and should not generally be called otherwise, because the
10719     * property may be changed at any time by the layout.
10720     *
10721     * @param bottom The bottom of this view, in pixels.
10722     */
10723    public final void setBottom(int bottom) {
10724        if (bottom != mBottom) {
10725            final boolean matrixIsIdentity = hasIdentityMatrix();
10726            if (matrixIsIdentity) {
10727                if (mAttachInfo != null) {
10728                    int maxBottom;
10729                    if (bottom < mBottom) {
10730                        maxBottom = mBottom;
10731                    } else {
10732                        maxBottom = bottom;
10733                    }
10734                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10735                }
10736            } else {
10737                // Double-invalidation is necessary to capture view's old and new areas
10738                invalidate(true);
10739            }
10740
10741            int width = mRight - mLeft;
10742            int oldHeight = mBottom - mTop;
10743
10744            mBottom = bottom;
10745            mRenderNode.setBottom(mBottom);
10746
10747            sizeChange(width, mBottom - mTop, width, oldHeight);
10748
10749            if (!matrixIsIdentity) {
10750                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10751                invalidate(true);
10752            }
10753            mBackgroundSizeChanged = true;
10754            invalidateParentIfNeeded();
10755            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10756                // View was rejected last time it was drawn by its parent; this may have changed
10757                invalidateParentIfNeeded();
10758            }
10759        }
10760    }
10761
10762    /**
10763     * Left position of this view relative to its parent.
10764     *
10765     * @return The left edge of this view, in pixels.
10766     */
10767    @ViewDebug.CapturedViewProperty
10768    public final int getLeft() {
10769        return mLeft;
10770    }
10771
10772    /**
10773     * Sets the left position of this view relative to its parent. This method is meant to be called
10774     * by the layout system and should not generally be called otherwise, because the property
10775     * may be changed at any time by the layout.
10776     *
10777     * @param left The left of this view, in pixels.
10778     */
10779    public final void setLeft(int left) {
10780        if (left != mLeft) {
10781            final boolean matrixIsIdentity = hasIdentityMatrix();
10782            if (matrixIsIdentity) {
10783                if (mAttachInfo != null) {
10784                    int minLeft;
10785                    int xLoc;
10786                    if (left < mLeft) {
10787                        minLeft = left;
10788                        xLoc = left - mLeft;
10789                    } else {
10790                        minLeft = mLeft;
10791                        xLoc = 0;
10792                    }
10793                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
10794                }
10795            } else {
10796                // Double-invalidation is necessary to capture view's old and new areas
10797                invalidate(true);
10798            }
10799
10800            int oldWidth = mRight - mLeft;
10801            int height = mBottom - mTop;
10802
10803            mLeft = left;
10804            mRenderNode.setLeft(left);
10805
10806            sizeChange(mRight - mLeft, height, oldWidth, height);
10807
10808            if (!matrixIsIdentity) {
10809                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10810                invalidate(true);
10811            }
10812            mBackgroundSizeChanged = true;
10813            invalidateParentIfNeeded();
10814            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10815                // View was rejected last time it was drawn by its parent; this may have changed
10816                invalidateParentIfNeeded();
10817            }
10818        }
10819    }
10820
10821    /**
10822     * Right position of this view relative to its parent.
10823     *
10824     * @return The right edge of this view, in pixels.
10825     */
10826    @ViewDebug.CapturedViewProperty
10827    public final int getRight() {
10828        return mRight;
10829    }
10830
10831    /**
10832     * Sets the right position of this view relative to its parent. This method is meant to be called
10833     * by the layout system and should not generally be called otherwise, because the property
10834     * may be changed at any time by the layout.
10835     *
10836     * @param right The right of this view, in pixels.
10837     */
10838    public final void setRight(int right) {
10839        if (right != mRight) {
10840            final boolean matrixIsIdentity = hasIdentityMatrix();
10841            if (matrixIsIdentity) {
10842                if (mAttachInfo != null) {
10843                    int maxRight;
10844                    if (right < mRight) {
10845                        maxRight = mRight;
10846                    } else {
10847                        maxRight = right;
10848                    }
10849                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
10850                }
10851            } else {
10852                // Double-invalidation is necessary to capture view's old and new areas
10853                invalidate(true);
10854            }
10855
10856            int oldWidth = mRight - mLeft;
10857            int height = mBottom - mTop;
10858
10859            mRight = right;
10860            mRenderNode.setRight(mRight);
10861
10862            sizeChange(mRight - mLeft, height, oldWidth, height);
10863
10864            if (!matrixIsIdentity) {
10865                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10866                invalidate(true);
10867            }
10868            mBackgroundSizeChanged = true;
10869            invalidateParentIfNeeded();
10870            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10871                // View was rejected last time it was drawn by its parent; this may have changed
10872                invalidateParentIfNeeded();
10873            }
10874        }
10875    }
10876
10877    /**
10878     * The visual x position of this view, in pixels. This is equivalent to the
10879     * {@link #setTranslationX(float) translationX} property plus the current
10880     * {@link #getLeft() left} property.
10881     *
10882     * @return The visual x position of this view, in pixels.
10883     */
10884    @ViewDebug.ExportedProperty(category = "drawing")
10885    public float getX() {
10886        return mLeft + getTranslationX();
10887    }
10888
10889    /**
10890     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
10891     * {@link #setTranslationX(float) translationX} property to be the difference between
10892     * the x value passed in and the current {@link #getLeft() left} property.
10893     *
10894     * @param x The visual x position of this view, in pixels.
10895     */
10896    public void setX(float x) {
10897        setTranslationX(x - mLeft);
10898    }
10899
10900    /**
10901     * The visual y position of this view, in pixels. This is equivalent to the
10902     * {@link #setTranslationY(float) translationY} property plus the current
10903     * {@link #getTop() top} property.
10904     *
10905     * @return The visual y position of this view, in pixels.
10906     */
10907    @ViewDebug.ExportedProperty(category = "drawing")
10908    public float getY() {
10909        return mTop + getTranslationY();
10910    }
10911
10912    /**
10913     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
10914     * {@link #setTranslationY(float) translationY} property to be the difference between
10915     * the y value passed in and the current {@link #getTop() top} property.
10916     *
10917     * @param y The visual y position of this view, in pixels.
10918     */
10919    public void setY(float y) {
10920        setTranslationY(y - mTop);
10921    }
10922
10923    /**
10924     * The visual z position of this view, in pixels. This is equivalent to the
10925     * {@link #setTranslationZ(float) translationZ} property plus the current
10926     * {@link #getElevation() elevation} property.
10927     *
10928     * @return The visual z position of this view, in pixels.
10929     */
10930    @ViewDebug.ExportedProperty(category = "drawing")
10931    public float getZ() {
10932        return getElevation() + getTranslationZ();
10933    }
10934
10935    /**
10936     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
10937     * {@link #setTranslationZ(float) translationZ} property to be the difference between
10938     * the x value passed in and the current {@link #getElevation() elevation} property.
10939     *
10940     * @param z The visual z position of this view, in pixels.
10941     */
10942    public void setZ(float z) {
10943        setTranslationZ(z - getElevation());
10944    }
10945
10946    /**
10947     * The base elevation of this view relative to its parent, in pixels.
10948     *
10949     * @return The base depth position of the view, in pixels.
10950     */
10951    @ViewDebug.ExportedProperty(category = "drawing")
10952    public float getElevation() {
10953        return mRenderNode.getElevation();
10954    }
10955
10956    /**
10957     * Sets the base elevation of this view, in pixels.
10958     *
10959     * @attr ref android.R.styleable#View_elevation
10960     */
10961    public void setElevation(float elevation) {
10962        if (elevation != getElevation()) {
10963            invalidateViewProperty(true, false);
10964            mRenderNode.setElevation(elevation);
10965            invalidateViewProperty(false, true);
10966
10967            invalidateParentIfNeededAndWasQuickRejected();
10968        }
10969    }
10970
10971    /**
10972     * The horizontal location of this view relative to its {@link #getLeft() left} position.
10973     * This position is post-layout, in addition to wherever the object's
10974     * layout placed it.
10975     *
10976     * @return The horizontal position of this view relative to its left position, in pixels.
10977     */
10978    @ViewDebug.ExportedProperty(category = "drawing")
10979    public float getTranslationX() {
10980        return mRenderNode.getTranslationX();
10981    }
10982
10983    /**
10984     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
10985     * This effectively positions the object post-layout, in addition to wherever the object's
10986     * layout placed it.
10987     *
10988     * @param translationX The horizontal position of this view relative to its left position,
10989     * in pixels.
10990     *
10991     * @attr ref android.R.styleable#View_translationX
10992     */
10993    public void setTranslationX(float translationX) {
10994        if (translationX != getTranslationX()) {
10995            invalidateViewProperty(true, false);
10996            mRenderNode.setTranslationX(translationX);
10997            invalidateViewProperty(false, true);
10998
10999            invalidateParentIfNeededAndWasQuickRejected();
11000            notifySubtreeAccessibilityStateChangedIfNeeded();
11001        }
11002    }
11003
11004    /**
11005     * The vertical location of this view relative to its {@link #getTop() top} position.
11006     * This position is post-layout, in addition to wherever the object's
11007     * layout placed it.
11008     *
11009     * @return The vertical position of this view relative to its top position,
11010     * in pixels.
11011     */
11012    @ViewDebug.ExportedProperty(category = "drawing")
11013    public float getTranslationY() {
11014        return mRenderNode.getTranslationY();
11015    }
11016
11017    /**
11018     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11019     * This effectively positions the object post-layout, in addition to wherever the object's
11020     * layout placed it.
11021     *
11022     * @param translationY The vertical position of this view relative to its top position,
11023     * in pixels.
11024     *
11025     * @attr ref android.R.styleable#View_translationY
11026     */
11027    public void setTranslationY(float translationY) {
11028        if (translationY != getTranslationY()) {
11029            invalidateViewProperty(true, false);
11030            mRenderNode.setTranslationY(translationY);
11031            invalidateViewProperty(false, true);
11032
11033            invalidateParentIfNeededAndWasQuickRejected();
11034        }
11035    }
11036
11037    /**
11038     * The depth location of this view relative to its {@link #getElevation() elevation}.
11039     *
11040     * @return The depth of this view relative to its elevation.
11041     */
11042    @ViewDebug.ExportedProperty(category = "drawing")
11043    public float getTranslationZ() {
11044        return mRenderNode.getTranslationZ();
11045    }
11046
11047    /**
11048     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11049     *
11050     * @attr ref android.R.styleable#View_translationZ
11051     */
11052    public void setTranslationZ(float translationZ) {
11053        if (translationZ != getTranslationZ()) {
11054            invalidateViewProperty(true, false);
11055            mRenderNode.setTranslationZ(translationZ);
11056            invalidateViewProperty(false, true);
11057
11058            invalidateParentIfNeededAndWasQuickRejected();
11059        }
11060    }
11061
11062    /** @hide */
11063    public void setAnimationMatrix(Matrix matrix) {
11064        invalidateViewProperty(true, false);
11065        mRenderNode.setAnimationMatrix(matrix);
11066        invalidateViewProperty(false, true);
11067
11068        invalidateParentIfNeededAndWasQuickRejected();
11069    }
11070
11071    /**
11072     * Returns the current StateListAnimator if exists.
11073     *
11074     * @return StateListAnimator or null if it does not exists
11075     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11076     */
11077    public StateListAnimator getStateListAnimator() {
11078        return mStateListAnimator;
11079    }
11080
11081    /**
11082     * Attaches the provided StateListAnimator to this View.
11083     * <p>
11084     * Any previously attached StateListAnimator will be detached.
11085     *
11086     * @param stateListAnimator The StateListAnimator to update the view
11087     * @see {@link android.animation.StateListAnimator}
11088     */
11089    public void setStateListAnimator(StateListAnimator stateListAnimator) {
11090        if (mStateListAnimator == stateListAnimator) {
11091            return;
11092        }
11093        if (mStateListAnimator != null) {
11094            mStateListAnimator.setTarget(null);
11095        }
11096        mStateListAnimator = stateListAnimator;
11097        if (stateListAnimator != null) {
11098            stateListAnimator.setTarget(this);
11099            if (isAttachedToWindow()) {
11100                stateListAnimator.setState(getDrawableState());
11101            }
11102        }
11103    }
11104
11105    /**
11106     * Returns whether the Outline should be used to clip the contents of the View.
11107     * <p>
11108     * Note that this flag will only be respected if the View's Outline returns true from
11109     * {@link Outline#canClip()}.
11110     *
11111     * @see #setOutlineProvider(ViewOutlineProvider)
11112     * @see #setClipToOutline(boolean)
11113     */
11114    public final boolean getClipToOutline() {
11115        return mRenderNode.getClipToOutline();
11116    }
11117
11118    /**
11119     * Sets whether the View's Outline should be used to clip the contents of the View.
11120     * <p>
11121     * Only a single non-rectangular clip can be applied on a View at any time.
11122     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11123     * circular reveal} animation take priority over Outline clipping, and
11124     * child Outline clipping takes priority over Outline clipping done by a
11125     * parent.
11126     * <p>
11127     * Note that this flag will only be respected if the View's Outline returns true from
11128     * {@link Outline#canClip()}.
11129     *
11130     * @see #setOutlineProvider(ViewOutlineProvider)
11131     * @see #getClipToOutline()
11132     */
11133    public void setClipToOutline(boolean clipToOutline) {
11134        damageInParent();
11135        if (getClipToOutline() != clipToOutline) {
11136            mRenderNode.setClipToOutline(clipToOutline);
11137        }
11138    }
11139
11140    // correspond to the enum values of View_outlineProvider
11141    private static final int PROVIDER_BACKGROUND = 0;
11142    private static final int PROVIDER_NONE = 1;
11143    private static final int PROVIDER_BOUNDS = 2;
11144    private static final int PROVIDER_PADDED_BOUNDS = 3;
11145    private void setOutlineProviderFromAttribute(int providerInt) {
11146        switch (providerInt) {
11147            case PROVIDER_BACKGROUND:
11148                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11149                break;
11150            case PROVIDER_NONE:
11151                setOutlineProvider(null);
11152                break;
11153            case PROVIDER_BOUNDS:
11154                setOutlineProvider(ViewOutlineProvider.BOUNDS);
11155                break;
11156            case PROVIDER_PADDED_BOUNDS:
11157                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11158                break;
11159        }
11160    }
11161
11162    /**
11163     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11164     * the shape of the shadow it casts, and enables outline clipping.
11165     * <p>
11166     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11167     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11168     * outline provider with this method allows this behavior to be overridden.
11169     * <p>
11170     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11171     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11172     * <p>
11173     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11174     *
11175     * @see #setClipToOutline(boolean)
11176     * @see #getClipToOutline()
11177     * @see #getOutlineProvider()
11178     */
11179    public void setOutlineProvider(ViewOutlineProvider provider) {
11180        mOutlineProvider = provider;
11181        invalidateOutline();
11182    }
11183
11184    /**
11185     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11186     * that defines the shape of the shadow it casts, and enables outline clipping.
11187     *
11188     * @see #setOutlineProvider(ViewOutlineProvider)
11189     */
11190    public ViewOutlineProvider getOutlineProvider() {
11191        return mOutlineProvider;
11192    }
11193
11194    /**
11195     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11196     *
11197     * @see #setOutlineProvider(ViewOutlineProvider)
11198     */
11199    public void invalidateOutline() {
11200        rebuildOutline();
11201
11202        notifySubtreeAccessibilityStateChangedIfNeeded();
11203        invalidateViewProperty(false, false);
11204    }
11205
11206    /**
11207     * Internal version of {@link #invalidateOutline()} which invalidates the
11208     * outline without invalidating the view itself. This is intended to be called from
11209     * within methods in the View class itself which are the result of the view being
11210     * invalidated already. For example, when we are drawing the background of a View,
11211     * we invalidate the outline in case it changed in the meantime, but we do not
11212     * need to invalidate the view because we're already drawing the background as part
11213     * of drawing the view in response to an earlier invalidation of the view.
11214     */
11215    private void rebuildOutline() {
11216        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11217        if (mAttachInfo == null) return;
11218
11219        if (mOutlineProvider == null) {
11220            // no provider, remove outline
11221            mRenderNode.setOutline(null);
11222        } else {
11223            final Outline outline = mAttachInfo.mTmpOutline;
11224            outline.setEmpty();
11225            outline.setAlpha(1.0f);
11226
11227            mOutlineProvider.getOutline(this, outline);
11228            mRenderNode.setOutline(outline);
11229        }
11230    }
11231
11232    /**
11233     * HierarchyViewer only
11234     *
11235     * @hide
11236     */
11237    @ViewDebug.ExportedProperty(category = "drawing")
11238    public boolean hasShadow() {
11239        return mRenderNode.hasShadow();
11240    }
11241
11242
11243    /** @hide */
11244    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11245        mRenderNode.setRevealClip(shouldClip, x, y, radius);
11246        invalidateViewProperty(false, false);
11247    }
11248
11249    /**
11250     * Hit rectangle in parent's coordinates
11251     *
11252     * @param outRect The hit rectangle of the view.
11253     */
11254    public void getHitRect(Rect outRect) {
11255        if (hasIdentityMatrix() || mAttachInfo == null) {
11256            outRect.set(mLeft, mTop, mRight, mBottom);
11257        } else {
11258            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11259            tmpRect.set(0, 0, getWidth(), getHeight());
11260            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11261            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11262                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11263        }
11264    }
11265
11266    /**
11267     * Determines whether the given point, in local coordinates is inside the view.
11268     */
11269    /*package*/ final boolean pointInView(float localX, float localY) {
11270        return localX >= 0 && localX < (mRight - mLeft)
11271                && localY >= 0 && localY < (mBottom - mTop);
11272    }
11273
11274    /**
11275     * Utility method to determine whether the given point, in local coordinates,
11276     * is inside the view, where the area of the view is expanded by the slop factor.
11277     * This method is called while processing touch-move events to determine if the event
11278     * is still within the view.
11279     *
11280     * @hide
11281     */
11282    public boolean pointInView(float localX, float localY, float slop) {
11283        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11284                localY < ((mBottom - mTop) + slop);
11285    }
11286
11287    /**
11288     * When a view has focus and the user navigates away from it, the next view is searched for
11289     * starting from the rectangle filled in by this method.
11290     *
11291     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11292     * of the view.  However, if your view maintains some idea of internal selection,
11293     * such as a cursor, or a selected row or column, you should override this method and
11294     * fill in a more specific rectangle.
11295     *
11296     * @param r The rectangle to fill in, in this view's coordinates.
11297     */
11298    public void getFocusedRect(Rect r) {
11299        getDrawingRect(r);
11300    }
11301
11302    /**
11303     * If some part of this view is not clipped by any of its parents, then
11304     * return that area in r in global (root) coordinates. To convert r to local
11305     * coordinates (without taking possible View rotations into account), offset
11306     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11307     * If the view is completely clipped or translated out, return false.
11308     *
11309     * @param r If true is returned, r holds the global coordinates of the
11310     *        visible portion of this view.
11311     * @param globalOffset If true is returned, globalOffset holds the dx,dy
11312     *        between this view and its root. globalOffet may be null.
11313     * @return true if r is non-empty (i.e. part of the view is visible at the
11314     *         root level.
11315     */
11316    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11317        int width = mRight - mLeft;
11318        int height = mBottom - mTop;
11319        if (width > 0 && height > 0) {
11320            r.set(0, 0, width, height);
11321            if (globalOffset != null) {
11322                globalOffset.set(-mScrollX, -mScrollY);
11323            }
11324            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11325        }
11326        return false;
11327    }
11328
11329    public final boolean getGlobalVisibleRect(Rect r) {
11330        return getGlobalVisibleRect(r, null);
11331    }
11332
11333    public final boolean getLocalVisibleRect(Rect r) {
11334        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11335        if (getGlobalVisibleRect(r, offset)) {
11336            r.offset(-offset.x, -offset.y); // make r local
11337            return true;
11338        }
11339        return false;
11340    }
11341
11342    /**
11343     * Offset this view's vertical location by the specified number of pixels.
11344     *
11345     * @param offset the number of pixels to offset the view by
11346     */
11347    public void offsetTopAndBottom(int offset) {
11348        if (offset != 0) {
11349            final boolean matrixIsIdentity = hasIdentityMatrix();
11350            if (matrixIsIdentity) {
11351                if (isHardwareAccelerated()) {
11352                    invalidateViewProperty(false, false);
11353                } else {
11354                    final ViewParent p = mParent;
11355                    if (p != null && mAttachInfo != null) {
11356                        final Rect r = mAttachInfo.mTmpInvalRect;
11357                        int minTop;
11358                        int maxBottom;
11359                        int yLoc;
11360                        if (offset < 0) {
11361                            minTop = mTop + offset;
11362                            maxBottom = mBottom;
11363                            yLoc = offset;
11364                        } else {
11365                            minTop = mTop;
11366                            maxBottom = mBottom + offset;
11367                            yLoc = 0;
11368                        }
11369                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11370                        p.invalidateChild(this, r);
11371                    }
11372                }
11373            } else {
11374                invalidateViewProperty(false, false);
11375            }
11376
11377            mTop += offset;
11378            mBottom += offset;
11379            mRenderNode.offsetTopAndBottom(offset);
11380            if (isHardwareAccelerated()) {
11381                invalidateViewProperty(false, false);
11382            } else {
11383                if (!matrixIsIdentity) {
11384                    invalidateViewProperty(false, true);
11385                }
11386                invalidateParentIfNeeded();
11387            }
11388            notifySubtreeAccessibilityStateChangedIfNeeded();
11389        }
11390    }
11391
11392    /**
11393     * Offset this view's horizontal location by the specified amount of pixels.
11394     *
11395     * @param offset the number of pixels to offset the view by
11396     */
11397    public void offsetLeftAndRight(int offset) {
11398        if (offset != 0) {
11399            final boolean matrixIsIdentity = hasIdentityMatrix();
11400            if (matrixIsIdentity) {
11401                if (isHardwareAccelerated()) {
11402                    invalidateViewProperty(false, false);
11403                } else {
11404                    final ViewParent p = mParent;
11405                    if (p != null && mAttachInfo != null) {
11406                        final Rect r = mAttachInfo.mTmpInvalRect;
11407                        int minLeft;
11408                        int maxRight;
11409                        if (offset < 0) {
11410                            minLeft = mLeft + offset;
11411                            maxRight = mRight;
11412                        } else {
11413                            minLeft = mLeft;
11414                            maxRight = mRight + offset;
11415                        }
11416                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11417                        p.invalidateChild(this, r);
11418                    }
11419                }
11420            } else {
11421                invalidateViewProperty(false, false);
11422            }
11423
11424            mLeft += offset;
11425            mRight += offset;
11426            mRenderNode.offsetLeftAndRight(offset);
11427            if (isHardwareAccelerated()) {
11428                invalidateViewProperty(false, false);
11429            } else {
11430                if (!matrixIsIdentity) {
11431                    invalidateViewProperty(false, true);
11432                }
11433                invalidateParentIfNeeded();
11434            }
11435            notifySubtreeAccessibilityStateChangedIfNeeded();
11436        }
11437    }
11438
11439    /**
11440     * Get the LayoutParams associated with this view. All views should have
11441     * layout parameters. These supply parameters to the <i>parent</i> of this
11442     * view specifying how it should be arranged. There are many subclasses of
11443     * ViewGroup.LayoutParams, and these correspond to the different subclasses
11444     * of ViewGroup that are responsible for arranging their children.
11445     *
11446     * This method may return null if this View is not attached to a parent
11447     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11448     * was not invoked successfully. When a View is attached to a parent
11449     * ViewGroup, this method must not return null.
11450     *
11451     * @return The LayoutParams associated with this view, or null if no
11452     *         parameters have been set yet
11453     */
11454    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11455    public ViewGroup.LayoutParams getLayoutParams() {
11456        return mLayoutParams;
11457    }
11458
11459    /**
11460     * Set the layout parameters associated with this view. These supply
11461     * parameters to the <i>parent</i> of this view specifying how it should be
11462     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11463     * correspond to the different subclasses of ViewGroup that are responsible
11464     * for arranging their children.
11465     *
11466     * @param params The layout parameters for this view, cannot be null
11467     */
11468    public void setLayoutParams(ViewGroup.LayoutParams params) {
11469        if (params == null) {
11470            throw new NullPointerException("Layout parameters cannot be null");
11471        }
11472        mLayoutParams = params;
11473        resolveLayoutParams();
11474        if (mParent instanceof ViewGroup) {
11475            ((ViewGroup) mParent).onSetLayoutParams(this, params);
11476        }
11477        requestLayout();
11478    }
11479
11480    /**
11481     * Resolve the layout parameters depending on the resolved layout direction
11482     *
11483     * @hide
11484     */
11485    public void resolveLayoutParams() {
11486        if (mLayoutParams != null) {
11487            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11488        }
11489    }
11490
11491    /**
11492     * Set the scrolled position of your view. This will cause a call to
11493     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11494     * invalidated.
11495     * @param x the x position to scroll to
11496     * @param y the y position to scroll to
11497     */
11498    public void scrollTo(int x, int y) {
11499        if (mScrollX != x || mScrollY != y) {
11500            int oldX = mScrollX;
11501            int oldY = mScrollY;
11502            mScrollX = x;
11503            mScrollY = y;
11504            invalidateParentCaches();
11505            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11506            if (!awakenScrollBars()) {
11507                postInvalidateOnAnimation();
11508            }
11509        }
11510    }
11511
11512    /**
11513     * Move the scrolled position of your view. This will cause a call to
11514     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11515     * invalidated.
11516     * @param x the amount of pixels to scroll by horizontally
11517     * @param y the amount of pixels to scroll by vertically
11518     */
11519    public void scrollBy(int x, int y) {
11520        scrollTo(mScrollX + x, mScrollY + y);
11521    }
11522
11523    /**
11524     * <p>Trigger the scrollbars to draw. When invoked this method starts an
11525     * animation to fade the scrollbars out after a default delay. If a subclass
11526     * provides animated scrolling, the start delay should equal the duration
11527     * of the scrolling animation.</p>
11528     *
11529     * <p>The animation starts only if at least one of the scrollbars is
11530     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11531     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11532     * this method returns true, and false otherwise. If the animation is
11533     * started, this method calls {@link #invalidate()}; in that case the
11534     * caller should not call {@link #invalidate()}.</p>
11535     *
11536     * <p>This method should be invoked every time a subclass directly updates
11537     * the scroll parameters.</p>
11538     *
11539     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11540     * and {@link #scrollTo(int, int)}.</p>
11541     *
11542     * @return true if the animation is played, false otherwise
11543     *
11544     * @see #awakenScrollBars(int)
11545     * @see #scrollBy(int, int)
11546     * @see #scrollTo(int, int)
11547     * @see #isHorizontalScrollBarEnabled()
11548     * @see #isVerticalScrollBarEnabled()
11549     * @see #setHorizontalScrollBarEnabled(boolean)
11550     * @see #setVerticalScrollBarEnabled(boolean)
11551     */
11552    protected boolean awakenScrollBars() {
11553        return mScrollCache != null &&
11554                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11555    }
11556
11557    /**
11558     * Trigger the scrollbars to draw.
11559     * This method differs from awakenScrollBars() only in its default duration.
11560     * initialAwakenScrollBars() will show the scroll bars for longer than
11561     * usual to give the user more of a chance to notice them.
11562     *
11563     * @return true if the animation is played, false otherwise.
11564     */
11565    private boolean initialAwakenScrollBars() {
11566        return mScrollCache != null &&
11567                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11568    }
11569
11570    /**
11571     * <p>
11572     * Trigger the scrollbars to draw. When invoked this method starts an
11573     * animation to fade the scrollbars out after a fixed delay. If a subclass
11574     * provides animated scrolling, the start delay should equal the duration of
11575     * the scrolling animation.
11576     * </p>
11577     *
11578     * <p>
11579     * The animation starts only if at least one of the scrollbars is enabled,
11580     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11581     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11582     * this method returns true, and false otherwise. If the animation is
11583     * started, this method calls {@link #invalidate()}; in that case the caller
11584     * should not call {@link #invalidate()}.
11585     * </p>
11586     *
11587     * <p>
11588     * This method should be invoked everytime a subclass directly updates the
11589     * scroll parameters.
11590     * </p>
11591     *
11592     * @param startDelay the delay, in milliseconds, after which the animation
11593     *        should start; when the delay is 0, the animation starts
11594     *        immediately
11595     * @return true if the animation is played, false otherwise
11596     *
11597     * @see #scrollBy(int, int)
11598     * @see #scrollTo(int, int)
11599     * @see #isHorizontalScrollBarEnabled()
11600     * @see #isVerticalScrollBarEnabled()
11601     * @see #setHorizontalScrollBarEnabled(boolean)
11602     * @see #setVerticalScrollBarEnabled(boolean)
11603     */
11604    protected boolean awakenScrollBars(int startDelay) {
11605        return awakenScrollBars(startDelay, true);
11606    }
11607
11608    /**
11609     * <p>
11610     * Trigger the scrollbars to draw. When invoked this method starts an
11611     * animation to fade the scrollbars out after a fixed delay. If a subclass
11612     * provides animated scrolling, the start delay should equal the duration of
11613     * the scrolling animation.
11614     * </p>
11615     *
11616     * <p>
11617     * The animation starts only if at least one of the scrollbars is enabled,
11618     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11619     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11620     * this method returns true, and false otherwise. If the animation is
11621     * started, this method calls {@link #invalidate()} if the invalidate parameter
11622     * is set to true; in that case the caller
11623     * should not call {@link #invalidate()}.
11624     * </p>
11625     *
11626     * <p>
11627     * This method should be invoked everytime a subclass directly updates the
11628     * scroll parameters.
11629     * </p>
11630     *
11631     * @param startDelay the delay, in milliseconds, after which the animation
11632     *        should start; when the delay is 0, the animation starts
11633     *        immediately
11634     *
11635     * @param invalidate Wheter this method should call invalidate
11636     *
11637     * @return true if the animation is played, false otherwise
11638     *
11639     * @see #scrollBy(int, int)
11640     * @see #scrollTo(int, int)
11641     * @see #isHorizontalScrollBarEnabled()
11642     * @see #isVerticalScrollBarEnabled()
11643     * @see #setHorizontalScrollBarEnabled(boolean)
11644     * @see #setVerticalScrollBarEnabled(boolean)
11645     */
11646    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11647        final ScrollabilityCache scrollCache = mScrollCache;
11648
11649        if (scrollCache == null || !scrollCache.fadeScrollBars) {
11650            return false;
11651        }
11652
11653        if (scrollCache.scrollBar == null) {
11654            scrollCache.scrollBar = new ScrollBarDrawable();
11655        }
11656
11657        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11658
11659            if (invalidate) {
11660                // Invalidate to show the scrollbars
11661                postInvalidateOnAnimation();
11662            }
11663
11664            if (scrollCache.state == ScrollabilityCache.OFF) {
11665                // FIXME: this is copied from WindowManagerService.
11666                // We should get this value from the system when it
11667                // is possible to do so.
11668                final int KEY_REPEAT_FIRST_DELAY = 750;
11669                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11670            }
11671
11672            // Tell mScrollCache when we should start fading. This may
11673            // extend the fade start time if one was already scheduled
11674            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11675            scrollCache.fadeStartTime = fadeStartTime;
11676            scrollCache.state = ScrollabilityCache.ON;
11677
11678            // Schedule our fader to run, unscheduling any old ones first
11679            if (mAttachInfo != null) {
11680                mAttachInfo.mHandler.removeCallbacks(scrollCache);
11681                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11682            }
11683
11684            return true;
11685        }
11686
11687        return false;
11688    }
11689
11690    /**
11691     * Do not invalidate views which are not visible and which are not running an animation. They
11692     * will not get drawn and they should not set dirty flags as if they will be drawn
11693     */
11694    private boolean skipInvalidate() {
11695        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11696                (!(mParent instanceof ViewGroup) ||
11697                        !((ViewGroup) mParent).isViewTransitioning(this));
11698    }
11699
11700    /**
11701     * Mark the area defined by dirty as needing to be drawn. If the view is
11702     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11703     * point in the future.
11704     * <p>
11705     * This must be called from a UI thread. To call from a non-UI thread, call
11706     * {@link #postInvalidate()}.
11707     * <p>
11708     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11709     * {@code dirty}.
11710     *
11711     * @param dirty the rectangle representing the bounds of the dirty region
11712     */
11713    public void invalidate(Rect dirty) {
11714        final int scrollX = mScrollX;
11715        final int scrollY = mScrollY;
11716        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11717                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11718    }
11719
11720    /**
11721     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11722     * coordinates of the dirty rect are relative to the view. If the view is
11723     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11724     * point in the future.
11725     * <p>
11726     * This must be called from a UI thread. To call from a non-UI thread, call
11727     * {@link #postInvalidate()}.
11728     *
11729     * @param l the left position of the dirty region
11730     * @param t the top position of the dirty region
11731     * @param r the right position of the dirty region
11732     * @param b the bottom position of the dirty region
11733     */
11734    public void invalidate(int l, int t, int r, int b) {
11735        final int scrollX = mScrollX;
11736        final int scrollY = mScrollY;
11737        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
11738    }
11739
11740    /**
11741     * Invalidate the whole view. If the view is visible,
11742     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
11743     * the future.
11744     * <p>
11745     * This must be called from a UI thread. To call from a non-UI thread, call
11746     * {@link #postInvalidate()}.
11747     */
11748    public void invalidate() {
11749        invalidate(true);
11750    }
11751
11752    /**
11753     * This is where the invalidate() work actually happens. A full invalidate()
11754     * causes the drawing cache to be invalidated, but this function can be
11755     * called with invalidateCache set to false to skip that invalidation step
11756     * for cases that do not need it (for example, a component that remains at
11757     * the same dimensions with the same content).
11758     *
11759     * @param invalidateCache Whether the drawing cache for this view should be
11760     *            invalidated as well. This is usually true for a full
11761     *            invalidate, but may be set to false if the View's contents or
11762     *            dimensions have not changed.
11763     */
11764    void invalidate(boolean invalidateCache) {
11765        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
11766    }
11767
11768    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
11769            boolean fullInvalidate) {
11770        if (mGhostView != null) {
11771            mGhostView.invalidate(true);
11772            return;
11773        }
11774
11775        if (skipInvalidate()) {
11776            return;
11777        }
11778
11779        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
11780                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
11781                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
11782                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
11783            if (fullInvalidate) {
11784                mLastIsOpaque = isOpaque();
11785                mPrivateFlags &= ~PFLAG_DRAWN;
11786            }
11787
11788            mPrivateFlags |= PFLAG_DIRTY;
11789
11790            if (invalidateCache) {
11791                mPrivateFlags |= PFLAG_INVALIDATED;
11792                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
11793            }
11794
11795            // Propagate the damage rectangle to the parent view.
11796            final AttachInfo ai = mAttachInfo;
11797            final ViewParent p = mParent;
11798            if (p != null && ai != null && l < r && t < b) {
11799                final Rect damage = ai.mTmpInvalRect;
11800                damage.set(l, t, r, b);
11801                p.invalidateChild(this, damage);
11802            }
11803
11804            // Damage the entire projection receiver, if necessary.
11805            if (mBackground != null && mBackground.isProjected()) {
11806                final View receiver = getProjectionReceiver();
11807                if (receiver != null) {
11808                    receiver.damageInParent();
11809                }
11810            }
11811
11812            // Damage the entire IsolatedZVolume receiving this view's shadow.
11813            if (isHardwareAccelerated() && getZ() != 0) {
11814                damageShadowReceiver();
11815            }
11816        }
11817    }
11818
11819    /**
11820     * @return this view's projection receiver, or {@code null} if none exists
11821     */
11822    private View getProjectionReceiver() {
11823        ViewParent p = getParent();
11824        while (p != null && p instanceof View) {
11825            final View v = (View) p;
11826            if (v.isProjectionReceiver()) {
11827                return v;
11828            }
11829            p = p.getParent();
11830        }
11831
11832        return null;
11833    }
11834
11835    /**
11836     * @return whether the view is a projection receiver
11837     */
11838    private boolean isProjectionReceiver() {
11839        return mBackground != null;
11840    }
11841
11842    /**
11843     * Damage area of the screen that can be covered by this View's shadow.
11844     *
11845     * This method will guarantee that any changes to shadows cast by a View
11846     * are damaged on the screen for future redraw.
11847     */
11848    private void damageShadowReceiver() {
11849        final AttachInfo ai = mAttachInfo;
11850        if (ai != null) {
11851            ViewParent p = getParent();
11852            if (p != null && p instanceof ViewGroup) {
11853                final ViewGroup vg = (ViewGroup) p;
11854                vg.damageInParent();
11855            }
11856        }
11857    }
11858
11859    /**
11860     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
11861     * set any flags or handle all of the cases handled by the default invalidation methods.
11862     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
11863     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
11864     * walk up the hierarchy, transforming the dirty rect as necessary.
11865     *
11866     * The method also handles normal invalidation logic if display list properties are not
11867     * being used in this view. The invalidateParent and forceRedraw flags are used by that
11868     * backup approach, to handle these cases used in the various property-setting methods.
11869     *
11870     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
11871     * are not being used in this view
11872     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
11873     * list properties are not being used in this view
11874     */
11875    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
11876        if (!isHardwareAccelerated()
11877                || !mRenderNode.isValid()
11878                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
11879            if (invalidateParent) {
11880                invalidateParentCaches();
11881            }
11882            if (forceRedraw) {
11883                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11884            }
11885            invalidate(false);
11886        } else {
11887            damageInParent();
11888        }
11889        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
11890            damageShadowReceiver();
11891        }
11892    }
11893
11894    /**
11895     * Tells the parent view to damage this view's bounds.
11896     *
11897     * @hide
11898     */
11899    protected void damageInParent() {
11900        final AttachInfo ai = mAttachInfo;
11901        final ViewParent p = mParent;
11902        if (p != null && ai != null) {
11903            final Rect r = ai.mTmpInvalRect;
11904            r.set(0, 0, mRight - mLeft, mBottom - mTop);
11905            if (mParent instanceof ViewGroup) {
11906                ((ViewGroup) mParent).damageChild(this, r);
11907            } else {
11908                mParent.invalidateChild(this, r);
11909            }
11910        }
11911    }
11912
11913    /**
11914     * Utility method to transform a given Rect by the current matrix of this view.
11915     */
11916    void transformRect(final Rect rect) {
11917        if (!getMatrix().isIdentity()) {
11918            RectF boundingRect = mAttachInfo.mTmpTransformRect;
11919            boundingRect.set(rect);
11920            getMatrix().mapRect(boundingRect);
11921            rect.set((int) Math.floor(boundingRect.left),
11922                    (int) Math.floor(boundingRect.top),
11923                    (int) Math.ceil(boundingRect.right),
11924                    (int) Math.ceil(boundingRect.bottom));
11925        }
11926    }
11927
11928    /**
11929     * Used to indicate that the parent of this view should clear its caches. This functionality
11930     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11931     * which is necessary when various parent-managed properties of the view change, such as
11932     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
11933     * clears the parent caches and does not causes an invalidate event.
11934     *
11935     * @hide
11936     */
11937    protected void invalidateParentCaches() {
11938        if (mParent instanceof View) {
11939            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
11940        }
11941    }
11942
11943    /**
11944     * Used to indicate that the parent of this view should be invalidated. This functionality
11945     * is used to force the parent to rebuild its display list (when hardware-accelerated),
11946     * which is necessary when various parent-managed properties of the view change, such as
11947     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
11948     * an invalidation event to the parent.
11949     *
11950     * @hide
11951     */
11952    protected void invalidateParentIfNeeded() {
11953        if (isHardwareAccelerated() && mParent instanceof View) {
11954            ((View) mParent).invalidate(true);
11955        }
11956    }
11957
11958    /**
11959     * @hide
11960     */
11961    protected void invalidateParentIfNeededAndWasQuickRejected() {
11962        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
11963            // View was rejected last time it was drawn by its parent; this may have changed
11964            invalidateParentIfNeeded();
11965        }
11966    }
11967
11968    /**
11969     * Indicates whether this View is opaque. An opaque View guarantees that it will
11970     * draw all the pixels overlapping its bounds using a fully opaque color.
11971     *
11972     * Subclasses of View should override this method whenever possible to indicate
11973     * whether an instance is opaque. Opaque Views are treated in a special way by
11974     * the View hierarchy, possibly allowing it to perform optimizations during
11975     * invalidate/draw passes.
11976     *
11977     * @return True if this View is guaranteed to be fully opaque, false otherwise.
11978     */
11979    @ViewDebug.ExportedProperty(category = "drawing")
11980    public boolean isOpaque() {
11981        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
11982                getFinalAlpha() >= 1.0f;
11983    }
11984
11985    /**
11986     * @hide
11987     */
11988    protected void computeOpaqueFlags() {
11989        // Opaque if:
11990        //   - Has a background
11991        //   - Background is opaque
11992        //   - Doesn't have scrollbars or scrollbars overlay
11993
11994        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
11995            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
11996        } else {
11997            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
11998        }
11999
12000        final int flags = mViewFlags;
12001        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12002                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12003                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12004            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12005        } else {
12006            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12007        }
12008    }
12009
12010    /**
12011     * @hide
12012     */
12013    protected boolean hasOpaqueScrollbars() {
12014        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12015    }
12016
12017    /**
12018     * @return A handler associated with the thread running the View. This
12019     * handler can be used to pump events in the UI events queue.
12020     */
12021    public Handler getHandler() {
12022        final AttachInfo attachInfo = mAttachInfo;
12023        if (attachInfo != null) {
12024            return attachInfo.mHandler;
12025        }
12026        return null;
12027    }
12028
12029    /**
12030     * Gets the view root associated with the View.
12031     * @return The view root, or null if none.
12032     * @hide
12033     */
12034    public ViewRootImpl getViewRootImpl() {
12035        if (mAttachInfo != null) {
12036            return mAttachInfo.mViewRootImpl;
12037        }
12038        return null;
12039    }
12040
12041    /**
12042     * @hide
12043     */
12044    public HardwareRenderer getHardwareRenderer() {
12045        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12046    }
12047
12048    /**
12049     * <p>Causes the Runnable to be added to the message queue.
12050     * The runnable will be run on the user interface thread.</p>
12051     *
12052     * @param action The Runnable that will be executed.
12053     *
12054     * @return Returns true if the Runnable was successfully placed in to the
12055     *         message queue.  Returns false on failure, usually because the
12056     *         looper processing the message queue is exiting.
12057     *
12058     * @see #postDelayed
12059     * @see #removeCallbacks
12060     */
12061    public boolean post(Runnable action) {
12062        final AttachInfo attachInfo = mAttachInfo;
12063        if (attachInfo != null) {
12064            return attachInfo.mHandler.post(action);
12065        }
12066        // Assume that post will succeed later
12067        ViewRootImpl.getRunQueue().post(action);
12068        return true;
12069    }
12070
12071    /**
12072     * <p>Causes the Runnable to be added to the message queue, to be run
12073     * after the specified amount of time elapses.
12074     * The runnable will be run on the user interface thread.</p>
12075     *
12076     * @param action The Runnable that will be executed.
12077     * @param delayMillis The delay (in milliseconds) until the Runnable
12078     *        will be executed.
12079     *
12080     * @return true if the Runnable was successfully placed in to the
12081     *         message queue.  Returns false on failure, usually because the
12082     *         looper processing the message queue is exiting.  Note that a
12083     *         result of true does not mean the Runnable will be processed --
12084     *         if the looper is quit before the delivery time of the message
12085     *         occurs then the message will be dropped.
12086     *
12087     * @see #post
12088     * @see #removeCallbacks
12089     */
12090    public boolean postDelayed(Runnable action, long delayMillis) {
12091        final AttachInfo attachInfo = mAttachInfo;
12092        if (attachInfo != null) {
12093            return attachInfo.mHandler.postDelayed(action, delayMillis);
12094        }
12095        // Assume that post will succeed later
12096        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12097        return true;
12098    }
12099
12100    /**
12101     * <p>Causes the Runnable to execute on the next animation time step.
12102     * The runnable will be run on the user interface thread.</p>
12103     *
12104     * @param action The Runnable that will be executed.
12105     *
12106     * @see #postOnAnimationDelayed
12107     * @see #removeCallbacks
12108     */
12109    public void postOnAnimation(Runnable action) {
12110        final AttachInfo attachInfo = mAttachInfo;
12111        if (attachInfo != null) {
12112            attachInfo.mViewRootImpl.mChoreographer.postCallback(
12113                    Choreographer.CALLBACK_ANIMATION, action, null);
12114        } else {
12115            // Assume that post will succeed later
12116            ViewRootImpl.getRunQueue().post(action);
12117        }
12118    }
12119
12120    /**
12121     * <p>Causes the Runnable to execute on the next animation time step,
12122     * after the specified amount of time elapses.
12123     * The runnable will be run on the user interface thread.</p>
12124     *
12125     * @param action The Runnable that will be executed.
12126     * @param delayMillis The delay (in milliseconds) until the Runnable
12127     *        will be executed.
12128     *
12129     * @see #postOnAnimation
12130     * @see #removeCallbacks
12131     */
12132    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12133        final AttachInfo attachInfo = mAttachInfo;
12134        if (attachInfo != null) {
12135            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12136                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12137        } else {
12138            // Assume that post will succeed later
12139            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12140        }
12141    }
12142
12143    /**
12144     * <p>Removes the specified Runnable from the message queue.</p>
12145     *
12146     * @param action The Runnable to remove from the message handling queue
12147     *
12148     * @return true if this view could ask the Handler to remove the Runnable,
12149     *         false otherwise. When the returned value is true, the Runnable
12150     *         may or may not have been actually removed from the message queue
12151     *         (for instance, if the Runnable was not in the queue already.)
12152     *
12153     * @see #post
12154     * @see #postDelayed
12155     * @see #postOnAnimation
12156     * @see #postOnAnimationDelayed
12157     */
12158    public boolean removeCallbacks(Runnable action) {
12159        if (action != null) {
12160            final AttachInfo attachInfo = mAttachInfo;
12161            if (attachInfo != null) {
12162                attachInfo.mHandler.removeCallbacks(action);
12163                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12164                        Choreographer.CALLBACK_ANIMATION, action, null);
12165            }
12166            // Assume that post will succeed later
12167            ViewRootImpl.getRunQueue().removeCallbacks(action);
12168        }
12169        return true;
12170    }
12171
12172    /**
12173     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12174     * Use this to invalidate the View from a non-UI thread.</p>
12175     *
12176     * <p>This method can be invoked from outside of the UI thread
12177     * only when this View is attached to a window.</p>
12178     *
12179     * @see #invalidate()
12180     * @see #postInvalidateDelayed(long)
12181     */
12182    public void postInvalidate() {
12183        postInvalidateDelayed(0);
12184    }
12185
12186    /**
12187     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12188     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12189     *
12190     * <p>This method can be invoked from outside of the UI thread
12191     * only when this View is attached to a window.</p>
12192     *
12193     * @param left The left coordinate of the rectangle to invalidate.
12194     * @param top The top coordinate of the rectangle to invalidate.
12195     * @param right The right coordinate of the rectangle to invalidate.
12196     * @param bottom The bottom coordinate of the rectangle to invalidate.
12197     *
12198     * @see #invalidate(int, int, int, int)
12199     * @see #invalidate(Rect)
12200     * @see #postInvalidateDelayed(long, int, int, int, int)
12201     */
12202    public void postInvalidate(int left, int top, int right, int bottom) {
12203        postInvalidateDelayed(0, left, top, right, bottom);
12204    }
12205
12206    /**
12207     * <p>Cause an invalidate to happen on a subsequent cycle through the event
12208     * loop. Waits for the specified amount of time.</p>
12209     *
12210     * <p>This method can be invoked from outside of the UI thread
12211     * only when this View is attached to a window.</p>
12212     *
12213     * @param delayMilliseconds the duration in milliseconds to delay the
12214     *         invalidation by
12215     *
12216     * @see #invalidate()
12217     * @see #postInvalidate()
12218     */
12219    public void postInvalidateDelayed(long delayMilliseconds) {
12220        // We try only with the AttachInfo because there's no point in invalidating
12221        // if we are not attached to our window
12222        final AttachInfo attachInfo = mAttachInfo;
12223        if (attachInfo != null) {
12224            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12225        }
12226    }
12227
12228    /**
12229     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12230     * through the event loop. Waits for the specified amount of time.</p>
12231     *
12232     * <p>This method can be invoked from outside of the UI thread
12233     * only when this View is attached to a window.</p>
12234     *
12235     * @param delayMilliseconds the duration in milliseconds to delay the
12236     *         invalidation by
12237     * @param left The left coordinate of the rectangle to invalidate.
12238     * @param top The top coordinate of the rectangle to invalidate.
12239     * @param right The right coordinate of the rectangle to invalidate.
12240     * @param bottom The bottom coordinate of the rectangle to invalidate.
12241     *
12242     * @see #invalidate(int, int, int, int)
12243     * @see #invalidate(Rect)
12244     * @see #postInvalidate(int, int, int, int)
12245     */
12246    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12247            int right, int bottom) {
12248
12249        // We try only with the AttachInfo because there's no point in invalidating
12250        // if we are not attached to our window
12251        final AttachInfo attachInfo = mAttachInfo;
12252        if (attachInfo != null) {
12253            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12254            info.target = this;
12255            info.left = left;
12256            info.top = top;
12257            info.right = right;
12258            info.bottom = bottom;
12259
12260            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12261        }
12262    }
12263
12264    /**
12265     * <p>Cause an invalidate to happen on the next animation time step, typically the
12266     * next display frame.</p>
12267     *
12268     * <p>This method can be invoked from outside of the UI thread
12269     * only when this View is attached to a window.</p>
12270     *
12271     * @see #invalidate()
12272     */
12273    public void postInvalidateOnAnimation() {
12274        // We try only with the AttachInfo because there's no point in invalidating
12275        // if we are not attached to our window
12276        final AttachInfo attachInfo = mAttachInfo;
12277        if (attachInfo != null) {
12278            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12279        }
12280    }
12281
12282    /**
12283     * <p>Cause an invalidate of the specified area to happen on the next animation
12284     * time step, typically the next display frame.</p>
12285     *
12286     * <p>This method can be invoked from outside of the UI thread
12287     * only when this View is attached to a window.</p>
12288     *
12289     * @param left The left coordinate of the rectangle to invalidate.
12290     * @param top The top coordinate of the rectangle to invalidate.
12291     * @param right The right coordinate of the rectangle to invalidate.
12292     * @param bottom The bottom coordinate of the rectangle to invalidate.
12293     *
12294     * @see #invalidate(int, int, int, int)
12295     * @see #invalidate(Rect)
12296     */
12297    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12298        // We try only with the AttachInfo because there's no point in invalidating
12299        // if we are not attached to our window
12300        final AttachInfo attachInfo = mAttachInfo;
12301        if (attachInfo != null) {
12302            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12303            info.target = this;
12304            info.left = left;
12305            info.top = top;
12306            info.right = right;
12307            info.bottom = bottom;
12308
12309            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12310        }
12311    }
12312
12313    /**
12314     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12315     * This event is sent at most once every
12316     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12317     */
12318    private void postSendViewScrolledAccessibilityEventCallback() {
12319        if (mSendViewScrolledAccessibilityEvent == null) {
12320            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12321        }
12322        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12323            mSendViewScrolledAccessibilityEvent.mIsPending = true;
12324            postDelayed(mSendViewScrolledAccessibilityEvent,
12325                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12326        }
12327    }
12328
12329    /**
12330     * Called by a parent to request that a child update its values for mScrollX
12331     * and mScrollY if necessary. This will typically be done if the child is
12332     * animating a scroll using a {@link android.widget.Scroller Scroller}
12333     * object.
12334     */
12335    public void computeScroll() {
12336    }
12337
12338    /**
12339     * <p>Indicate whether the horizontal edges are faded when the view is
12340     * scrolled horizontally.</p>
12341     *
12342     * @return true if the horizontal edges should are faded on scroll, false
12343     *         otherwise
12344     *
12345     * @see #setHorizontalFadingEdgeEnabled(boolean)
12346     *
12347     * @attr ref android.R.styleable#View_requiresFadingEdge
12348     */
12349    public boolean isHorizontalFadingEdgeEnabled() {
12350        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12351    }
12352
12353    /**
12354     * <p>Define whether the horizontal edges should be faded when this view
12355     * is scrolled horizontally.</p>
12356     *
12357     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12358     *                                    be faded when the view is scrolled
12359     *                                    horizontally
12360     *
12361     * @see #isHorizontalFadingEdgeEnabled()
12362     *
12363     * @attr ref android.R.styleable#View_requiresFadingEdge
12364     */
12365    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12366        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12367            if (horizontalFadingEdgeEnabled) {
12368                initScrollCache();
12369            }
12370
12371            mViewFlags ^= FADING_EDGE_HORIZONTAL;
12372        }
12373    }
12374
12375    /**
12376     * <p>Indicate whether the vertical edges are faded when the view is
12377     * scrolled horizontally.</p>
12378     *
12379     * @return true if the vertical edges should are faded on scroll, false
12380     *         otherwise
12381     *
12382     * @see #setVerticalFadingEdgeEnabled(boolean)
12383     *
12384     * @attr ref android.R.styleable#View_requiresFadingEdge
12385     */
12386    public boolean isVerticalFadingEdgeEnabled() {
12387        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12388    }
12389
12390    /**
12391     * <p>Define whether the vertical edges should be faded when this view
12392     * is scrolled vertically.</p>
12393     *
12394     * @param verticalFadingEdgeEnabled true if the vertical edges should
12395     *                                  be faded when the view is scrolled
12396     *                                  vertically
12397     *
12398     * @see #isVerticalFadingEdgeEnabled()
12399     *
12400     * @attr ref android.R.styleable#View_requiresFadingEdge
12401     */
12402    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12403        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12404            if (verticalFadingEdgeEnabled) {
12405                initScrollCache();
12406            }
12407
12408            mViewFlags ^= FADING_EDGE_VERTICAL;
12409        }
12410    }
12411
12412    /**
12413     * Returns the strength, or intensity, of the top faded edge. The strength is
12414     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12415     * returns 0.0 or 1.0 but no value in between.
12416     *
12417     * Subclasses should override this method to provide a smoother fade transition
12418     * when scrolling occurs.
12419     *
12420     * @return the intensity of the top fade as a float between 0.0f and 1.0f
12421     */
12422    protected float getTopFadingEdgeStrength() {
12423        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12424    }
12425
12426    /**
12427     * Returns the strength, or intensity, of the bottom faded edge. The strength is
12428     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12429     * returns 0.0 or 1.0 but no value in between.
12430     *
12431     * Subclasses should override this method to provide a smoother fade transition
12432     * when scrolling occurs.
12433     *
12434     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12435     */
12436    protected float getBottomFadingEdgeStrength() {
12437        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12438                computeVerticalScrollRange() ? 1.0f : 0.0f;
12439    }
12440
12441    /**
12442     * Returns the strength, or intensity, of the left faded edge. The strength is
12443     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12444     * returns 0.0 or 1.0 but no value in between.
12445     *
12446     * Subclasses should override this method to provide a smoother fade transition
12447     * when scrolling occurs.
12448     *
12449     * @return the intensity of the left fade as a float between 0.0f and 1.0f
12450     */
12451    protected float getLeftFadingEdgeStrength() {
12452        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12453    }
12454
12455    /**
12456     * Returns the strength, or intensity, of the right faded edge. The strength is
12457     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12458     * returns 0.0 or 1.0 but no value in between.
12459     *
12460     * Subclasses should override this method to provide a smoother fade transition
12461     * when scrolling occurs.
12462     *
12463     * @return the intensity of the right fade as a float between 0.0f and 1.0f
12464     */
12465    protected float getRightFadingEdgeStrength() {
12466        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12467                computeHorizontalScrollRange() ? 1.0f : 0.0f;
12468    }
12469
12470    /**
12471     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12472     * scrollbar is not drawn by default.</p>
12473     *
12474     * @return true if the horizontal scrollbar should be painted, false
12475     *         otherwise
12476     *
12477     * @see #setHorizontalScrollBarEnabled(boolean)
12478     */
12479    public boolean isHorizontalScrollBarEnabled() {
12480        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12481    }
12482
12483    /**
12484     * <p>Define whether the horizontal scrollbar should be drawn or not. The
12485     * scrollbar is not drawn by default.</p>
12486     *
12487     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12488     *                                   be painted
12489     *
12490     * @see #isHorizontalScrollBarEnabled()
12491     */
12492    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12493        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12494            mViewFlags ^= SCROLLBARS_HORIZONTAL;
12495            computeOpaqueFlags();
12496            resolvePadding();
12497        }
12498    }
12499
12500    /**
12501     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12502     * scrollbar is not drawn by default.</p>
12503     *
12504     * @return true if the vertical scrollbar should be painted, false
12505     *         otherwise
12506     *
12507     * @see #setVerticalScrollBarEnabled(boolean)
12508     */
12509    public boolean isVerticalScrollBarEnabled() {
12510        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12511    }
12512
12513    /**
12514     * <p>Define whether the vertical scrollbar should be drawn or not. The
12515     * scrollbar is not drawn by default.</p>
12516     *
12517     * @param verticalScrollBarEnabled true if the vertical scrollbar should
12518     *                                 be painted
12519     *
12520     * @see #isVerticalScrollBarEnabled()
12521     */
12522    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12523        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12524            mViewFlags ^= SCROLLBARS_VERTICAL;
12525            computeOpaqueFlags();
12526            resolvePadding();
12527        }
12528    }
12529
12530    /**
12531     * @hide
12532     */
12533    protected void recomputePadding() {
12534        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12535    }
12536
12537    /**
12538     * Define whether scrollbars will fade when the view is not scrolling.
12539     *
12540     * @param fadeScrollbars wheter to enable fading
12541     *
12542     * @attr ref android.R.styleable#View_fadeScrollbars
12543     */
12544    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12545        initScrollCache();
12546        final ScrollabilityCache scrollabilityCache = mScrollCache;
12547        scrollabilityCache.fadeScrollBars = fadeScrollbars;
12548        if (fadeScrollbars) {
12549            scrollabilityCache.state = ScrollabilityCache.OFF;
12550        } else {
12551            scrollabilityCache.state = ScrollabilityCache.ON;
12552        }
12553    }
12554
12555    /**
12556     *
12557     * Returns true if scrollbars will fade when this view is not scrolling
12558     *
12559     * @return true if scrollbar fading is enabled
12560     *
12561     * @attr ref android.R.styleable#View_fadeScrollbars
12562     */
12563    public boolean isScrollbarFadingEnabled() {
12564        return mScrollCache != null && mScrollCache.fadeScrollBars;
12565    }
12566
12567    /**
12568     *
12569     * Returns the delay before scrollbars fade.
12570     *
12571     * @return the delay before scrollbars fade
12572     *
12573     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12574     */
12575    public int getScrollBarDefaultDelayBeforeFade() {
12576        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12577                mScrollCache.scrollBarDefaultDelayBeforeFade;
12578    }
12579
12580    /**
12581     * Define the delay before scrollbars fade.
12582     *
12583     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12584     *
12585     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12586     */
12587    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12588        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12589    }
12590
12591    /**
12592     *
12593     * Returns the scrollbar fade duration.
12594     *
12595     * @return the scrollbar fade duration
12596     *
12597     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12598     */
12599    public int getScrollBarFadeDuration() {
12600        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12601                mScrollCache.scrollBarFadeDuration;
12602    }
12603
12604    /**
12605     * Define the scrollbar fade duration.
12606     *
12607     * @param scrollBarFadeDuration - the scrollbar fade duration
12608     *
12609     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12610     */
12611    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12612        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12613    }
12614
12615    /**
12616     *
12617     * Returns the scrollbar size.
12618     *
12619     * @return the scrollbar size
12620     *
12621     * @attr ref android.R.styleable#View_scrollbarSize
12622     */
12623    public int getScrollBarSize() {
12624        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12625                mScrollCache.scrollBarSize;
12626    }
12627
12628    /**
12629     * Define the scrollbar size.
12630     *
12631     * @param scrollBarSize - the scrollbar size
12632     *
12633     * @attr ref android.R.styleable#View_scrollbarSize
12634     */
12635    public void setScrollBarSize(int scrollBarSize) {
12636        getScrollCache().scrollBarSize = scrollBarSize;
12637    }
12638
12639    /**
12640     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12641     * inset. When inset, they add to the padding of the view. And the scrollbars
12642     * can be drawn inside the padding area or on the edge of the view. For example,
12643     * if a view has a background drawable and you want to draw the scrollbars
12644     * inside the padding specified by the drawable, you can use
12645     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12646     * appear at the edge of the view, ignoring the padding, then you can use
12647     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12648     * @param style the style of the scrollbars. Should be one of
12649     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12650     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12651     * @see #SCROLLBARS_INSIDE_OVERLAY
12652     * @see #SCROLLBARS_INSIDE_INSET
12653     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12654     * @see #SCROLLBARS_OUTSIDE_INSET
12655     *
12656     * @attr ref android.R.styleable#View_scrollbarStyle
12657     */
12658    public void setScrollBarStyle(@ScrollBarStyle int style) {
12659        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12660            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12661            computeOpaqueFlags();
12662            resolvePadding();
12663        }
12664    }
12665
12666    /**
12667     * <p>Returns the current scrollbar style.</p>
12668     * @return the current scrollbar style
12669     * @see #SCROLLBARS_INSIDE_OVERLAY
12670     * @see #SCROLLBARS_INSIDE_INSET
12671     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12672     * @see #SCROLLBARS_OUTSIDE_INSET
12673     *
12674     * @attr ref android.R.styleable#View_scrollbarStyle
12675     */
12676    @ViewDebug.ExportedProperty(mapping = {
12677            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12678            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12679            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12680            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12681    })
12682    @ScrollBarStyle
12683    public int getScrollBarStyle() {
12684        return mViewFlags & SCROLLBARS_STYLE_MASK;
12685    }
12686
12687    /**
12688     * <p>Compute the horizontal range that the horizontal scrollbar
12689     * represents.</p>
12690     *
12691     * <p>The range is expressed in arbitrary units that must be the same as the
12692     * units used by {@link #computeHorizontalScrollExtent()} and
12693     * {@link #computeHorizontalScrollOffset()}.</p>
12694     *
12695     * <p>The default range is the drawing width of this view.</p>
12696     *
12697     * @return the total horizontal range represented by the horizontal
12698     *         scrollbar
12699     *
12700     * @see #computeHorizontalScrollExtent()
12701     * @see #computeHorizontalScrollOffset()
12702     * @see android.widget.ScrollBarDrawable
12703     */
12704    protected int computeHorizontalScrollRange() {
12705        return getWidth();
12706    }
12707
12708    /**
12709     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12710     * within the horizontal range. This value is used to compute the position
12711     * of the thumb within the scrollbar's track.</p>
12712     *
12713     * <p>The range is expressed in arbitrary units that must be the same as the
12714     * units used by {@link #computeHorizontalScrollRange()} and
12715     * {@link #computeHorizontalScrollExtent()}.</p>
12716     *
12717     * <p>The default offset is the scroll offset of this view.</p>
12718     *
12719     * @return the horizontal offset of the scrollbar's thumb
12720     *
12721     * @see #computeHorizontalScrollRange()
12722     * @see #computeHorizontalScrollExtent()
12723     * @see android.widget.ScrollBarDrawable
12724     */
12725    protected int computeHorizontalScrollOffset() {
12726        return mScrollX;
12727    }
12728
12729    /**
12730     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
12731     * within the horizontal range. This value is used to compute the length
12732     * of the thumb within the scrollbar's track.</p>
12733     *
12734     * <p>The range is expressed in arbitrary units that must be the same as the
12735     * units used by {@link #computeHorizontalScrollRange()} and
12736     * {@link #computeHorizontalScrollOffset()}.</p>
12737     *
12738     * <p>The default extent is the drawing width of this view.</p>
12739     *
12740     * @return the horizontal extent of the scrollbar's thumb
12741     *
12742     * @see #computeHorizontalScrollRange()
12743     * @see #computeHorizontalScrollOffset()
12744     * @see android.widget.ScrollBarDrawable
12745     */
12746    protected int computeHorizontalScrollExtent() {
12747        return getWidth();
12748    }
12749
12750    /**
12751     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
12752     *
12753     * <p>The range is expressed in arbitrary units that must be the same as the
12754     * units used by {@link #computeVerticalScrollExtent()} and
12755     * {@link #computeVerticalScrollOffset()}.</p>
12756     *
12757     * @return the total vertical range represented by the vertical scrollbar
12758     *
12759     * <p>The default range is the drawing height of this view.</p>
12760     *
12761     * @see #computeVerticalScrollExtent()
12762     * @see #computeVerticalScrollOffset()
12763     * @see android.widget.ScrollBarDrawable
12764     */
12765    protected int computeVerticalScrollRange() {
12766        return getHeight();
12767    }
12768
12769    /**
12770     * <p>Compute the vertical offset of the vertical scrollbar's thumb
12771     * within the horizontal range. This value is used to compute the position
12772     * of the thumb within the scrollbar's track.</p>
12773     *
12774     * <p>The range is expressed in arbitrary units that must be the same as the
12775     * units used by {@link #computeVerticalScrollRange()} and
12776     * {@link #computeVerticalScrollExtent()}.</p>
12777     *
12778     * <p>The default offset is the scroll offset of this view.</p>
12779     *
12780     * @return the vertical offset of the scrollbar's thumb
12781     *
12782     * @see #computeVerticalScrollRange()
12783     * @see #computeVerticalScrollExtent()
12784     * @see android.widget.ScrollBarDrawable
12785     */
12786    protected int computeVerticalScrollOffset() {
12787        return mScrollY;
12788    }
12789
12790    /**
12791     * <p>Compute the vertical extent of the vertical scrollbar's thumb
12792     * within the vertical range. This value is used to compute the length
12793     * of the thumb within the scrollbar's track.</p>
12794     *
12795     * <p>The range is expressed in arbitrary units that must be the same as the
12796     * units used by {@link #computeVerticalScrollRange()} and
12797     * {@link #computeVerticalScrollOffset()}.</p>
12798     *
12799     * <p>The default extent is the drawing height of this view.</p>
12800     *
12801     * @return the vertical extent of the scrollbar's thumb
12802     *
12803     * @see #computeVerticalScrollRange()
12804     * @see #computeVerticalScrollOffset()
12805     * @see android.widget.ScrollBarDrawable
12806     */
12807    protected int computeVerticalScrollExtent() {
12808        return getHeight();
12809    }
12810
12811    /**
12812     * Check if this view can be scrolled horizontally in a certain direction.
12813     *
12814     * @param direction Negative to check scrolling left, positive to check scrolling right.
12815     * @return true if this view can be scrolled in the specified direction, false otherwise.
12816     */
12817    public boolean canScrollHorizontally(int direction) {
12818        final int offset = computeHorizontalScrollOffset();
12819        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
12820        if (range == 0) return false;
12821        if (direction < 0) {
12822            return offset > 0;
12823        } else {
12824            return offset < range - 1;
12825        }
12826    }
12827
12828    /**
12829     * Check if this view can be scrolled vertically in a certain direction.
12830     *
12831     * @param direction Negative to check scrolling up, positive to check scrolling down.
12832     * @return true if this view can be scrolled in the specified direction, false otherwise.
12833     */
12834    public boolean canScrollVertically(int direction) {
12835        final int offset = computeVerticalScrollOffset();
12836        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
12837        if (range == 0) return false;
12838        if (direction < 0) {
12839            return offset > 0;
12840        } else {
12841            return offset < range - 1;
12842        }
12843    }
12844
12845    /**
12846     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
12847     * scrollbars are painted only if they have been awakened first.</p>
12848     *
12849     * @param canvas the canvas on which to draw the scrollbars
12850     *
12851     * @see #awakenScrollBars(int)
12852     */
12853    protected final void onDrawScrollBars(Canvas canvas) {
12854        // scrollbars are drawn only when the animation is running
12855        final ScrollabilityCache cache = mScrollCache;
12856        if (cache != null) {
12857
12858            int state = cache.state;
12859
12860            if (state == ScrollabilityCache.OFF) {
12861                return;
12862            }
12863
12864            boolean invalidate = false;
12865
12866            if (state == ScrollabilityCache.FADING) {
12867                // We're fading -- get our fade interpolation
12868                if (cache.interpolatorValues == null) {
12869                    cache.interpolatorValues = new float[1];
12870                }
12871
12872                float[] values = cache.interpolatorValues;
12873
12874                // Stops the animation if we're done
12875                if (cache.scrollBarInterpolator.timeToValues(values) ==
12876                        Interpolator.Result.FREEZE_END) {
12877                    cache.state = ScrollabilityCache.OFF;
12878                } else {
12879                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
12880                }
12881
12882                // This will make the scroll bars inval themselves after
12883                // drawing. We only want this when we're fading so that
12884                // we prevent excessive redraws
12885                invalidate = true;
12886            } else {
12887                // We're just on -- but we may have been fading before so
12888                // reset alpha
12889                cache.scrollBar.mutate().setAlpha(255);
12890            }
12891
12892
12893            final int viewFlags = mViewFlags;
12894
12895            final boolean drawHorizontalScrollBar =
12896                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12897            final boolean drawVerticalScrollBar =
12898                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
12899                && !isVerticalScrollBarHidden();
12900
12901            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
12902                final int width = mRight - mLeft;
12903                final int height = mBottom - mTop;
12904
12905                final ScrollBarDrawable scrollBar = cache.scrollBar;
12906
12907                final int scrollX = mScrollX;
12908                final int scrollY = mScrollY;
12909                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
12910
12911                int left;
12912                int top;
12913                int right;
12914                int bottom;
12915
12916                if (drawHorizontalScrollBar) {
12917                    int size = scrollBar.getSize(false);
12918                    if (size <= 0) {
12919                        size = cache.scrollBarSize;
12920                    }
12921
12922                    scrollBar.setParameters(computeHorizontalScrollRange(),
12923                                            computeHorizontalScrollOffset(),
12924                                            computeHorizontalScrollExtent(), false);
12925                    final int verticalScrollBarGap = drawVerticalScrollBar ?
12926                            getVerticalScrollbarWidth() : 0;
12927                    top = scrollY + height - size - (mUserPaddingBottom & inside);
12928                    left = scrollX + (mPaddingLeft & inside);
12929                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
12930                    bottom = top + size;
12931                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
12932                    if (invalidate) {
12933                        invalidate(left, top, right, bottom);
12934                    }
12935                }
12936
12937                if (drawVerticalScrollBar) {
12938                    int size = scrollBar.getSize(true);
12939                    if (size <= 0) {
12940                        size = cache.scrollBarSize;
12941                    }
12942
12943                    scrollBar.setParameters(computeVerticalScrollRange(),
12944                                            computeVerticalScrollOffset(),
12945                                            computeVerticalScrollExtent(), true);
12946                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
12947                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
12948                        verticalScrollbarPosition = isLayoutRtl() ?
12949                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
12950                    }
12951                    switch (verticalScrollbarPosition) {
12952                        default:
12953                        case SCROLLBAR_POSITION_RIGHT:
12954                            left = scrollX + width - size - (mUserPaddingRight & inside);
12955                            break;
12956                        case SCROLLBAR_POSITION_LEFT:
12957                            left = scrollX + (mUserPaddingLeft & inside);
12958                            break;
12959                    }
12960                    top = scrollY + (mPaddingTop & inside);
12961                    right = left + size;
12962                    bottom = scrollY + height - (mUserPaddingBottom & inside);
12963                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
12964                    if (invalidate) {
12965                        invalidate(left, top, right, bottom);
12966                    }
12967                }
12968            }
12969        }
12970    }
12971
12972    /**
12973     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
12974     * FastScroller is visible.
12975     * @return whether to temporarily hide the vertical scrollbar
12976     * @hide
12977     */
12978    protected boolean isVerticalScrollBarHidden() {
12979        return false;
12980    }
12981
12982    /**
12983     * <p>Draw the horizontal scrollbar if
12984     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
12985     *
12986     * @param canvas the canvas on which to draw the scrollbar
12987     * @param scrollBar the scrollbar's drawable
12988     *
12989     * @see #isHorizontalScrollBarEnabled()
12990     * @see #computeHorizontalScrollRange()
12991     * @see #computeHorizontalScrollExtent()
12992     * @see #computeHorizontalScrollOffset()
12993     * @see android.widget.ScrollBarDrawable
12994     * @hide
12995     */
12996    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
12997            int l, int t, int r, int b) {
12998        scrollBar.setBounds(l, t, r, b);
12999        scrollBar.draw(canvas);
13000    }
13001
13002    /**
13003     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13004     * returns true.</p>
13005     *
13006     * @param canvas the canvas on which to draw the scrollbar
13007     * @param scrollBar the scrollbar's drawable
13008     *
13009     * @see #isVerticalScrollBarEnabled()
13010     * @see #computeVerticalScrollRange()
13011     * @see #computeVerticalScrollExtent()
13012     * @see #computeVerticalScrollOffset()
13013     * @see android.widget.ScrollBarDrawable
13014     * @hide
13015     */
13016    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13017            int l, int t, int r, int b) {
13018        scrollBar.setBounds(l, t, r, b);
13019        scrollBar.draw(canvas);
13020    }
13021
13022    /**
13023     * Implement this to do your drawing.
13024     *
13025     * @param canvas the canvas on which the background will be drawn
13026     */
13027    protected void onDraw(Canvas canvas) {
13028    }
13029
13030    /*
13031     * Caller is responsible for calling requestLayout if necessary.
13032     * (This allows addViewInLayout to not request a new layout.)
13033     */
13034    void assignParent(ViewParent parent) {
13035        if (mParent == null) {
13036            mParent = parent;
13037        } else if (parent == null) {
13038            mParent = null;
13039        } else {
13040            throw new RuntimeException("view " + this + " being added, but"
13041                    + " it already has a parent");
13042        }
13043    }
13044
13045    /**
13046     * This is called when the view is attached to a window.  At this point it
13047     * has a Surface and will start drawing.  Note that this function is
13048     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13049     * however it may be called any time before the first onDraw -- including
13050     * before or after {@link #onMeasure(int, int)}.
13051     *
13052     * @see #onDetachedFromWindow()
13053     */
13054    protected void onAttachedToWindow() {
13055        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13056            mParent.requestTransparentRegion(this);
13057        }
13058
13059        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
13060            initialAwakenScrollBars();
13061            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
13062        }
13063
13064        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13065
13066        jumpDrawablesToCurrentState();
13067
13068        resetSubtreeAccessibilityStateChanged();
13069
13070        // rebuild, since Outline not maintained while View is detached
13071        rebuildOutline();
13072
13073        if (isFocused()) {
13074            InputMethodManager imm = InputMethodManager.peekInstance();
13075            imm.focusIn(this);
13076        }
13077    }
13078
13079    /**
13080     * Resolve all RTL related properties.
13081     *
13082     * @return true if resolution of RTL properties has been done
13083     *
13084     * @hide
13085     */
13086    public boolean resolveRtlPropertiesIfNeeded() {
13087        if (!needRtlPropertiesResolution()) return false;
13088
13089        // Order is important here: LayoutDirection MUST be resolved first
13090        if (!isLayoutDirectionResolved()) {
13091            resolveLayoutDirection();
13092            resolveLayoutParams();
13093        }
13094        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
13095        if (!isTextDirectionResolved()) {
13096            resolveTextDirection();
13097        }
13098        if (!isTextAlignmentResolved()) {
13099            resolveTextAlignment();
13100        }
13101        // Should resolve Drawables before Padding because we need the layout direction of the
13102        // Drawable to correctly resolve Padding.
13103        if (!areDrawablesResolved()) {
13104            resolveDrawables();
13105        }
13106        if (!isPaddingResolved()) {
13107            resolvePadding();
13108        }
13109        onRtlPropertiesChanged(getLayoutDirection());
13110        return true;
13111    }
13112
13113    /**
13114     * Reset resolution of all RTL related properties.
13115     *
13116     * @hide
13117     */
13118    public void resetRtlProperties() {
13119        resetResolvedLayoutDirection();
13120        resetResolvedTextDirection();
13121        resetResolvedTextAlignment();
13122        resetResolvedPadding();
13123        resetResolvedDrawables();
13124    }
13125
13126    /**
13127     * @see #onScreenStateChanged(int)
13128     */
13129    void dispatchScreenStateChanged(int screenState) {
13130        onScreenStateChanged(screenState);
13131    }
13132
13133    /**
13134     * This method is called whenever the state of the screen this view is
13135     * attached to changes. A state change will usually occurs when the screen
13136     * turns on or off (whether it happens automatically or the user does it
13137     * manually.)
13138     *
13139     * @param screenState The new state of the screen. Can be either
13140     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13141     */
13142    public void onScreenStateChanged(int screenState) {
13143    }
13144
13145    /**
13146     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13147     */
13148    private boolean hasRtlSupport() {
13149        return mContext.getApplicationInfo().hasRtlSupport();
13150    }
13151
13152    /**
13153     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13154     * RTL not supported)
13155     */
13156    private boolean isRtlCompatibilityMode() {
13157        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13158        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13159    }
13160
13161    /**
13162     * @return true if RTL properties need resolution.
13163     *
13164     */
13165    private boolean needRtlPropertiesResolution() {
13166        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13167    }
13168
13169    /**
13170     * Called when any RTL property (layout direction or text direction or text alignment) has
13171     * been changed.
13172     *
13173     * Subclasses need to override this method to take care of cached information that depends on the
13174     * resolved layout direction, or to inform child views that inherit their layout direction.
13175     *
13176     * The default implementation does nothing.
13177     *
13178     * @param layoutDirection the direction of the layout
13179     *
13180     * @see #LAYOUT_DIRECTION_LTR
13181     * @see #LAYOUT_DIRECTION_RTL
13182     */
13183    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13184    }
13185
13186    /**
13187     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13188     * that the parent directionality can and will be resolved before its children.
13189     *
13190     * @return true if resolution has been done, false otherwise.
13191     *
13192     * @hide
13193     */
13194    public boolean resolveLayoutDirection() {
13195        // Clear any previous layout direction resolution
13196        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13197
13198        if (hasRtlSupport()) {
13199            // Set resolved depending on layout direction
13200            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13201                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13202                case LAYOUT_DIRECTION_INHERIT:
13203                    // We cannot resolve yet. LTR is by default and let the resolution happen again
13204                    // later to get the correct resolved value
13205                    if (!canResolveLayoutDirection()) return false;
13206
13207                    // Parent has not yet resolved, LTR is still the default
13208                    try {
13209                        if (!mParent.isLayoutDirectionResolved()) return false;
13210
13211                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13212                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13213                        }
13214                    } catch (AbstractMethodError e) {
13215                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13216                                " does not fully implement ViewParent", e);
13217                    }
13218                    break;
13219                case LAYOUT_DIRECTION_RTL:
13220                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13221                    break;
13222                case LAYOUT_DIRECTION_LOCALE:
13223                    if((LAYOUT_DIRECTION_RTL ==
13224                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13225                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13226                    }
13227                    break;
13228                default:
13229                    // Nothing to do, LTR by default
13230            }
13231        }
13232
13233        // Set to resolved
13234        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13235        return true;
13236    }
13237
13238    /**
13239     * Check if layout direction resolution can be done.
13240     *
13241     * @return true if layout direction resolution can be done otherwise return false.
13242     */
13243    public boolean canResolveLayoutDirection() {
13244        switch (getRawLayoutDirection()) {
13245            case LAYOUT_DIRECTION_INHERIT:
13246                if (mParent != null) {
13247                    try {
13248                        return mParent.canResolveLayoutDirection();
13249                    } catch (AbstractMethodError e) {
13250                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13251                                " does not fully implement ViewParent", e);
13252                    }
13253                }
13254                return false;
13255
13256            default:
13257                return true;
13258        }
13259    }
13260
13261    /**
13262     * Reset the resolved layout direction. Layout direction will be resolved during a call to
13263     * {@link #onMeasure(int, int)}.
13264     *
13265     * @hide
13266     */
13267    public void resetResolvedLayoutDirection() {
13268        // Reset the current resolved bits
13269        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13270    }
13271
13272    /**
13273     * @return true if the layout direction is inherited.
13274     *
13275     * @hide
13276     */
13277    public boolean isLayoutDirectionInherited() {
13278        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13279    }
13280
13281    /**
13282     * @return true if layout direction has been resolved.
13283     */
13284    public boolean isLayoutDirectionResolved() {
13285        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13286    }
13287
13288    /**
13289     * Return if padding has been resolved
13290     *
13291     * @hide
13292     */
13293    boolean isPaddingResolved() {
13294        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13295    }
13296
13297    /**
13298     * Resolves padding depending on layout direction, if applicable, and
13299     * recomputes internal padding values to adjust for scroll bars.
13300     *
13301     * @hide
13302     */
13303    public void resolvePadding() {
13304        final int resolvedLayoutDirection = getLayoutDirection();
13305
13306        if (!isRtlCompatibilityMode()) {
13307            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13308            // If start / end padding are defined, they will be resolved (hence overriding) to
13309            // left / right or right / left depending on the resolved layout direction.
13310            // If start / end padding are not defined, use the left / right ones.
13311            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13312                Rect padding = sThreadLocal.get();
13313                if (padding == null) {
13314                    padding = new Rect();
13315                    sThreadLocal.set(padding);
13316                }
13317                mBackground.getPadding(padding);
13318                if (!mLeftPaddingDefined) {
13319                    mUserPaddingLeftInitial = padding.left;
13320                }
13321                if (!mRightPaddingDefined) {
13322                    mUserPaddingRightInitial = padding.right;
13323                }
13324            }
13325            switch (resolvedLayoutDirection) {
13326                case LAYOUT_DIRECTION_RTL:
13327                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13328                        mUserPaddingRight = mUserPaddingStart;
13329                    } else {
13330                        mUserPaddingRight = mUserPaddingRightInitial;
13331                    }
13332                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13333                        mUserPaddingLeft = mUserPaddingEnd;
13334                    } else {
13335                        mUserPaddingLeft = mUserPaddingLeftInitial;
13336                    }
13337                    break;
13338                case LAYOUT_DIRECTION_LTR:
13339                default:
13340                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13341                        mUserPaddingLeft = mUserPaddingStart;
13342                    } else {
13343                        mUserPaddingLeft = mUserPaddingLeftInitial;
13344                    }
13345                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13346                        mUserPaddingRight = mUserPaddingEnd;
13347                    } else {
13348                        mUserPaddingRight = mUserPaddingRightInitial;
13349                    }
13350            }
13351
13352            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13353        }
13354
13355        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13356        onRtlPropertiesChanged(resolvedLayoutDirection);
13357
13358        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13359    }
13360
13361    /**
13362     * Reset the resolved layout direction.
13363     *
13364     * @hide
13365     */
13366    public void resetResolvedPadding() {
13367        resetResolvedPaddingInternal();
13368    }
13369
13370    /**
13371     * Used when we only want to reset *this* view's padding and not trigger overrides
13372     * in ViewGroup that reset children too.
13373     */
13374    void resetResolvedPaddingInternal() {
13375        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13376    }
13377
13378    /**
13379     * This is called when the view is detached from a window.  At this point it
13380     * no longer has a surface for drawing.
13381     *
13382     * @see #onAttachedToWindow()
13383     */
13384    protected void onDetachedFromWindow() {
13385    }
13386
13387    /**
13388     * This is a framework-internal mirror of onDetachedFromWindow() that's called
13389     * after onDetachedFromWindow().
13390     *
13391     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13392     * The super method should be called at the end of the overriden method to ensure
13393     * subclasses are destroyed first
13394     *
13395     * @hide
13396     */
13397    protected void onDetachedFromWindowInternal() {
13398        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13399        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13400
13401        removeUnsetPressCallback();
13402        removeLongPressCallback();
13403        removePerformClickCallback();
13404        removeSendViewScrolledAccessibilityEventCallback();
13405        stopNestedScroll();
13406
13407        // Anything that started animating right before detach should already
13408        // be in its final state when re-attached.
13409        jumpDrawablesToCurrentState();
13410
13411        destroyDrawingCache();
13412
13413        cleanupDraw();
13414        mCurrentAnimation = null;
13415    }
13416
13417    private void cleanupDraw() {
13418        resetDisplayList();
13419        if (mAttachInfo != null) {
13420            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13421        }
13422    }
13423
13424    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13425    }
13426
13427    /**
13428     * @return The number of times this view has been attached to a window
13429     */
13430    protected int getWindowAttachCount() {
13431        return mWindowAttachCount;
13432    }
13433
13434    /**
13435     * Retrieve a unique token identifying the window this view is attached to.
13436     * @return Return the window's token for use in
13437     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13438     */
13439    public IBinder getWindowToken() {
13440        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13441    }
13442
13443    /**
13444     * Retrieve the {@link WindowId} for the window this view is
13445     * currently attached to.
13446     */
13447    public WindowId getWindowId() {
13448        if (mAttachInfo == null) {
13449            return null;
13450        }
13451        if (mAttachInfo.mWindowId == null) {
13452            try {
13453                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13454                        mAttachInfo.mWindowToken);
13455                mAttachInfo.mWindowId = new WindowId(
13456                        mAttachInfo.mIWindowId);
13457            } catch (RemoteException e) {
13458            }
13459        }
13460        return mAttachInfo.mWindowId;
13461    }
13462
13463    /**
13464     * Retrieve a unique token identifying the top-level "real" window of
13465     * the window that this view is attached to.  That is, this is like
13466     * {@link #getWindowToken}, except if the window this view in is a panel
13467     * window (attached to another containing window), then the token of
13468     * the containing window is returned instead.
13469     *
13470     * @return Returns the associated window token, either
13471     * {@link #getWindowToken()} or the containing window's token.
13472     */
13473    public IBinder getApplicationWindowToken() {
13474        AttachInfo ai = mAttachInfo;
13475        if (ai != null) {
13476            IBinder appWindowToken = ai.mPanelParentWindowToken;
13477            if (appWindowToken == null) {
13478                appWindowToken = ai.mWindowToken;
13479            }
13480            return appWindowToken;
13481        }
13482        return null;
13483    }
13484
13485    /**
13486     * Gets the logical display to which the view's window has been attached.
13487     *
13488     * @return The logical display, or null if the view is not currently attached to a window.
13489     */
13490    public Display getDisplay() {
13491        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13492    }
13493
13494    /**
13495     * Retrieve private session object this view hierarchy is using to
13496     * communicate with the window manager.
13497     * @return the session object to communicate with the window manager
13498     */
13499    /*package*/ IWindowSession getWindowSession() {
13500        return mAttachInfo != null ? mAttachInfo.mSession : null;
13501    }
13502
13503    /**
13504     * @param info the {@link android.view.View.AttachInfo} to associated with
13505     *        this view
13506     */
13507    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13508        //System.out.println("Attached! " + this);
13509        mAttachInfo = info;
13510        if (mOverlay != null) {
13511            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13512        }
13513        mWindowAttachCount++;
13514        // We will need to evaluate the drawable state at least once.
13515        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13516        if (mFloatingTreeObserver != null) {
13517            info.mTreeObserver.merge(mFloatingTreeObserver);
13518            mFloatingTreeObserver = null;
13519        }
13520        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13521            mAttachInfo.mScrollContainers.add(this);
13522            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13523        }
13524        performCollectViewAttributes(mAttachInfo, visibility);
13525        onAttachedToWindow();
13526
13527        ListenerInfo li = mListenerInfo;
13528        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13529                li != null ? li.mOnAttachStateChangeListeners : null;
13530        if (listeners != null && listeners.size() > 0) {
13531            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13532            // perform the dispatching. The iterator is a safe guard against listeners that
13533            // could mutate the list by calling the various add/remove methods. This prevents
13534            // the array from being modified while we iterate it.
13535            for (OnAttachStateChangeListener listener : listeners) {
13536                listener.onViewAttachedToWindow(this);
13537            }
13538        }
13539
13540        int vis = info.mWindowVisibility;
13541        if (vis != GONE) {
13542            onWindowVisibilityChanged(vis);
13543        }
13544        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13545            // If nobody has evaluated the drawable state yet, then do it now.
13546            refreshDrawableState();
13547        }
13548        needGlobalAttributesUpdate(false);
13549    }
13550
13551    void dispatchDetachedFromWindow() {
13552        AttachInfo info = mAttachInfo;
13553        if (info != null) {
13554            int vis = info.mWindowVisibility;
13555            if (vis != GONE) {
13556                onWindowVisibilityChanged(GONE);
13557            }
13558        }
13559
13560        onDetachedFromWindow();
13561        onDetachedFromWindowInternal();
13562
13563        ListenerInfo li = mListenerInfo;
13564        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13565                li != null ? li.mOnAttachStateChangeListeners : null;
13566        if (listeners != null && listeners.size() > 0) {
13567            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13568            // perform the dispatching. The iterator is a safe guard against listeners that
13569            // could mutate the list by calling the various add/remove methods. This prevents
13570            // the array from being modified while we iterate it.
13571            for (OnAttachStateChangeListener listener : listeners) {
13572                listener.onViewDetachedFromWindow(this);
13573            }
13574        }
13575
13576        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13577            mAttachInfo.mScrollContainers.remove(this);
13578            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13579        }
13580
13581        mAttachInfo = null;
13582        if (mOverlay != null) {
13583            mOverlay.getOverlayView().dispatchDetachedFromWindow();
13584        }
13585    }
13586
13587    /**
13588     * Cancel any deferred high-level input events that were previously posted to the event queue.
13589     *
13590     * <p>Many views post high-level events such as click handlers to the event queue
13591     * to run deferred in order to preserve a desired user experience - clearing visible
13592     * pressed states before executing, etc. This method will abort any events of this nature
13593     * that are currently in flight.</p>
13594     *
13595     * <p>Custom views that generate their own high-level deferred input events should override
13596     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13597     *
13598     * <p>This will also cancel pending input events for any child views.</p>
13599     *
13600     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13601     * This will not impact newer events posted after this call that may occur as a result of
13602     * lower-level input events still waiting in the queue. If you are trying to prevent
13603     * double-submitted  events for the duration of some sort of asynchronous transaction
13604     * you should also take other steps to protect against unexpected double inputs e.g. calling
13605     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13606     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13607     */
13608    public final void cancelPendingInputEvents() {
13609        dispatchCancelPendingInputEvents();
13610    }
13611
13612    /**
13613     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13614     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13615     */
13616    void dispatchCancelPendingInputEvents() {
13617        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13618        onCancelPendingInputEvents();
13619        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13620            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13621                    " did not call through to super.onCancelPendingInputEvents()");
13622        }
13623    }
13624
13625    /**
13626     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13627     * a parent view.
13628     *
13629     * <p>This method is responsible for removing any pending high-level input events that were
13630     * posted to the event queue to run later. Custom view classes that post their own deferred
13631     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13632     * {@link android.os.Handler} should override this method, call
13633     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13634     * </p>
13635     */
13636    public void onCancelPendingInputEvents() {
13637        removePerformClickCallback();
13638        cancelLongPress();
13639        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13640    }
13641
13642    /**
13643     * Store this view hierarchy's frozen state into the given container.
13644     *
13645     * @param container The SparseArray in which to save the view's state.
13646     *
13647     * @see #restoreHierarchyState(android.util.SparseArray)
13648     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13649     * @see #onSaveInstanceState()
13650     */
13651    public void saveHierarchyState(SparseArray<Parcelable> container) {
13652        dispatchSaveInstanceState(container);
13653    }
13654
13655    /**
13656     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13657     * this view and its children. May be overridden to modify how freezing happens to a
13658     * view's children; for example, some views may want to not store state for their children.
13659     *
13660     * @param container The SparseArray in which to save the view's state.
13661     *
13662     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13663     * @see #saveHierarchyState(android.util.SparseArray)
13664     * @see #onSaveInstanceState()
13665     */
13666    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13667        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13668            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13669            Parcelable state = onSaveInstanceState();
13670            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13671                throw new IllegalStateException(
13672                        "Derived class did not call super.onSaveInstanceState()");
13673            }
13674            if (state != null) {
13675                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13676                // + ": " + state);
13677                container.put(mID, state);
13678            }
13679        }
13680    }
13681
13682    /**
13683     * Hook allowing a view to generate a representation of its internal state
13684     * that can later be used to create a new instance with that same state.
13685     * This state should only contain information that is not persistent or can
13686     * not be reconstructed later. For example, you will never store your
13687     * current position on screen because that will be computed again when a
13688     * new instance of the view is placed in its view hierarchy.
13689     * <p>
13690     * Some examples of things you may store here: the current cursor position
13691     * in a text view (but usually not the text itself since that is stored in a
13692     * content provider or other persistent storage), the currently selected
13693     * item in a list view.
13694     *
13695     * @return Returns a Parcelable object containing the view's current dynamic
13696     *         state, or null if there is nothing interesting to save. The
13697     *         default implementation returns null.
13698     * @see #onRestoreInstanceState(android.os.Parcelable)
13699     * @see #saveHierarchyState(android.util.SparseArray)
13700     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13701     * @see #setSaveEnabled(boolean)
13702     */
13703    protected Parcelable onSaveInstanceState() {
13704        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13705        return BaseSavedState.EMPTY_STATE;
13706    }
13707
13708    /**
13709     * Restore this view hierarchy's frozen state from the given container.
13710     *
13711     * @param container The SparseArray which holds previously frozen states.
13712     *
13713     * @see #saveHierarchyState(android.util.SparseArray)
13714     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13715     * @see #onRestoreInstanceState(android.os.Parcelable)
13716     */
13717    public void restoreHierarchyState(SparseArray<Parcelable> container) {
13718        dispatchRestoreInstanceState(container);
13719    }
13720
13721    /**
13722     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
13723     * state for this view and its children. May be overridden to modify how restoring
13724     * happens to a view's children; for example, some views may want to not store state
13725     * for their children.
13726     *
13727     * @param container The SparseArray which holds previously saved state.
13728     *
13729     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13730     * @see #restoreHierarchyState(android.util.SparseArray)
13731     * @see #onRestoreInstanceState(android.os.Parcelable)
13732     */
13733    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
13734        if (mID != NO_ID) {
13735            Parcelable state = container.get(mID);
13736            if (state != null) {
13737                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
13738                // + ": " + state);
13739                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13740                onRestoreInstanceState(state);
13741                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13742                    throw new IllegalStateException(
13743                            "Derived class did not call super.onRestoreInstanceState()");
13744                }
13745            }
13746        }
13747    }
13748
13749    /**
13750     * Hook allowing a view to re-apply a representation of its internal state that had previously
13751     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
13752     * null state.
13753     *
13754     * @param state The frozen state that had previously been returned by
13755     *        {@link #onSaveInstanceState}.
13756     *
13757     * @see #onSaveInstanceState()
13758     * @see #restoreHierarchyState(android.util.SparseArray)
13759     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13760     */
13761    protected void onRestoreInstanceState(Parcelable state) {
13762        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13763        if (state != BaseSavedState.EMPTY_STATE && state != null) {
13764            throw new IllegalArgumentException("Wrong state class, expecting View State but "
13765                    + "received " + state.getClass().toString() + " instead. This usually happens "
13766                    + "when two views of different type have the same id in the same hierarchy. "
13767                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
13768                    + "other views do not use the same id.");
13769        }
13770    }
13771
13772    /**
13773     * <p>Return the time at which the drawing of the view hierarchy started.</p>
13774     *
13775     * @return the drawing start time in milliseconds
13776     */
13777    public long getDrawingTime() {
13778        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
13779    }
13780
13781    /**
13782     * <p>Enables or disables the duplication of the parent's state into this view. When
13783     * duplication is enabled, this view gets its drawable state from its parent rather
13784     * than from its own internal properties.</p>
13785     *
13786     * <p>Note: in the current implementation, setting this property to true after the
13787     * view was added to a ViewGroup might have no effect at all. This property should
13788     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
13789     *
13790     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
13791     * property is enabled, an exception will be thrown.</p>
13792     *
13793     * <p>Note: if the child view uses and updates additionnal states which are unknown to the
13794     * parent, these states should not be affected by this method.</p>
13795     *
13796     * @param enabled True to enable duplication of the parent's drawable state, false
13797     *                to disable it.
13798     *
13799     * @see #getDrawableState()
13800     * @see #isDuplicateParentStateEnabled()
13801     */
13802    public void setDuplicateParentStateEnabled(boolean enabled) {
13803        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
13804    }
13805
13806    /**
13807     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
13808     *
13809     * @return True if this view's drawable state is duplicated from the parent,
13810     *         false otherwise
13811     *
13812     * @see #getDrawableState()
13813     * @see #setDuplicateParentStateEnabled(boolean)
13814     */
13815    public boolean isDuplicateParentStateEnabled() {
13816        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
13817    }
13818
13819    /**
13820     * <p>Specifies the type of layer backing this view. The layer can be
13821     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13822     * {@link #LAYER_TYPE_HARDWARE}.</p>
13823     *
13824     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13825     * instance that controls how the layer is composed on screen. The following
13826     * properties of the paint are taken into account when composing the layer:</p>
13827     * <ul>
13828     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13829     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13830     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13831     * </ul>
13832     *
13833     * <p>If this view has an alpha value set to < 1.0 by calling
13834     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superceded
13835     * by this view's alpha value.</p>
13836     *
13837     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
13838     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
13839     * for more information on when and how to use layers.</p>
13840     *
13841     * @param layerType The type of layer to use with this view, must be one of
13842     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13843     *        {@link #LAYER_TYPE_HARDWARE}
13844     * @param paint The paint used to compose the layer. This argument is optional
13845     *        and can be null. It is ignored when the layer type is
13846     *        {@link #LAYER_TYPE_NONE}
13847     *
13848     * @see #getLayerType()
13849     * @see #LAYER_TYPE_NONE
13850     * @see #LAYER_TYPE_SOFTWARE
13851     * @see #LAYER_TYPE_HARDWARE
13852     * @see #setAlpha(float)
13853     *
13854     * @attr ref android.R.styleable#View_layerType
13855     */
13856    public void setLayerType(int layerType, Paint paint) {
13857        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
13858            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
13859                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
13860        }
13861
13862        boolean typeChanged = mRenderNode.setLayerType(layerType);
13863
13864        if (!typeChanged) {
13865            setLayerPaint(paint);
13866            return;
13867        }
13868
13869        // Destroy any previous software drawing cache if needed
13870        if (mLayerType == LAYER_TYPE_SOFTWARE) {
13871            destroyDrawingCache();
13872        }
13873
13874        mLayerType = layerType;
13875        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
13876        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
13877        mRenderNode.setLayerPaint(mLayerPaint);
13878
13879        // draw() behaves differently if we are on a layer, so we need to
13880        // invalidate() here
13881        invalidateParentCaches();
13882        invalidate(true);
13883    }
13884
13885    /**
13886     * Updates the {@link Paint} object used with the current layer (used only if the current
13887     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
13888     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
13889     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
13890     * ensure that the view gets redrawn immediately.
13891     *
13892     * <p>A layer is associated with an optional {@link android.graphics.Paint}
13893     * instance that controls how the layer is composed on screen. The following
13894     * properties of the paint are taken into account when composing the layer:</p>
13895     * <ul>
13896     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
13897     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
13898     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
13899     * </ul>
13900     *
13901     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
13902     * alpha value of the layer's paint is superceded by this view's alpha value.</p>
13903     *
13904     * @param paint The paint used to compose the layer. This argument is optional
13905     *        and can be null. It is ignored when the layer type is
13906     *        {@link #LAYER_TYPE_NONE}
13907     *
13908     * @see #setLayerType(int, android.graphics.Paint)
13909     */
13910    public void setLayerPaint(Paint paint) {
13911        int layerType = getLayerType();
13912        if (layerType != LAYER_TYPE_NONE) {
13913            mLayerPaint = paint == null ? new Paint() : paint;
13914            if (layerType == LAYER_TYPE_HARDWARE) {
13915                if (mRenderNode.setLayerPaint(mLayerPaint)) {
13916                    invalidateViewProperty(false, false);
13917                }
13918            } else {
13919                invalidate();
13920            }
13921        }
13922    }
13923
13924    /**
13925     * Indicates whether this view has a static layer. A view with layer type
13926     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
13927     * dynamic.
13928     */
13929    boolean hasStaticLayer() {
13930        return true;
13931    }
13932
13933    /**
13934     * Indicates what type of layer is currently associated with this view. By default
13935     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
13936     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
13937     * for more information on the different types of layers.
13938     *
13939     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
13940     *         {@link #LAYER_TYPE_HARDWARE}
13941     *
13942     * @see #setLayerType(int, android.graphics.Paint)
13943     * @see #buildLayer()
13944     * @see #LAYER_TYPE_NONE
13945     * @see #LAYER_TYPE_SOFTWARE
13946     * @see #LAYER_TYPE_HARDWARE
13947     */
13948    public int getLayerType() {
13949        return mLayerType;
13950    }
13951
13952    /**
13953     * Forces this view's layer to be created and this view to be rendered
13954     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
13955     * invoking this method will have no effect.
13956     *
13957     * This method can for instance be used to render a view into its layer before
13958     * starting an animation. If this view is complex, rendering into the layer
13959     * before starting the animation will avoid skipping frames.
13960     *
13961     * @throws IllegalStateException If this view is not attached to a window
13962     *
13963     * @see #setLayerType(int, android.graphics.Paint)
13964     */
13965    public void buildLayer() {
13966        if (mLayerType == LAYER_TYPE_NONE) return;
13967
13968        final AttachInfo attachInfo = mAttachInfo;
13969        if (attachInfo == null) {
13970            throw new IllegalStateException("This view must be attached to a window first");
13971        }
13972
13973        if (getWidth() == 0 || getHeight() == 0) {
13974            return;
13975        }
13976
13977        switch (mLayerType) {
13978            case LAYER_TYPE_HARDWARE:
13979                updateDisplayListIfDirty();
13980                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
13981                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
13982                }
13983                break;
13984            case LAYER_TYPE_SOFTWARE:
13985                buildDrawingCache(true);
13986                break;
13987        }
13988    }
13989
13990    /**
13991     * If this View draws with a HardwareLayer, returns it.
13992     * Otherwise returns null
13993     *
13994     * TODO: Only TextureView uses this, can we eliminate it?
13995     */
13996    HardwareLayer getHardwareLayer() {
13997        return null;
13998    }
13999
14000    /**
14001     * Destroys all hardware rendering resources. This method is invoked
14002     * when the system needs to reclaim resources. Upon execution of this
14003     * method, you should free any OpenGL resources created by the view.
14004     *
14005     * Note: you <strong>must</strong> call
14006     * <code>super.destroyHardwareResources()</code> when overriding
14007     * this method.
14008     *
14009     * @hide
14010     */
14011    protected void destroyHardwareResources() {
14012        // Although the Layer will be destroyed by RenderNode, we want to release
14013        // the staging display list, which is also a signal to RenderNode that it's
14014        // safe to free its copy of the display list as it knows that we will
14015        // push an updated DisplayList if we try to draw again
14016        resetDisplayList();
14017    }
14018
14019    /**
14020     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14021     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14022     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14023     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14024     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14025     * null.</p>
14026     *
14027     * <p>Enabling the drawing cache is similar to
14028     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14029     * acceleration is turned off. When hardware acceleration is turned on, enabling the
14030     * drawing cache has no effect on rendering because the system uses a different mechanism
14031     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14032     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14033     * for information on how to enable software and hardware layers.</p>
14034     *
14035     * <p>This API can be used to manually generate
14036     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14037     * {@link #getDrawingCache()}.</p>
14038     *
14039     * @param enabled true to enable the drawing cache, false otherwise
14040     *
14041     * @see #isDrawingCacheEnabled()
14042     * @see #getDrawingCache()
14043     * @see #buildDrawingCache()
14044     * @see #setLayerType(int, android.graphics.Paint)
14045     */
14046    public void setDrawingCacheEnabled(boolean enabled) {
14047        mCachingFailed = false;
14048        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14049    }
14050
14051    /**
14052     * <p>Indicates whether the drawing cache is enabled for this view.</p>
14053     *
14054     * @return true if the drawing cache is enabled
14055     *
14056     * @see #setDrawingCacheEnabled(boolean)
14057     * @see #getDrawingCache()
14058     */
14059    @ViewDebug.ExportedProperty(category = "drawing")
14060    public boolean isDrawingCacheEnabled() {
14061        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
14062    }
14063
14064    /**
14065     * Debugging utility which recursively outputs the dirty state of a view and its
14066     * descendants.
14067     *
14068     * @hide
14069     */
14070    @SuppressWarnings({"UnusedDeclaration"})
14071    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
14072        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
14073                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
14074                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
14075                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
14076        if (clear) {
14077            mPrivateFlags &= clearMask;
14078        }
14079        if (this instanceof ViewGroup) {
14080            ViewGroup parent = (ViewGroup) this;
14081            final int count = parent.getChildCount();
14082            for (int i = 0; i < count; i++) {
14083                final View child = parent.getChildAt(i);
14084                child.outputDirtyFlags(indent + "  ", clear, clearMask);
14085            }
14086        }
14087    }
14088
14089    /**
14090     * This method is used by ViewGroup to cause its children to restore or recreate their
14091     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
14092     * to recreate its own display list, which would happen if it went through the normal
14093     * draw/dispatchDraw mechanisms.
14094     *
14095     * @hide
14096     */
14097    protected void dispatchGetDisplayList() {}
14098
14099    /**
14100     * A view that is not attached or hardware accelerated cannot create a display list.
14101     * This method checks these conditions and returns the appropriate result.
14102     *
14103     * @return true if view has the ability to create a display list, false otherwise.
14104     *
14105     * @hide
14106     */
14107    public boolean canHaveDisplayList() {
14108        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
14109    }
14110
14111    private void updateDisplayListIfDirty() {
14112        final RenderNode renderNode = mRenderNode;
14113        if (!canHaveDisplayList()) {
14114            // can't populate RenderNode, don't try
14115            return;
14116        }
14117
14118        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14119                || !renderNode.isValid()
14120                || (mRecreateDisplayList)) {
14121            // Don't need to recreate the display list, just need to tell our
14122            // children to restore/recreate theirs
14123            if (renderNode.isValid()
14124                    && !mRecreateDisplayList) {
14125                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14126                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14127                dispatchGetDisplayList();
14128
14129                return; // no work needed
14130            }
14131
14132            // If we got here, we're recreating it. Mark it as such to ensure that
14133            // we copy in child display lists into ours in drawChild()
14134            mRecreateDisplayList = true;
14135
14136            int width = mRight - mLeft;
14137            int height = mBottom - mTop;
14138            int layerType = getLayerType();
14139
14140            final HardwareCanvas canvas = renderNode.start(width, height);
14141            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14142
14143            try {
14144                final HardwareLayer layer = getHardwareLayer();
14145                if (layer != null && layer.isValid()) {
14146                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14147                } else if (layerType == LAYER_TYPE_SOFTWARE) {
14148                    buildDrawingCache(true);
14149                    Bitmap cache = getDrawingCache(true);
14150                    if (cache != null) {
14151                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14152                    }
14153                } else {
14154                    computeScroll();
14155
14156                    canvas.translate(-mScrollX, -mScrollY);
14157                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14158                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14159
14160                    // Fast path for layouts with no backgrounds
14161                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14162                        dispatchDraw(canvas);
14163                        if (mOverlay != null && !mOverlay.isEmpty()) {
14164                            mOverlay.getOverlayView().draw(canvas);
14165                        }
14166                    } else {
14167                        draw(canvas);
14168                    }
14169                }
14170            } finally {
14171                renderNode.end(canvas);
14172                setDisplayListProperties(renderNode);
14173            }
14174        } else {
14175            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14176            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14177        }
14178    }
14179
14180    /**
14181     * Returns a RenderNode with View draw content recorded, which can be
14182     * used to draw this view again without executing its draw method.
14183     *
14184     * @return A RenderNode ready to replay, or null if caching is not enabled.
14185     *
14186     * @hide
14187     */
14188    public RenderNode getDisplayList() {
14189        updateDisplayListIfDirty();
14190        return mRenderNode;
14191    }
14192
14193    private void resetDisplayList() {
14194        if (mRenderNode.isValid()) {
14195            mRenderNode.destroyDisplayListData();
14196        }
14197
14198        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14199            mBackgroundRenderNode.destroyDisplayListData();
14200        }
14201    }
14202
14203    /**
14204     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14205     *
14206     * @return A non-scaled bitmap representing this view or null if cache is disabled.
14207     *
14208     * @see #getDrawingCache(boolean)
14209     */
14210    public Bitmap getDrawingCache() {
14211        return getDrawingCache(false);
14212    }
14213
14214    /**
14215     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14216     * is null when caching is disabled. If caching is enabled and the cache is not ready,
14217     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14218     * draw from the cache when the cache is enabled. To benefit from the cache, you must
14219     * request the drawing cache by calling this method and draw it on screen if the
14220     * returned bitmap is not null.</p>
14221     *
14222     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14223     * this method will create a bitmap of the same size as this view. Because this bitmap
14224     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14225     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14226     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14227     * size than the view. This implies that your application must be able to handle this
14228     * size.</p>
14229     *
14230     * @param autoScale Indicates whether the generated bitmap should be scaled based on
14231     *        the current density of the screen when the application is in compatibility
14232     *        mode.
14233     *
14234     * @return A bitmap representing this view or null if cache is disabled.
14235     *
14236     * @see #setDrawingCacheEnabled(boolean)
14237     * @see #isDrawingCacheEnabled()
14238     * @see #buildDrawingCache(boolean)
14239     * @see #destroyDrawingCache()
14240     */
14241    public Bitmap getDrawingCache(boolean autoScale) {
14242        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14243            return null;
14244        }
14245        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14246            buildDrawingCache(autoScale);
14247        }
14248        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14249    }
14250
14251    /**
14252     * <p>Frees the resources used by the drawing cache. If you call
14253     * {@link #buildDrawingCache()} manually without calling
14254     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14255     * should cleanup the cache with this method afterwards.</p>
14256     *
14257     * @see #setDrawingCacheEnabled(boolean)
14258     * @see #buildDrawingCache()
14259     * @see #getDrawingCache()
14260     */
14261    public void destroyDrawingCache() {
14262        if (mDrawingCache != null) {
14263            mDrawingCache.recycle();
14264            mDrawingCache = null;
14265        }
14266        if (mUnscaledDrawingCache != null) {
14267            mUnscaledDrawingCache.recycle();
14268            mUnscaledDrawingCache = null;
14269        }
14270    }
14271
14272    /**
14273     * Setting a solid background color for the drawing cache's bitmaps will improve
14274     * performance and memory usage. Note, though that this should only be used if this
14275     * view will always be drawn on top of a solid color.
14276     *
14277     * @param color The background color to use for the drawing cache's bitmap
14278     *
14279     * @see #setDrawingCacheEnabled(boolean)
14280     * @see #buildDrawingCache()
14281     * @see #getDrawingCache()
14282     */
14283    public void setDrawingCacheBackgroundColor(int color) {
14284        if (color != mDrawingCacheBackgroundColor) {
14285            mDrawingCacheBackgroundColor = color;
14286            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14287        }
14288    }
14289
14290    /**
14291     * @see #setDrawingCacheBackgroundColor(int)
14292     *
14293     * @return The background color to used for the drawing cache's bitmap
14294     */
14295    public int getDrawingCacheBackgroundColor() {
14296        return mDrawingCacheBackgroundColor;
14297    }
14298
14299    /**
14300     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14301     *
14302     * @see #buildDrawingCache(boolean)
14303     */
14304    public void buildDrawingCache() {
14305        buildDrawingCache(false);
14306    }
14307
14308    /**
14309     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14310     *
14311     * <p>If you call {@link #buildDrawingCache()} manually without calling
14312     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14313     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14314     *
14315     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14316     * this method will create a bitmap of the same size as this view. Because this bitmap
14317     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14318     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14319     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14320     * size than the view. This implies that your application must be able to handle this
14321     * size.</p>
14322     *
14323     * <p>You should avoid calling this method when hardware acceleration is enabled. If
14324     * you do not need the drawing cache bitmap, calling this method will increase memory
14325     * usage and cause the view to be rendered in software once, thus negatively impacting
14326     * performance.</p>
14327     *
14328     * @see #getDrawingCache()
14329     * @see #destroyDrawingCache()
14330     */
14331    public void buildDrawingCache(boolean autoScale) {
14332        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14333                mDrawingCache == null : mUnscaledDrawingCache == null)) {
14334            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
14335                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
14336                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
14337            }
14338            try {
14339                buildDrawingCacheImpl(autoScale);
14340            } finally {
14341                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
14342            }
14343        }
14344    }
14345
14346    /**
14347     * private, internal implementation of buildDrawingCache, used to enable tracing
14348     */
14349    private void buildDrawingCacheImpl(boolean autoScale) {
14350        mCachingFailed = false;
14351
14352        int width = mRight - mLeft;
14353        int height = mBottom - mTop;
14354
14355        final AttachInfo attachInfo = mAttachInfo;
14356        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14357
14358        if (autoScale && scalingRequired) {
14359            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14360            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14361        }
14362
14363        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14364        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14365        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14366
14367        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14368        final long drawingCacheSize =
14369                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14370        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14371            if (width > 0 && height > 0) {
14372                Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14373                        + projectedBitmapSize + " bytes, only "
14374                        + drawingCacheSize + " available");
14375            }
14376            destroyDrawingCache();
14377            mCachingFailed = true;
14378            return;
14379        }
14380
14381        boolean clear = true;
14382        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14383
14384        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14385            Bitmap.Config quality;
14386            if (!opaque) {
14387                // Never pick ARGB_4444 because it looks awful
14388                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14389                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14390                    case DRAWING_CACHE_QUALITY_AUTO:
14391                    case DRAWING_CACHE_QUALITY_LOW:
14392                    case DRAWING_CACHE_QUALITY_HIGH:
14393                    default:
14394                        quality = Bitmap.Config.ARGB_8888;
14395                        break;
14396                }
14397            } else {
14398                // Optimization for translucent windows
14399                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14400                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14401            }
14402
14403            // Try to cleanup memory
14404            if (bitmap != null) bitmap.recycle();
14405
14406            try {
14407                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14408                        width, height, quality);
14409                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14410                if (autoScale) {
14411                    mDrawingCache = bitmap;
14412                } else {
14413                    mUnscaledDrawingCache = bitmap;
14414                }
14415                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14416            } catch (OutOfMemoryError e) {
14417                // If there is not enough memory to create the bitmap cache, just
14418                // ignore the issue as bitmap caches are not required to draw the
14419                // view hierarchy
14420                if (autoScale) {
14421                    mDrawingCache = null;
14422                } else {
14423                    mUnscaledDrawingCache = null;
14424                }
14425                mCachingFailed = true;
14426                return;
14427            }
14428
14429            clear = drawingCacheBackgroundColor != 0;
14430        }
14431
14432        Canvas canvas;
14433        if (attachInfo != null) {
14434            canvas = attachInfo.mCanvas;
14435            if (canvas == null) {
14436                canvas = new Canvas();
14437            }
14438            canvas.setBitmap(bitmap);
14439            // Temporarily clobber the cached Canvas in case one of our children
14440            // is also using a drawing cache. Without this, the children would
14441            // steal the canvas by attaching their own bitmap to it and bad, bad
14442            // thing would happen (invisible views, corrupted drawings, etc.)
14443            attachInfo.mCanvas = null;
14444        } else {
14445            // This case should hopefully never or seldom happen
14446            canvas = new Canvas(bitmap);
14447        }
14448
14449        if (clear) {
14450            bitmap.eraseColor(drawingCacheBackgroundColor);
14451        }
14452
14453        computeScroll();
14454        final int restoreCount = canvas.save();
14455
14456        if (autoScale && scalingRequired) {
14457            final float scale = attachInfo.mApplicationScale;
14458            canvas.scale(scale, scale);
14459        }
14460
14461        canvas.translate(-mScrollX, -mScrollY);
14462
14463        mPrivateFlags |= PFLAG_DRAWN;
14464        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14465                mLayerType != LAYER_TYPE_NONE) {
14466            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14467        }
14468
14469        // Fast path for layouts with no backgrounds
14470        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14471            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14472            dispatchDraw(canvas);
14473            if (mOverlay != null && !mOverlay.isEmpty()) {
14474                mOverlay.getOverlayView().draw(canvas);
14475            }
14476        } else {
14477            draw(canvas);
14478        }
14479
14480        canvas.restoreToCount(restoreCount);
14481        canvas.setBitmap(null);
14482
14483        if (attachInfo != null) {
14484            // Restore the cached Canvas for our siblings
14485            attachInfo.mCanvas = canvas;
14486        }
14487    }
14488
14489    /**
14490     * Create a snapshot of the view into a bitmap.  We should probably make
14491     * some form of this public, but should think about the API.
14492     */
14493    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14494        int width = mRight - mLeft;
14495        int height = mBottom - mTop;
14496
14497        final AttachInfo attachInfo = mAttachInfo;
14498        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14499        width = (int) ((width * scale) + 0.5f);
14500        height = (int) ((height * scale) + 0.5f);
14501
14502        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14503                width > 0 ? width : 1, height > 0 ? height : 1, quality);
14504        if (bitmap == null) {
14505            throw new OutOfMemoryError();
14506        }
14507
14508        Resources resources = getResources();
14509        if (resources != null) {
14510            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14511        }
14512
14513        Canvas canvas;
14514        if (attachInfo != null) {
14515            canvas = attachInfo.mCanvas;
14516            if (canvas == null) {
14517                canvas = new Canvas();
14518            }
14519            canvas.setBitmap(bitmap);
14520            // Temporarily clobber the cached Canvas in case one of our children
14521            // is also using a drawing cache. Without this, the children would
14522            // steal the canvas by attaching their own bitmap to it and bad, bad
14523            // things would happen (invisible views, corrupted drawings, etc.)
14524            attachInfo.mCanvas = null;
14525        } else {
14526            // This case should hopefully never or seldom happen
14527            canvas = new Canvas(bitmap);
14528        }
14529
14530        if ((backgroundColor & 0xff000000) != 0) {
14531            bitmap.eraseColor(backgroundColor);
14532        }
14533
14534        computeScroll();
14535        final int restoreCount = canvas.save();
14536        canvas.scale(scale, scale);
14537        canvas.translate(-mScrollX, -mScrollY);
14538
14539        // Temporarily remove the dirty mask
14540        int flags = mPrivateFlags;
14541        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14542
14543        // Fast path for layouts with no backgrounds
14544        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14545            dispatchDraw(canvas);
14546            if (mOverlay != null && !mOverlay.isEmpty()) {
14547                mOverlay.getOverlayView().draw(canvas);
14548            }
14549        } else {
14550            draw(canvas);
14551        }
14552
14553        mPrivateFlags = flags;
14554
14555        canvas.restoreToCount(restoreCount);
14556        canvas.setBitmap(null);
14557
14558        if (attachInfo != null) {
14559            // Restore the cached Canvas for our siblings
14560            attachInfo.mCanvas = canvas;
14561        }
14562
14563        return bitmap;
14564    }
14565
14566    /**
14567     * Indicates whether this View is currently in edit mode. A View is usually
14568     * in edit mode when displayed within a developer tool. For instance, if
14569     * this View is being drawn by a visual user interface builder, this method
14570     * should return true.
14571     *
14572     * Subclasses should check the return value of this method to provide
14573     * different behaviors if their normal behavior might interfere with the
14574     * host environment. For instance: the class spawns a thread in its
14575     * constructor, the drawing code relies on device-specific features, etc.
14576     *
14577     * This method is usually checked in the drawing code of custom widgets.
14578     *
14579     * @return True if this View is in edit mode, false otherwise.
14580     */
14581    public boolean isInEditMode() {
14582        return false;
14583    }
14584
14585    /**
14586     * If the View draws content inside its padding and enables fading edges,
14587     * it needs to support padding offsets. Padding offsets are added to the
14588     * fading edges to extend the length of the fade so that it covers pixels
14589     * drawn inside the padding.
14590     *
14591     * Subclasses of this class should override this method if they need
14592     * to draw content inside the padding.
14593     *
14594     * @return True if padding offset must be applied, false otherwise.
14595     *
14596     * @see #getLeftPaddingOffset()
14597     * @see #getRightPaddingOffset()
14598     * @see #getTopPaddingOffset()
14599     * @see #getBottomPaddingOffset()
14600     *
14601     * @since CURRENT
14602     */
14603    protected boolean isPaddingOffsetRequired() {
14604        return false;
14605    }
14606
14607    /**
14608     * Amount by which to extend the left fading region. Called only when
14609     * {@link #isPaddingOffsetRequired()} returns true.
14610     *
14611     * @return The left padding offset in pixels.
14612     *
14613     * @see #isPaddingOffsetRequired()
14614     *
14615     * @since CURRENT
14616     */
14617    protected int getLeftPaddingOffset() {
14618        return 0;
14619    }
14620
14621    /**
14622     * Amount by which to extend the right fading region. Called only when
14623     * {@link #isPaddingOffsetRequired()} returns true.
14624     *
14625     * @return The right padding offset in pixels.
14626     *
14627     * @see #isPaddingOffsetRequired()
14628     *
14629     * @since CURRENT
14630     */
14631    protected int getRightPaddingOffset() {
14632        return 0;
14633    }
14634
14635    /**
14636     * Amount by which to extend the top fading region. Called only when
14637     * {@link #isPaddingOffsetRequired()} returns true.
14638     *
14639     * @return The top padding offset in pixels.
14640     *
14641     * @see #isPaddingOffsetRequired()
14642     *
14643     * @since CURRENT
14644     */
14645    protected int getTopPaddingOffset() {
14646        return 0;
14647    }
14648
14649    /**
14650     * Amount by which to extend the bottom fading region. Called only when
14651     * {@link #isPaddingOffsetRequired()} returns true.
14652     *
14653     * @return The bottom padding offset in pixels.
14654     *
14655     * @see #isPaddingOffsetRequired()
14656     *
14657     * @since CURRENT
14658     */
14659    protected int getBottomPaddingOffset() {
14660        return 0;
14661    }
14662
14663    /**
14664     * @hide
14665     * @param offsetRequired
14666     */
14667    protected int getFadeTop(boolean offsetRequired) {
14668        int top = mPaddingTop;
14669        if (offsetRequired) top += getTopPaddingOffset();
14670        return top;
14671    }
14672
14673    /**
14674     * @hide
14675     * @param offsetRequired
14676     */
14677    protected int getFadeHeight(boolean offsetRequired) {
14678        int padding = mPaddingTop;
14679        if (offsetRequired) padding += getTopPaddingOffset();
14680        return mBottom - mTop - mPaddingBottom - padding;
14681    }
14682
14683    /**
14684     * <p>Indicates whether this view is attached to a hardware accelerated
14685     * window or not.</p>
14686     *
14687     * <p>Even if this method returns true, it does not mean that every call
14688     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14689     * accelerated {@link android.graphics.Canvas}. For instance, if this view
14690     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14691     * window is hardware accelerated,
14692     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14693     * return false, and this method will return true.</p>
14694     *
14695     * @return True if the view is attached to a window and the window is
14696     *         hardware accelerated; false in any other case.
14697     */
14698    @ViewDebug.ExportedProperty(category = "drawing")
14699    public boolean isHardwareAccelerated() {
14700        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14701    }
14702
14703    /**
14704     * Sets a rectangular area on this view to which the view will be clipped
14705     * when it is drawn. Setting the value to null will remove the clip bounds
14706     * and the view will draw normally, using its full bounds.
14707     *
14708     * @param clipBounds The rectangular area, in the local coordinates of
14709     * this view, to which future drawing operations will be clipped.
14710     */
14711    public void setClipBounds(Rect clipBounds) {
14712        if (clipBounds == mClipBounds
14713                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
14714            return;
14715        }
14716        if (clipBounds != null) {
14717            if (mClipBounds == null) {
14718                mClipBounds = new Rect(clipBounds);
14719            } else {
14720                mClipBounds.set(clipBounds);
14721            }
14722        } else {
14723            mClipBounds = null;
14724        }
14725        mRenderNode.setClipBounds(mClipBounds);
14726        invalidateViewProperty(false, false);
14727    }
14728
14729    /**
14730     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
14731     *
14732     * @return A copy of the current clip bounds if clip bounds are set,
14733     * otherwise null.
14734     */
14735    public Rect getClipBounds() {
14736        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
14737    }
14738
14739    /**
14740     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
14741     * case of an active Animation being run on the view.
14742     */
14743    private boolean drawAnimation(ViewGroup parent, long drawingTime,
14744            Animation a, boolean scalingRequired) {
14745        Transformation invalidationTransform;
14746        final int flags = parent.mGroupFlags;
14747        final boolean initialized = a.isInitialized();
14748        if (!initialized) {
14749            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
14750            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
14751            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
14752            onAnimationStart();
14753        }
14754
14755        final Transformation t = parent.getChildTransformation();
14756        boolean more = a.getTransformation(drawingTime, t, 1f);
14757        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
14758            if (parent.mInvalidationTransformation == null) {
14759                parent.mInvalidationTransformation = new Transformation();
14760            }
14761            invalidationTransform = parent.mInvalidationTransformation;
14762            a.getTransformation(drawingTime, invalidationTransform, 1f);
14763        } else {
14764            invalidationTransform = t;
14765        }
14766
14767        if (more) {
14768            if (!a.willChangeBounds()) {
14769                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
14770                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
14771                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
14772                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
14773                    // The child need to draw an animation, potentially offscreen, so
14774                    // make sure we do not cancel invalidate requests
14775                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14776                    parent.invalidate(mLeft, mTop, mRight, mBottom);
14777                }
14778            } else {
14779                if (parent.mInvalidateRegion == null) {
14780                    parent.mInvalidateRegion = new RectF();
14781                }
14782                final RectF region = parent.mInvalidateRegion;
14783                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
14784                        invalidationTransform);
14785
14786                // The child need to draw an animation, potentially offscreen, so
14787                // make sure we do not cancel invalidate requests
14788                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
14789
14790                final int left = mLeft + (int) region.left;
14791                final int top = mTop + (int) region.top;
14792                parent.invalidate(left, top, left + (int) (region.width() + .5f),
14793                        top + (int) (region.height() + .5f));
14794            }
14795        }
14796        return more;
14797    }
14798
14799    /**
14800     * This method is called by getDisplayList() when a display list is recorded for a View.
14801     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
14802     */
14803    void setDisplayListProperties(RenderNode renderNode) {
14804        if (renderNode != null) {
14805            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
14806            if (mParent instanceof ViewGroup) {
14807                renderNode.setClipToBounds(
14808                        (((ViewGroup) mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
14809            }
14810            float alpha = 1;
14811            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
14812                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14813                ViewGroup parentVG = (ViewGroup) mParent;
14814                final Transformation t = parentVG.getChildTransformation();
14815                if (parentVG.getChildStaticTransformation(this, t)) {
14816                    final int transformType = t.getTransformationType();
14817                    if (transformType != Transformation.TYPE_IDENTITY) {
14818                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
14819                            alpha = t.getAlpha();
14820                        }
14821                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
14822                            renderNode.setStaticMatrix(t.getMatrix());
14823                        }
14824                    }
14825                }
14826            }
14827            if (mTransformationInfo != null) {
14828                alpha *= getFinalAlpha();
14829                if (alpha < 1) {
14830                    final int multipliedAlpha = (int) (255 * alpha);
14831                    if (onSetAlpha(multipliedAlpha)) {
14832                        alpha = 1;
14833                    }
14834                }
14835                renderNode.setAlpha(alpha);
14836            } else if (alpha < 1) {
14837                renderNode.setAlpha(alpha);
14838            }
14839        }
14840    }
14841
14842    /**
14843     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
14844     * This draw() method is an implementation detail and is not intended to be overridden or
14845     * to be called from anywhere else other than ViewGroup.drawChild().
14846     */
14847    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
14848        boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14849        boolean more = false;
14850        final boolean childHasIdentityMatrix = hasIdentityMatrix();
14851        final int flags = parent.mGroupFlags;
14852
14853        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
14854            parent.getChildTransformation().clear();
14855            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
14856        }
14857
14858        Transformation transformToApply = null;
14859        boolean concatMatrix = false;
14860
14861        boolean scalingRequired = false;
14862        boolean caching;
14863        int layerType = getLayerType();
14864
14865        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
14866        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
14867                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
14868            caching = true;
14869            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
14870            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
14871        } else {
14872            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
14873        }
14874
14875        final Animation a = getAnimation();
14876        if (a != null) {
14877            more = drawAnimation(parent, drawingTime, a, scalingRequired);
14878            concatMatrix = a.willChangeTransformationMatrix();
14879            if (concatMatrix) {
14880                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14881            }
14882            transformToApply = parent.getChildTransformation();
14883        } else {
14884            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
14885                // No longer animating: clear out old animation matrix
14886                mRenderNode.setAnimationMatrix(null);
14887                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
14888            }
14889            if (!usingRenderNodeProperties &&
14890                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
14891                final Transformation t = parent.getChildTransformation();
14892                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
14893                if (hasTransform) {
14894                    final int transformType = t.getTransformationType();
14895                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
14896                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
14897                }
14898            }
14899        }
14900
14901        concatMatrix |= !childHasIdentityMatrix;
14902
14903        // Sets the flag as early as possible to allow draw() implementations
14904        // to call invalidate() successfully when doing animations
14905        mPrivateFlags |= PFLAG_DRAWN;
14906
14907        if (!concatMatrix &&
14908                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
14909                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
14910                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
14911                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
14912            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
14913            return more;
14914        }
14915        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
14916
14917        if (hardwareAccelerated) {
14918            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
14919            // retain the flag's value temporarily in the mRecreateDisplayList flag
14920            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
14921            mPrivateFlags &= ~PFLAG_INVALIDATED;
14922        }
14923
14924        RenderNode renderNode = null;
14925        Bitmap cache = null;
14926        boolean hasDisplayList = false;
14927        if (caching) {
14928            if (!hardwareAccelerated) {
14929                if (layerType != LAYER_TYPE_NONE) {
14930                    layerType = LAYER_TYPE_SOFTWARE;
14931                    buildDrawingCache(true);
14932                }
14933                cache = getDrawingCache(true);
14934            } else {
14935                switch (layerType) {
14936                    case LAYER_TYPE_SOFTWARE:
14937                        if (usingRenderNodeProperties) {
14938                            hasDisplayList = canHaveDisplayList();
14939                        } else {
14940                            buildDrawingCache(true);
14941                            cache = getDrawingCache(true);
14942                        }
14943                        break;
14944                    case LAYER_TYPE_HARDWARE:
14945                        if (usingRenderNodeProperties) {
14946                            hasDisplayList = canHaveDisplayList();
14947                        }
14948                        break;
14949                    case LAYER_TYPE_NONE:
14950                        // Delay getting the display list until animation-driven alpha values are
14951                        // set up and possibly passed on to the view
14952                        hasDisplayList = canHaveDisplayList();
14953                        break;
14954                }
14955            }
14956        }
14957        usingRenderNodeProperties &= hasDisplayList;
14958        if (usingRenderNodeProperties) {
14959            renderNode = getDisplayList();
14960            if (!renderNode.isValid()) {
14961                // Uncommon, but possible. If a view is removed from the hierarchy during the call
14962                // to getDisplayList(), the display list will be marked invalid and we should not
14963                // try to use it again.
14964                renderNode = null;
14965                hasDisplayList = false;
14966                usingRenderNodeProperties = false;
14967            }
14968        }
14969
14970        int sx = 0;
14971        int sy = 0;
14972        if (!hasDisplayList) {
14973            computeScroll();
14974            sx = mScrollX;
14975            sy = mScrollY;
14976        }
14977
14978        final boolean hasNoCache = cache == null || hasDisplayList;
14979        final boolean offsetForScroll = cache == null && !hasDisplayList &&
14980                layerType != LAYER_TYPE_HARDWARE;
14981
14982        int restoreTo = -1;
14983        if (!usingRenderNodeProperties || transformToApply != null) {
14984            restoreTo = canvas.save();
14985        }
14986        if (offsetForScroll) {
14987            canvas.translate(mLeft - sx, mTop - sy);
14988        } else {
14989            if (!usingRenderNodeProperties) {
14990                canvas.translate(mLeft, mTop);
14991            }
14992            if (scalingRequired) {
14993                if (usingRenderNodeProperties) {
14994                    // TODO: Might not need this if we put everything inside the DL
14995                    restoreTo = canvas.save();
14996                }
14997                // mAttachInfo cannot be null, otherwise scalingRequired == false
14998                final float scale = 1.0f / mAttachInfo.mApplicationScale;
14999                canvas.scale(scale, scale);
15000            }
15001        }
15002
15003        float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
15004        if (transformToApply != null || alpha < 1 ||  !hasIdentityMatrix() ||
15005                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15006            if (transformToApply != null || !childHasIdentityMatrix) {
15007                int transX = 0;
15008                int transY = 0;
15009
15010                if (offsetForScroll) {
15011                    transX = -sx;
15012                    transY = -sy;
15013                }
15014
15015                if (transformToApply != null) {
15016                    if (concatMatrix) {
15017                        if (usingRenderNodeProperties) {
15018                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
15019                        } else {
15020                            // Undo the scroll translation, apply the transformation matrix,
15021                            // then redo the scroll translate to get the correct result.
15022                            canvas.translate(-transX, -transY);
15023                            canvas.concat(transformToApply.getMatrix());
15024                            canvas.translate(transX, transY);
15025                        }
15026                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15027                    }
15028
15029                    float transformAlpha = transformToApply.getAlpha();
15030                    if (transformAlpha < 1) {
15031                        alpha *= transformAlpha;
15032                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15033                    }
15034                }
15035
15036                if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
15037                    canvas.translate(-transX, -transY);
15038                    canvas.concat(getMatrix());
15039                    canvas.translate(transX, transY);
15040                }
15041            }
15042
15043            // Deal with alpha if it is or used to be <1
15044            if (alpha < 1 ||
15045                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15046                if (alpha < 1) {
15047                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15048                } else {
15049                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15050                }
15051                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15052                if (hasNoCache) {
15053                    final int multipliedAlpha = (int) (255 * alpha);
15054                    if (!onSetAlpha(multipliedAlpha)) {
15055                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15056                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
15057                                layerType != LAYER_TYPE_NONE) {
15058                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
15059                        }
15060                        if (usingRenderNodeProperties) {
15061                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15062                        } else  if (layerType == LAYER_TYPE_NONE) {
15063                            final int scrollX = hasDisplayList ? 0 : sx;
15064                            final int scrollY = hasDisplayList ? 0 : sy;
15065                            canvas.saveLayerAlpha(scrollX, scrollY,
15066                                    scrollX + (mRight - mLeft), scrollY + (mBottom - mTop),
15067                                    multipliedAlpha, layerFlags);
15068                        }
15069                    } else {
15070                        // Alpha is handled by the child directly, clobber the layer's alpha
15071                        mPrivateFlags |= PFLAG_ALPHA_SET;
15072                    }
15073                }
15074            }
15075        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15076            onSetAlpha(255);
15077            mPrivateFlags &= ~PFLAG_ALPHA_SET;
15078        }
15079
15080        if (!usingRenderNodeProperties) {
15081            // apply clips directly, since RenderNode won't do it for this draw
15082            if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN
15083                    && cache == null) {
15084                if (offsetForScroll) {
15085                    canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
15086                } else {
15087                    if (!scalingRequired || cache == null) {
15088                        canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
15089                    } else {
15090                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
15091                    }
15092                }
15093            }
15094
15095            if (mClipBounds != null) {
15096                // clip bounds ignore scroll
15097                canvas.clipRect(mClipBounds);
15098            }
15099        }
15100
15101
15102
15103        if (!usingRenderNodeProperties && hasDisplayList) {
15104            renderNode = getDisplayList();
15105            if (!renderNode.isValid()) {
15106                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15107                // to getDisplayList(), the display list will be marked invalid and we should not
15108                // try to use it again.
15109                renderNode = null;
15110                hasDisplayList = false;
15111            }
15112        }
15113
15114        if (hasNoCache) {
15115            boolean layerRendered = false;
15116            if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
15117                final HardwareLayer layer = getHardwareLayer();
15118                if (layer != null && layer.isValid()) {
15119                    int restoreAlpha = mLayerPaint.getAlpha();
15120                    mLayerPaint.setAlpha((int) (alpha * 255));
15121                    ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
15122                    mLayerPaint.setAlpha(restoreAlpha);
15123                    layerRendered = true;
15124                } else {
15125                    final int scrollX = hasDisplayList ? 0 : sx;
15126                    final int scrollY = hasDisplayList ? 0 : sy;
15127                    canvas.saveLayer(scrollX, scrollY,
15128                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
15129                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
15130                }
15131            }
15132
15133            if (!layerRendered) {
15134                if (!hasDisplayList) {
15135                    // Fast path for layouts with no backgrounds
15136                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15137                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15138                        dispatchDraw(canvas);
15139                    } else {
15140                        draw(canvas);
15141                    }
15142                } else {
15143                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15144                    ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
15145                }
15146            }
15147        } else if (cache != null) {
15148            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15149            Paint cachePaint;
15150            int restoreAlpha = 0;
15151
15152            if (layerType == LAYER_TYPE_NONE) {
15153                cachePaint = parent.mCachePaint;
15154                if (cachePaint == null) {
15155                    cachePaint = new Paint();
15156                    cachePaint.setDither(false);
15157                    parent.mCachePaint = cachePaint;
15158                }
15159            } else {
15160                cachePaint = mLayerPaint;
15161                restoreAlpha = mLayerPaint.getAlpha();
15162            }
15163            cachePaint.setAlpha((int) (alpha * 255));
15164            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15165            cachePaint.setAlpha(restoreAlpha);
15166        }
15167
15168        if (restoreTo >= 0) {
15169            canvas.restoreToCount(restoreTo);
15170        }
15171
15172        if (a != null && !more) {
15173            if (!hardwareAccelerated && !a.getFillAfter()) {
15174                onSetAlpha(255);
15175            }
15176            parent.finishAnimatingView(this, a);
15177        }
15178
15179        if (more && hardwareAccelerated) {
15180            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15181                // alpha animations should cause the child to recreate its display list
15182                invalidate(true);
15183            }
15184        }
15185
15186        mRecreateDisplayList = false;
15187
15188        return more;
15189    }
15190
15191    /**
15192     * Manually render this view (and all of its children) to the given Canvas.
15193     * The view must have already done a full layout before this function is
15194     * called.  When implementing a view, implement
15195     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15196     * If you do need to override this method, call the superclass version.
15197     *
15198     * @param canvas The Canvas to which the View is rendered.
15199     */
15200    public void draw(Canvas canvas) {
15201        final int privateFlags = mPrivateFlags;
15202        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15203                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15204        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15205
15206        /*
15207         * Draw traversal performs several drawing steps which must be executed
15208         * in the appropriate order:
15209         *
15210         *      1. Draw the background
15211         *      2. If necessary, save the canvas' layers to prepare for fading
15212         *      3. Draw view's content
15213         *      4. Draw children
15214         *      5. If necessary, draw the fading edges and restore layers
15215         *      6. Draw decorations (scrollbars for instance)
15216         */
15217
15218        // Step 1, draw the background, if needed
15219        int saveCount;
15220
15221        if (!dirtyOpaque) {
15222            drawBackground(canvas);
15223        }
15224
15225        // skip step 2 & 5 if possible (common case)
15226        final int viewFlags = mViewFlags;
15227        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15228        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15229        if (!verticalEdges && !horizontalEdges) {
15230            // Step 3, draw the content
15231            if (!dirtyOpaque) onDraw(canvas);
15232
15233            // Step 4, draw the children
15234            dispatchDraw(canvas);
15235
15236            // Step 6, draw decorations (scrollbars)
15237            onDrawScrollBars(canvas);
15238
15239            if (mOverlay != null && !mOverlay.isEmpty()) {
15240                mOverlay.getOverlayView().dispatchDraw(canvas);
15241            }
15242
15243            // we're done...
15244            return;
15245        }
15246
15247        /*
15248         * Here we do the full fledged routine...
15249         * (this is an uncommon case where speed matters less,
15250         * this is why we repeat some of the tests that have been
15251         * done above)
15252         */
15253
15254        boolean drawTop = false;
15255        boolean drawBottom = false;
15256        boolean drawLeft = false;
15257        boolean drawRight = false;
15258
15259        float topFadeStrength = 0.0f;
15260        float bottomFadeStrength = 0.0f;
15261        float leftFadeStrength = 0.0f;
15262        float rightFadeStrength = 0.0f;
15263
15264        // Step 2, save the canvas' layers
15265        int paddingLeft = mPaddingLeft;
15266
15267        final boolean offsetRequired = isPaddingOffsetRequired();
15268        if (offsetRequired) {
15269            paddingLeft += getLeftPaddingOffset();
15270        }
15271
15272        int left = mScrollX + paddingLeft;
15273        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15274        int top = mScrollY + getFadeTop(offsetRequired);
15275        int bottom = top + getFadeHeight(offsetRequired);
15276
15277        if (offsetRequired) {
15278            right += getRightPaddingOffset();
15279            bottom += getBottomPaddingOffset();
15280        }
15281
15282        final ScrollabilityCache scrollabilityCache = mScrollCache;
15283        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15284        int length = (int) fadeHeight;
15285
15286        // clip the fade length if top and bottom fades overlap
15287        // overlapping fades produce odd-looking artifacts
15288        if (verticalEdges && (top + length > bottom - length)) {
15289            length = (bottom - top) / 2;
15290        }
15291
15292        // also clip horizontal fades if necessary
15293        if (horizontalEdges && (left + length > right - length)) {
15294            length = (right - left) / 2;
15295        }
15296
15297        if (verticalEdges) {
15298            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15299            drawTop = topFadeStrength * fadeHeight > 1.0f;
15300            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15301            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15302        }
15303
15304        if (horizontalEdges) {
15305            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15306            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15307            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15308            drawRight = rightFadeStrength * fadeHeight > 1.0f;
15309        }
15310
15311        saveCount = canvas.getSaveCount();
15312
15313        int solidColor = getSolidColor();
15314        if (solidColor == 0) {
15315            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15316
15317            if (drawTop) {
15318                canvas.saveLayer(left, top, right, top + length, null, flags);
15319            }
15320
15321            if (drawBottom) {
15322                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15323            }
15324
15325            if (drawLeft) {
15326                canvas.saveLayer(left, top, left + length, bottom, null, flags);
15327            }
15328
15329            if (drawRight) {
15330                canvas.saveLayer(right - length, top, right, bottom, null, flags);
15331            }
15332        } else {
15333            scrollabilityCache.setFadeColor(solidColor);
15334        }
15335
15336        // Step 3, draw the content
15337        if (!dirtyOpaque) onDraw(canvas);
15338
15339        // Step 4, draw the children
15340        dispatchDraw(canvas);
15341
15342        // Step 5, draw the fade effect and restore layers
15343        final Paint p = scrollabilityCache.paint;
15344        final Matrix matrix = scrollabilityCache.matrix;
15345        final Shader fade = scrollabilityCache.shader;
15346
15347        if (drawTop) {
15348            matrix.setScale(1, fadeHeight * topFadeStrength);
15349            matrix.postTranslate(left, top);
15350            fade.setLocalMatrix(matrix);
15351            p.setShader(fade);
15352            canvas.drawRect(left, top, right, top + length, p);
15353        }
15354
15355        if (drawBottom) {
15356            matrix.setScale(1, fadeHeight * bottomFadeStrength);
15357            matrix.postRotate(180);
15358            matrix.postTranslate(left, bottom);
15359            fade.setLocalMatrix(matrix);
15360            p.setShader(fade);
15361            canvas.drawRect(left, bottom - length, right, bottom, p);
15362        }
15363
15364        if (drawLeft) {
15365            matrix.setScale(1, fadeHeight * leftFadeStrength);
15366            matrix.postRotate(-90);
15367            matrix.postTranslate(left, top);
15368            fade.setLocalMatrix(matrix);
15369            p.setShader(fade);
15370            canvas.drawRect(left, top, left + length, bottom, p);
15371        }
15372
15373        if (drawRight) {
15374            matrix.setScale(1, fadeHeight * rightFadeStrength);
15375            matrix.postRotate(90);
15376            matrix.postTranslate(right, top);
15377            fade.setLocalMatrix(matrix);
15378            p.setShader(fade);
15379            canvas.drawRect(right - length, top, right, bottom, p);
15380        }
15381
15382        canvas.restoreToCount(saveCount);
15383
15384        // Step 6, draw decorations (scrollbars)
15385        onDrawScrollBars(canvas);
15386
15387        if (mOverlay != null && !mOverlay.isEmpty()) {
15388            mOverlay.getOverlayView().dispatchDraw(canvas);
15389        }
15390    }
15391
15392    /**
15393     * Draws the background onto the specified canvas.
15394     *
15395     * @param canvas Canvas on which to draw the background
15396     */
15397    private void drawBackground(Canvas canvas) {
15398        final Drawable background = mBackground;
15399        if (background == null) {
15400            return;
15401        }
15402
15403        if (mBackgroundSizeChanged) {
15404            background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
15405            mBackgroundSizeChanged = false;
15406            rebuildOutline();
15407        }
15408
15409        // Attempt to use a display list if requested.
15410        if (canvas.isHardwareAccelerated() && mAttachInfo != null
15411                && mAttachInfo.mHardwareRenderer != null) {
15412            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15413
15414            final RenderNode renderNode = mBackgroundRenderNode;
15415            if (renderNode != null && renderNode.isValid()) {
15416                setBackgroundRenderNodeProperties(renderNode);
15417                ((HardwareCanvas) canvas).drawRenderNode(renderNode);
15418                return;
15419            }
15420        }
15421
15422        final int scrollX = mScrollX;
15423        final int scrollY = mScrollY;
15424        if ((scrollX | scrollY) == 0) {
15425            background.draw(canvas);
15426        } else {
15427            canvas.translate(scrollX, scrollY);
15428            background.draw(canvas);
15429            canvas.translate(-scrollX, -scrollY);
15430        }
15431    }
15432
15433    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
15434        renderNode.setTranslationX(mScrollX);
15435        renderNode.setTranslationY(mScrollY);
15436    }
15437
15438    /**
15439     * Creates a new display list or updates the existing display list for the
15440     * specified Drawable.
15441     *
15442     * @param drawable Drawable for which to create a display list
15443     * @param renderNode Existing RenderNode, or {@code null}
15444     * @return A valid display list for the specified drawable
15445     */
15446    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15447        if (renderNode == null) {
15448            renderNode = RenderNode.create(drawable.getClass().getName(), this);
15449        }
15450
15451        final Rect bounds = drawable.getBounds();
15452        final int width = bounds.width();
15453        final int height = bounds.height();
15454        final HardwareCanvas canvas = renderNode.start(width, height);
15455
15456        // Reverse left/top translation done by drawable canvas, which will
15457        // instead be applied by rendernode's LTRB bounds below. This way, the
15458        // drawable's bounds match with its rendernode bounds and its content
15459        // will lie within those bounds in the rendernode tree.
15460        canvas.translate(-bounds.left, -bounds.top);
15461
15462        try {
15463            drawable.draw(canvas);
15464        } finally {
15465            renderNode.end(canvas);
15466        }
15467
15468        // Set up drawable properties that are view-independent.
15469        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15470        renderNode.setProjectBackwards(drawable.isProjected());
15471        renderNode.setProjectionReceiver(true);
15472        renderNode.setClipToBounds(false);
15473        return renderNode;
15474    }
15475
15476    /**
15477     * Returns the overlay for this view, creating it if it does not yet exist.
15478     * Adding drawables to the overlay will cause them to be displayed whenever
15479     * the view itself is redrawn. Objects in the overlay should be actively
15480     * managed: remove them when they should not be displayed anymore. The
15481     * overlay will always have the same size as its host view.
15482     *
15483     * <p>Note: Overlays do not currently work correctly with {@link
15484     * SurfaceView} or {@link TextureView}; contents in overlays for these
15485     * types of views may not display correctly.</p>
15486     *
15487     * @return The ViewOverlay object for this view.
15488     * @see ViewOverlay
15489     */
15490    public ViewOverlay getOverlay() {
15491        if (mOverlay == null) {
15492            mOverlay = new ViewOverlay(mContext, this);
15493        }
15494        return mOverlay;
15495    }
15496
15497    /**
15498     * Override this if your view is known to always be drawn on top of a solid color background,
15499     * and needs to draw fading edges. Returning a non-zero color enables the view system to
15500     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15501     * should be set to 0xFF.
15502     *
15503     * @see #setVerticalFadingEdgeEnabled(boolean)
15504     * @see #setHorizontalFadingEdgeEnabled(boolean)
15505     *
15506     * @return The known solid color background for this view, or 0 if the color may vary
15507     */
15508    @ViewDebug.ExportedProperty(category = "drawing")
15509    public int getSolidColor() {
15510        return 0;
15511    }
15512
15513    /**
15514     * Build a human readable string representation of the specified view flags.
15515     *
15516     * @param flags the view flags to convert to a string
15517     * @return a String representing the supplied flags
15518     */
15519    private static String printFlags(int flags) {
15520        String output = "";
15521        int numFlags = 0;
15522        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15523            output += "TAKES_FOCUS";
15524            numFlags++;
15525        }
15526
15527        switch (flags & VISIBILITY_MASK) {
15528        case INVISIBLE:
15529            if (numFlags > 0) {
15530                output += " ";
15531            }
15532            output += "INVISIBLE";
15533            // USELESS HERE numFlags++;
15534            break;
15535        case GONE:
15536            if (numFlags > 0) {
15537                output += " ";
15538            }
15539            output += "GONE";
15540            // USELESS HERE numFlags++;
15541            break;
15542        default:
15543            break;
15544        }
15545        return output;
15546    }
15547
15548    /**
15549     * Build a human readable string representation of the specified private
15550     * view flags.
15551     *
15552     * @param privateFlags the private view flags to convert to a string
15553     * @return a String representing the supplied flags
15554     */
15555    private static String printPrivateFlags(int privateFlags) {
15556        String output = "";
15557        int numFlags = 0;
15558
15559        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15560            output += "WANTS_FOCUS";
15561            numFlags++;
15562        }
15563
15564        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15565            if (numFlags > 0) {
15566                output += " ";
15567            }
15568            output += "FOCUSED";
15569            numFlags++;
15570        }
15571
15572        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15573            if (numFlags > 0) {
15574                output += " ";
15575            }
15576            output += "SELECTED";
15577            numFlags++;
15578        }
15579
15580        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15581            if (numFlags > 0) {
15582                output += " ";
15583            }
15584            output += "IS_ROOT_NAMESPACE";
15585            numFlags++;
15586        }
15587
15588        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15589            if (numFlags > 0) {
15590                output += " ";
15591            }
15592            output += "HAS_BOUNDS";
15593            numFlags++;
15594        }
15595
15596        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15597            if (numFlags > 0) {
15598                output += " ";
15599            }
15600            output += "DRAWN";
15601            // USELESS HERE numFlags++;
15602        }
15603        return output;
15604    }
15605
15606    /**
15607     * <p>Indicates whether or not this view's layout will be requested during
15608     * the next hierarchy layout pass.</p>
15609     *
15610     * @return true if the layout will be forced during next layout pass
15611     */
15612    public boolean isLayoutRequested() {
15613        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15614    }
15615
15616    /**
15617     * Return true if o is a ViewGroup that is laying out using optical bounds.
15618     * @hide
15619     */
15620    public static boolean isLayoutModeOptical(Object o) {
15621        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15622    }
15623
15624    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15625        Insets parentInsets = mParent instanceof View ?
15626                ((View) mParent).getOpticalInsets() : Insets.NONE;
15627        Insets childInsets = getOpticalInsets();
15628        return setFrame(
15629                left   + parentInsets.left - childInsets.left,
15630                top    + parentInsets.top  - childInsets.top,
15631                right  + parentInsets.left + childInsets.right,
15632                bottom + parentInsets.top  + childInsets.bottom);
15633    }
15634
15635    /**
15636     * Assign a size and position to a view and all of its
15637     * descendants
15638     *
15639     * <p>This is the second phase of the layout mechanism.
15640     * (The first is measuring). In this phase, each parent calls
15641     * layout on all of its children to position them.
15642     * This is typically done using the child measurements
15643     * that were stored in the measure pass().</p>
15644     *
15645     * <p>Derived classes should not override this method.
15646     * Derived classes with children should override
15647     * onLayout. In that method, they should
15648     * call layout on each of their children.</p>
15649     *
15650     * @param l Left position, relative to parent
15651     * @param t Top position, relative to parent
15652     * @param r Right position, relative to parent
15653     * @param b Bottom position, relative to parent
15654     */
15655    @SuppressWarnings({"unchecked"})
15656    public void layout(int l, int t, int r, int b) {
15657        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15658            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15659            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15660        }
15661
15662        int oldL = mLeft;
15663        int oldT = mTop;
15664        int oldB = mBottom;
15665        int oldR = mRight;
15666
15667        boolean changed = isLayoutModeOptical(mParent) ?
15668                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15669
15670        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15671            onLayout(changed, l, t, r, b);
15672            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15673
15674            ListenerInfo li = mListenerInfo;
15675            if (li != null && li.mOnLayoutChangeListeners != null) {
15676                ArrayList<OnLayoutChangeListener> listenersCopy =
15677                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15678                int numListeners = listenersCopy.size();
15679                for (int i = 0; i < numListeners; ++i) {
15680                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15681                }
15682            }
15683        }
15684
15685        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15686        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15687    }
15688
15689    /**
15690     * Called from layout when this view should
15691     * assign a size and position to each of its children.
15692     *
15693     * Derived classes with children should override
15694     * this method and call layout on each of
15695     * their children.
15696     * @param changed This is a new size or position for this view
15697     * @param left Left position, relative to parent
15698     * @param top Top position, relative to parent
15699     * @param right Right position, relative to parent
15700     * @param bottom Bottom position, relative to parent
15701     */
15702    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15703    }
15704
15705    /**
15706     * Assign a size and position to this view.
15707     *
15708     * This is called from layout.
15709     *
15710     * @param left Left position, relative to parent
15711     * @param top Top position, relative to parent
15712     * @param right Right position, relative to parent
15713     * @param bottom Bottom position, relative to parent
15714     * @return true if the new size and position are different than the
15715     *         previous ones
15716     * {@hide}
15717     */
15718    protected boolean setFrame(int left, int top, int right, int bottom) {
15719        boolean changed = false;
15720
15721        if (DBG) {
15722            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
15723                    + right + "," + bottom + ")");
15724        }
15725
15726        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
15727            changed = true;
15728
15729            // Remember our drawn bit
15730            int drawn = mPrivateFlags & PFLAG_DRAWN;
15731
15732            int oldWidth = mRight - mLeft;
15733            int oldHeight = mBottom - mTop;
15734            int newWidth = right - left;
15735            int newHeight = bottom - top;
15736            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
15737
15738            // Invalidate our old position
15739            invalidate(sizeChanged);
15740
15741            mLeft = left;
15742            mTop = top;
15743            mRight = right;
15744            mBottom = bottom;
15745            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
15746
15747            mPrivateFlags |= PFLAG_HAS_BOUNDS;
15748
15749
15750            if (sizeChanged) {
15751                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
15752            }
15753
15754            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
15755                // If we are visible, force the DRAWN bit to on so that
15756                // this invalidate will go through (at least to our parent).
15757                // This is because someone may have invalidated this view
15758                // before this call to setFrame came in, thereby clearing
15759                // the DRAWN bit.
15760                mPrivateFlags |= PFLAG_DRAWN;
15761                invalidate(sizeChanged);
15762                // parent display list may need to be recreated based on a change in the bounds
15763                // of any child
15764                invalidateParentCaches();
15765            }
15766
15767            // Reset drawn bit to original value (invalidate turns it off)
15768            mPrivateFlags |= drawn;
15769
15770            mBackgroundSizeChanged = true;
15771
15772            notifySubtreeAccessibilityStateChangedIfNeeded();
15773        }
15774        return changed;
15775    }
15776
15777    /**
15778     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
15779     * @hide
15780     */
15781    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
15782        setFrame(left, top, right, bottom);
15783    }
15784
15785    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
15786        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
15787        if (mOverlay != null) {
15788            mOverlay.getOverlayView().setRight(newWidth);
15789            mOverlay.getOverlayView().setBottom(newHeight);
15790        }
15791        rebuildOutline();
15792    }
15793
15794    /**
15795     * Finalize inflating a view from XML.  This is called as the last phase
15796     * of inflation, after all child views have been added.
15797     *
15798     * <p>Even if the subclass overrides onFinishInflate, they should always be
15799     * sure to call the super method, so that we get called.
15800     */
15801    protected void onFinishInflate() {
15802    }
15803
15804    /**
15805     * Returns the resources associated with this view.
15806     *
15807     * @return Resources object.
15808     */
15809    public Resources getResources() {
15810        return mResources;
15811    }
15812
15813    /**
15814     * Invalidates the specified Drawable.
15815     *
15816     * @param drawable the drawable to invalidate
15817     */
15818    @Override
15819    public void invalidateDrawable(@NonNull Drawable drawable) {
15820        if (verifyDrawable(drawable)) {
15821            final Rect dirty = drawable.getDirtyBounds();
15822            final int scrollX = mScrollX;
15823            final int scrollY = mScrollY;
15824
15825            invalidate(dirty.left + scrollX, dirty.top + scrollY,
15826                    dirty.right + scrollX, dirty.bottom + scrollY);
15827            rebuildOutline();
15828        }
15829    }
15830
15831    /**
15832     * Schedules an action on a drawable to occur at a specified time.
15833     *
15834     * @param who the recipient of the action
15835     * @param what the action to run on the drawable
15836     * @param when the time at which the action must occur. Uses the
15837     *        {@link SystemClock#uptimeMillis} timebase.
15838     */
15839    @Override
15840    public void scheduleDrawable(Drawable who, Runnable what, long when) {
15841        if (verifyDrawable(who) && what != null) {
15842            final long delay = when - SystemClock.uptimeMillis();
15843            if (mAttachInfo != null) {
15844                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
15845                        Choreographer.CALLBACK_ANIMATION, what, who,
15846                        Choreographer.subtractFrameDelay(delay));
15847            } else {
15848                ViewRootImpl.getRunQueue().postDelayed(what, delay);
15849            }
15850        }
15851    }
15852
15853    /**
15854     * Cancels a scheduled action on a drawable.
15855     *
15856     * @param who the recipient of the action
15857     * @param what the action to cancel
15858     */
15859    @Override
15860    public void unscheduleDrawable(Drawable who, Runnable what) {
15861        if (verifyDrawable(who) && what != null) {
15862            if (mAttachInfo != null) {
15863                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15864                        Choreographer.CALLBACK_ANIMATION, what, who);
15865            }
15866            ViewRootImpl.getRunQueue().removeCallbacks(what);
15867        }
15868    }
15869
15870    /**
15871     * Unschedule any events associated with the given Drawable.  This can be
15872     * used when selecting a new Drawable into a view, so that the previous
15873     * one is completely unscheduled.
15874     *
15875     * @param who The Drawable to unschedule.
15876     *
15877     * @see #drawableStateChanged
15878     */
15879    public void unscheduleDrawable(Drawable who) {
15880        if (mAttachInfo != null && who != null) {
15881            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
15882                    Choreographer.CALLBACK_ANIMATION, null, who);
15883        }
15884    }
15885
15886    /**
15887     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
15888     * that the View directionality can and will be resolved before its Drawables.
15889     *
15890     * Will call {@link View#onResolveDrawables} when resolution is done.
15891     *
15892     * @hide
15893     */
15894    protected void resolveDrawables() {
15895        // Drawables resolution may need to happen before resolving the layout direction (which is
15896        // done only during the measure() call).
15897        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
15898        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
15899        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
15900        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
15901        // direction to be resolved as its resolved value will be the same as its raw value.
15902        if (!isLayoutDirectionResolved() &&
15903                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
15904            return;
15905        }
15906
15907        final int layoutDirection = isLayoutDirectionResolved() ?
15908                getLayoutDirection() : getRawLayoutDirection();
15909
15910        if (mBackground != null) {
15911            mBackground.setLayoutDirection(layoutDirection);
15912        }
15913        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
15914        onResolveDrawables(layoutDirection);
15915    }
15916
15917    boolean areDrawablesResolved() {
15918        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
15919    }
15920
15921    /**
15922     * Called when layout direction has been resolved.
15923     *
15924     * The default implementation does nothing.
15925     *
15926     * @param layoutDirection The resolved layout direction.
15927     *
15928     * @see #LAYOUT_DIRECTION_LTR
15929     * @see #LAYOUT_DIRECTION_RTL
15930     *
15931     * @hide
15932     */
15933    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
15934    }
15935
15936    /**
15937     * @hide
15938     */
15939    protected void resetResolvedDrawables() {
15940        resetResolvedDrawablesInternal();
15941    }
15942
15943    void resetResolvedDrawablesInternal() {
15944        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
15945    }
15946
15947    /**
15948     * If your view subclass is displaying its own Drawable objects, it should
15949     * override this function and return true for any Drawable it is
15950     * displaying.  This allows animations for those drawables to be
15951     * scheduled.
15952     *
15953     * <p>Be sure to call through to the super class when overriding this
15954     * function.
15955     *
15956     * @param who The Drawable to verify.  Return true if it is one you are
15957     *            displaying, else return the result of calling through to the
15958     *            super class.
15959     *
15960     * @return boolean If true than the Drawable is being displayed in the
15961     *         view; else false and it is not allowed to animate.
15962     *
15963     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
15964     * @see #drawableStateChanged()
15965     */
15966    protected boolean verifyDrawable(Drawable who) {
15967        return who == mBackground;
15968    }
15969
15970    /**
15971     * This function is called whenever the state of the view changes in such
15972     * a way that it impacts the state of drawables being shown.
15973     * <p>
15974     * If the View has a StateListAnimator, it will also be called to run necessary state
15975     * change animations.
15976     * <p>
15977     * Be sure to call through to the superclass when overriding this function.
15978     *
15979     * @see Drawable#setState(int[])
15980     */
15981    protected void drawableStateChanged() {
15982        final Drawable d = mBackground;
15983        if (d != null && d.isStateful()) {
15984            d.setState(getDrawableState());
15985        }
15986
15987        if (mStateListAnimator != null) {
15988            mStateListAnimator.setState(getDrawableState());
15989        }
15990    }
15991
15992    /**
15993     * This function is called whenever the view hotspot changes and needs to
15994     * be propagated to drawables or child views managed by the view.
15995     * <p>
15996     * Dispatching to child views is handled by
15997     * {@link #dispatchDrawableHotspotChanged(float, float)}.
15998     * <p>
15999     * Be sure to call through to the superclass when overriding this function.
16000     *
16001     * @param x hotspot x coordinate
16002     * @param y hotspot y coordinate
16003     */
16004    public void drawableHotspotChanged(float x, float y) {
16005        if (mBackground != null) {
16006            mBackground.setHotspot(x, y);
16007        }
16008
16009        dispatchDrawableHotspotChanged(x, y);
16010    }
16011
16012    /**
16013     * Dispatches drawableHotspotChanged to all of this View's children.
16014     *
16015     * @param x hotspot x coordinate
16016     * @param y hotspot y coordinate
16017     * @see #drawableHotspotChanged(float, float)
16018     */
16019    public void dispatchDrawableHotspotChanged(float x, float y) {
16020    }
16021
16022    /**
16023     * Call this to force a view to update its drawable state. This will cause
16024     * drawableStateChanged to be called on this view. Views that are interested
16025     * in the new state should call getDrawableState.
16026     *
16027     * @see #drawableStateChanged
16028     * @see #getDrawableState
16029     */
16030    public void refreshDrawableState() {
16031        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16032        drawableStateChanged();
16033
16034        ViewParent parent = mParent;
16035        if (parent != null) {
16036            parent.childDrawableStateChanged(this);
16037        }
16038    }
16039
16040    /**
16041     * Return an array of resource IDs of the drawable states representing the
16042     * current state of the view.
16043     *
16044     * @return The current drawable state
16045     *
16046     * @see Drawable#setState(int[])
16047     * @see #drawableStateChanged()
16048     * @see #onCreateDrawableState(int)
16049     */
16050    public final int[] getDrawableState() {
16051        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16052            return mDrawableState;
16053        } else {
16054            mDrawableState = onCreateDrawableState(0);
16055            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16056            return mDrawableState;
16057        }
16058    }
16059
16060    /**
16061     * Generate the new {@link android.graphics.drawable.Drawable} state for
16062     * this view. This is called by the view
16063     * system when the cached Drawable state is determined to be invalid.  To
16064     * retrieve the current state, you should use {@link #getDrawableState}.
16065     *
16066     * @param extraSpace if non-zero, this is the number of extra entries you
16067     * would like in the returned array in which you can place your own
16068     * states.
16069     *
16070     * @return Returns an array holding the current {@link Drawable} state of
16071     * the view.
16072     *
16073     * @see #mergeDrawableStates(int[], int[])
16074     */
16075    protected int[] onCreateDrawableState(int extraSpace) {
16076        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
16077                mParent instanceof View) {
16078            return ((View) mParent).onCreateDrawableState(extraSpace);
16079        }
16080
16081        int[] drawableState;
16082
16083        int privateFlags = mPrivateFlags;
16084
16085        int viewStateIndex = 0;
16086        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
16087        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
16088        if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
16089        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
16090        if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
16091        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
16092        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16093                HardwareRenderer.isAvailable()) {
16094            // This is set if HW acceleration is requested, even if the current
16095            // process doesn't allow it.  This is just to allow app preview
16096            // windows to better match their app.
16097            viewStateIndex |= VIEW_STATE_ACCELERATED;
16098        }
16099        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
16100
16101        final int privateFlags2 = mPrivateFlags2;
16102        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
16103        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
16104
16105        drawableState = VIEW_STATE_SETS[viewStateIndex];
16106
16107        //noinspection ConstantIfStatement
16108        if (false) {
16109            Log.i("View", "drawableStateIndex=" + viewStateIndex);
16110            Log.i("View", toString()
16111                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16112                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16113                    + " fo=" + hasFocus()
16114                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16115                    + " wf=" + hasWindowFocus()
16116                    + ": " + Arrays.toString(drawableState));
16117        }
16118
16119        if (extraSpace == 0) {
16120            return drawableState;
16121        }
16122
16123        final int[] fullState;
16124        if (drawableState != null) {
16125            fullState = new int[drawableState.length + extraSpace];
16126            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16127        } else {
16128            fullState = new int[extraSpace];
16129        }
16130
16131        return fullState;
16132    }
16133
16134    /**
16135     * Merge your own state values in <var>additionalState</var> into the base
16136     * state values <var>baseState</var> that were returned by
16137     * {@link #onCreateDrawableState(int)}.
16138     *
16139     * @param baseState The base state values returned by
16140     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16141     * own additional state values.
16142     *
16143     * @param additionalState The additional state values you would like
16144     * added to <var>baseState</var>; this array is not modified.
16145     *
16146     * @return As a convenience, the <var>baseState</var> array you originally
16147     * passed into the function is returned.
16148     *
16149     * @see #onCreateDrawableState(int)
16150     */
16151    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16152        final int N = baseState.length;
16153        int i = N - 1;
16154        while (i >= 0 && baseState[i] == 0) {
16155            i--;
16156        }
16157        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16158        return baseState;
16159    }
16160
16161    /**
16162     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16163     * on all Drawable objects associated with this view.
16164     * <p>
16165     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16166     * attached to this view.
16167     */
16168    public void jumpDrawablesToCurrentState() {
16169        if (mBackground != null) {
16170            mBackground.jumpToCurrentState();
16171        }
16172        if (mStateListAnimator != null) {
16173            mStateListAnimator.jumpToCurrentState();
16174        }
16175    }
16176
16177    /**
16178     * Sets the background color for this view.
16179     * @param color the color of the background
16180     */
16181    @RemotableViewMethod
16182    public void setBackgroundColor(int color) {
16183        if (mBackground instanceof ColorDrawable) {
16184            ((ColorDrawable) mBackground.mutate()).setColor(color);
16185            computeOpaqueFlags();
16186            mBackgroundResource = 0;
16187        } else {
16188            setBackground(new ColorDrawable(color));
16189        }
16190    }
16191
16192    /**
16193     * Set the background to a given resource. The resource should refer to
16194     * a Drawable object or 0 to remove the background.
16195     * @param resid The identifier of the resource.
16196     *
16197     * @attr ref android.R.styleable#View_background
16198     */
16199    @RemotableViewMethod
16200    public void setBackgroundResource(int resid) {
16201        if (resid != 0 && resid == mBackgroundResource) {
16202            return;
16203        }
16204
16205        Drawable d = null;
16206        if (resid != 0) {
16207            d = mContext.getDrawable(resid);
16208        }
16209        setBackground(d);
16210
16211        mBackgroundResource = resid;
16212    }
16213
16214    /**
16215     * Set the background to a given Drawable, or remove the background. If the
16216     * background has padding, this View's padding is set to the background's
16217     * padding. However, when a background is removed, this View's padding isn't
16218     * touched. If setting the padding is desired, please use
16219     * {@link #setPadding(int, int, int, int)}.
16220     *
16221     * @param background The Drawable to use as the background, or null to remove the
16222     *        background
16223     */
16224    public void setBackground(Drawable background) {
16225        //noinspection deprecation
16226        setBackgroundDrawable(background);
16227    }
16228
16229    /**
16230     * @deprecated use {@link #setBackground(Drawable)} instead
16231     */
16232    @Deprecated
16233    public void setBackgroundDrawable(Drawable background) {
16234        computeOpaqueFlags();
16235
16236        if (background == mBackground) {
16237            return;
16238        }
16239
16240        boolean requestLayout = false;
16241
16242        mBackgroundResource = 0;
16243
16244        /*
16245         * Regardless of whether we're setting a new background or not, we want
16246         * to clear the previous drawable.
16247         */
16248        if (mBackground != null) {
16249            mBackground.setCallback(null);
16250            unscheduleDrawable(mBackground);
16251        }
16252
16253        if (background != null) {
16254            Rect padding = sThreadLocal.get();
16255            if (padding == null) {
16256                padding = new Rect();
16257                sThreadLocal.set(padding);
16258            }
16259            resetResolvedDrawablesInternal();
16260            background.setLayoutDirection(getLayoutDirection());
16261            if (background.getPadding(padding)) {
16262                resetResolvedPaddingInternal();
16263                switch (background.getLayoutDirection()) {
16264                    case LAYOUT_DIRECTION_RTL:
16265                        mUserPaddingLeftInitial = padding.right;
16266                        mUserPaddingRightInitial = padding.left;
16267                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16268                        break;
16269                    case LAYOUT_DIRECTION_LTR:
16270                    default:
16271                        mUserPaddingLeftInitial = padding.left;
16272                        mUserPaddingRightInitial = padding.right;
16273                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16274                }
16275                mLeftPaddingDefined = false;
16276                mRightPaddingDefined = false;
16277            }
16278
16279            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
16280            // if it has a different minimum size, we should layout again
16281            if (mBackground == null
16282                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
16283                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16284                requestLayout = true;
16285            }
16286
16287            background.setCallback(this);
16288            if (background.isStateful()) {
16289                background.setState(getDrawableState());
16290            }
16291            background.setVisible(getVisibility() == VISIBLE, false);
16292            mBackground = background;
16293
16294            applyBackgroundTint();
16295
16296            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16297                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16298                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16299                requestLayout = true;
16300            }
16301        } else {
16302            /* Remove the background */
16303            mBackground = null;
16304
16305            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16306                /*
16307                 * This view ONLY drew the background before and we're removing
16308                 * the background, so now it won't draw anything
16309                 * (hence we SKIP_DRAW)
16310                 */
16311                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16312                mPrivateFlags |= PFLAG_SKIP_DRAW;
16313            }
16314
16315            /*
16316             * When the background is set, we try to apply its padding to this
16317             * View. When the background is removed, we don't touch this View's
16318             * padding. This is noted in the Javadocs. Hence, we don't need to
16319             * requestLayout(), the invalidate() below is sufficient.
16320             */
16321
16322            // The old background's minimum size could have affected this
16323            // View's layout, so let's requestLayout
16324            requestLayout = true;
16325        }
16326
16327        computeOpaqueFlags();
16328
16329        if (requestLayout) {
16330            requestLayout();
16331        }
16332
16333        mBackgroundSizeChanged = true;
16334        invalidate(true);
16335    }
16336
16337    /**
16338     * Gets the background drawable
16339     *
16340     * @return The drawable used as the background for this view, if any.
16341     *
16342     * @see #setBackground(Drawable)
16343     *
16344     * @attr ref android.R.styleable#View_background
16345     */
16346    public Drawable getBackground() {
16347        return mBackground;
16348    }
16349
16350    /**
16351     * Applies a tint to the background drawable. Does not modify the current tint
16352     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16353     * <p>
16354     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16355     * mutate the drawable and apply the specified tint and tint mode using
16356     * {@link Drawable#setTintList(ColorStateList)}.
16357     *
16358     * @param tint the tint to apply, may be {@code null} to clear tint
16359     *
16360     * @attr ref android.R.styleable#View_backgroundTint
16361     * @see #getBackgroundTintList()
16362     * @see Drawable#setTintList(ColorStateList)
16363     */
16364    public void setBackgroundTintList(@Nullable ColorStateList tint) {
16365        if (mBackgroundTint == null) {
16366            mBackgroundTint = new TintInfo();
16367        }
16368        mBackgroundTint.mTintList = tint;
16369        mBackgroundTint.mHasTintList = true;
16370
16371        applyBackgroundTint();
16372    }
16373
16374    /**
16375     * Return the tint applied to the background drawable, if specified.
16376     *
16377     * @return the tint applied to the background drawable
16378     * @attr ref android.R.styleable#View_backgroundTint
16379     * @see #setBackgroundTintList(ColorStateList)
16380     */
16381    @Nullable
16382    public ColorStateList getBackgroundTintList() {
16383        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16384    }
16385
16386    /**
16387     * Specifies the blending mode used to apply the tint specified by
16388     * {@link #setBackgroundTintList(ColorStateList)}} to the background
16389     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16390     *
16391     * @param tintMode the blending mode used to apply the tint, may be
16392     *                 {@code null} to clear tint
16393     * @attr ref android.R.styleable#View_backgroundTintMode
16394     * @see #getBackgroundTintMode()
16395     * @see Drawable#setTintMode(PorterDuff.Mode)
16396     */
16397    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16398        if (mBackgroundTint == null) {
16399            mBackgroundTint = new TintInfo();
16400        }
16401        mBackgroundTint.mTintMode = tintMode;
16402        mBackgroundTint.mHasTintMode = true;
16403
16404        applyBackgroundTint();
16405    }
16406
16407    /**
16408     * Return the blending mode used to apply the tint to the background
16409     * drawable, if specified.
16410     *
16411     * @return the blending mode used to apply the tint to the background
16412     *         drawable
16413     * @attr ref android.R.styleable#View_backgroundTintMode
16414     * @see #setBackgroundTintMode(PorterDuff.Mode)
16415     */
16416    @Nullable
16417    public PorterDuff.Mode getBackgroundTintMode() {
16418        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16419    }
16420
16421    private void applyBackgroundTint() {
16422        if (mBackground != null && mBackgroundTint != null) {
16423            final TintInfo tintInfo = mBackgroundTint;
16424            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16425                mBackground = mBackground.mutate();
16426
16427                if (tintInfo.mHasTintList) {
16428                    mBackground.setTintList(tintInfo.mTintList);
16429                }
16430
16431                if (tintInfo.mHasTintMode) {
16432                    mBackground.setTintMode(tintInfo.mTintMode);
16433                }
16434
16435                // The drawable (or one of its children) may not have been
16436                // stateful before applying the tint, so let's try again.
16437                if (mBackground.isStateful()) {
16438                    mBackground.setState(getDrawableState());
16439                }
16440            }
16441        }
16442    }
16443
16444    /**
16445     * Sets the padding. The view may add on the space required to display
16446     * the scrollbars, depending on the style and visibility of the scrollbars.
16447     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
16448     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
16449     * from the values set in this call.
16450     *
16451     * @attr ref android.R.styleable#View_padding
16452     * @attr ref android.R.styleable#View_paddingBottom
16453     * @attr ref android.R.styleable#View_paddingLeft
16454     * @attr ref android.R.styleable#View_paddingRight
16455     * @attr ref android.R.styleable#View_paddingTop
16456     * @param left the left padding in pixels
16457     * @param top the top padding in pixels
16458     * @param right the right padding in pixels
16459     * @param bottom the bottom padding in pixels
16460     */
16461    public void setPadding(int left, int top, int right, int bottom) {
16462        resetResolvedPaddingInternal();
16463
16464        mUserPaddingStart = UNDEFINED_PADDING;
16465        mUserPaddingEnd = UNDEFINED_PADDING;
16466
16467        mUserPaddingLeftInitial = left;
16468        mUserPaddingRightInitial = right;
16469
16470        mLeftPaddingDefined = true;
16471        mRightPaddingDefined = true;
16472
16473        internalSetPadding(left, top, right, bottom);
16474    }
16475
16476    /**
16477     * @hide
16478     */
16479    protected void internalSetPadding(int left, int top, int right, int bottom) {
16480        mUserPaddingLeft = left;
16481        mUserPaddingRight = right;
16482        mUserPaddingBottom = bottom;
16483
16484        final int viewFlags = mViewFlags;
16485        boolean changed = false;
16486
16487        // Common case is there are no scroll bars.
16488        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
16489            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
16490                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
16491                        ? 0 : getVerticalScrollbarWidth();
16492                switch (mVerticalScrollbarPosition) {
16493                    case SCROLLBAR_POSITION_DEFAULT:
16494                        if (isLayoutRtl()) {
16495                            left += offset;
16496                        } else {
16497                            right += offset;
16498                        }
16499                        break;
16500                    case SCROLLBAR_POSITION_RIGHT:
16501                        right += offset;
16502                        break;
16503                    case SCROLLBAR_POSITION_LEFT:
16504                        left += offset;
16505                        break;
16506                }
16507            }
16508            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
16509                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
16510                        ? 0 : getHorizontalScrollbarHeight();
16511            }
16512        }
16513
16514        if (mPaddingLeft != left) {
16515            changed = true;
16516            mPaddingLeft = left;
16517        }
16518        if (mPaddingTop != top) {
16519            changed = true;
16520            mPaddingTop = top;
16521        }
16522        if (mPaddingRight != right) {
16523            changed = true;
16524            mPaddingRight = right;
16525        }
16526        if (mPaddingBottom != bottom) {
16527            changed = true;
16528            mPaddingBottom = bottom;
16529        }
16530
16531        if (changed) {
16532            requestLayout();
16533            invalidateOutline();
16534        }
16535    }
16536
16537    /**
16538     * Sets the relative padding. The view may add on the space required to display
16539     * the scrollbars, depending on the style and visibility of the scrollbars.
16540     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
16541     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
16542     * from the values set in this call.
16543     *
16544     * @attr ref android.R.styleable#View_padding
16545     * @attr ref android.R.styleable#View_paddingBottom
16546     * @attr ref android.R.styleable#View_paddingStart
16547     * @attr ref android.R.styleable#View_paddingEnd
16548     * @attr ref android.R.styleable#View_paddingTop
16549     * @param start the start padding in pixels
16550     * @param top the top padding in pixels
16551     * @param end the end padding in pixels
16552     * @param bottom the bottom padding in pixels
16553     */
16554    public void setPaddingRelative(int start, int top, int end, int bottom) {
16555        resetResolvedPaddingInternal();
16556
16557        mUserPaddingStart = start;
16558        mUserPaddingEnd = end;
16559        mLeftPaddingDefined = true;
16560        mRightPaddingDefined = true;
16561
16562        switch(getLayoutDirection()) {
16563            case LAYOUT_DIRECTION_RTL:
16564                mUserPaddingLeftInitial = end;
16565                mUserPaddingRightInitial = start;
16566                internalSetPadding(end, top, start, bottom);
16567                break;
16568            case LAYOUT_DIRECTION_LTR:
16569            default:
16570                mUserPaddingLeftInitial = start;
16571                mUserPaddingRightInitial = end;
16572                internalSetPadding(start, top, end, bottom);
16573        }
16574    }
16575
16576    /**
16577     * Returns the top padding of this view.
16578     *
16579     * @return the top padding in pixels
16580     */
16581    public int getPaddingTop() {
16582        return mPaddingTop;
16583    }
16584
16585    /**
16586     * Returns the bottom padding of this view. If there are inset and enabled
16587     * scrollbars, this value may include the space required to display the
16588     * scrollbars as well.
16589     *
16590     * @return the bottom padding in pixels
16591     */
16592    public int getPaddingBottom() {
16593        return mPaddingBottom;
16594    }
16595
16596    /**
16597     * Returns the left padding of this view. If there are inset and enabled
16598     * scrollbars, this value may include the space required to display the
16599     * scrollbars as well.
16600     *
16601     * @return the left padding in pixels
16602     */
16603    public int getPaddingLeft() {
16604        if (!isPaddingResolved()) {
16605            resolvePadding();
16606        }
16607        return mPaddingLeft;
16608    }
16609
16610    /**
16611     * Returns the start padding of this view depending on its resolved layout direction.
16612     * If there are inset and enabled scrollbars, this value may include the space
16613     * required to display the scrollbars as well.
16614     *
16615     * @return the start padding in pixels
16616     */
16617    public int getPaddingStart() {
16618        if (!isPaddingResolved()) {
16619            resolvePadding();
16620        }
16621        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16622                mPaddingRight : mPaddingLeft;
16623    }
16624
16625    /**
16626     * Returns the right padding of this view. If there are inset and enabled
16627     * scrollbars, this value may include the space required to display the
16628     * scrollbars as well.
16629     *
16630     * @return the right padding in pixels
16631     */
16632    public int getPaddingRight() {
16633        if (!isPaddingResolved()) {
16634            resolvePadding();
16635        }
16636        return mPaddingRight;
16637    }
16638
16639    /**
16640     * Returns the end padding of this view depending on its resolved layout direction.
16641     * If there are inset and enabled scrollbars, this value may include the space
16642     * required to display the scrollbars as well.
16643     *
16644     * @return the end padding in pixels
16645     */
16646    public int getPaddingEnd() {
16647        if (!isPaddingResolved()) {
16648            resolvePadding();
16649        }
16650        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
16651                mPaddingLeft : mPaddingRight;
16652    }
16653
16654    /**
16655     * Return if the padding as been set thru relative values
16656     * {@link #setPaddingRelative(int, int, int, int)} or thru
16657     * @attr ref android.R.styleable#View_paddingStart or
16658     * @attr ref android.R.styleable#View_paddingEnd
16659     *
16660     * @return true if the padding is relative or false if it is not.
16661     */
16662    public boolean isPaddingRelative() {
16663        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
16664    }
16665
16666    Insets computeOpticalInsets() {
16667        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
16668    }
16669
16670    /**
16671     * @hide
16672     */
16673    public void resetPaddingToInitialValues() {
16674        if (isRtlCompatibilityMode()) {
16675            mPaddingLeft = mUserPaddingLeftInitial;
16676            mPaddingRight = mUserPaddingRightInitial;
16677            return;
16678        }
16679        if (isLayoutRtl()) {
16680            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
16681            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
16682        } else {
16683            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
16684            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
16685        }
16686    }
16687
16688    /**
16689     * @hide
16690     */
16691    public Insets getOpticalInsets() {
16692        if (mLayoutInsets == null) {
16693            mLayoutInsets = computeOpticalInsets();
16694        }
16695        return mLayoutInsets;
16696    }
16697
16698    /**
16699     * Set this view's optical insets.
16700     *
16701     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
16702     * property. Views that compute their own optical insets should call it as part of measurement.
16703     * This method does not request layout. If you are setting optical insets outside of
16704     * measure/layout itself you will want to call requestLayout() yourself.
16705     * </p>
16706     * @hide
16707     */
16708    public void setOpticalInsets(Insets insets) {
16709        mLayoutInsets = insets;
16710    }
16711
16712    /**
16713     * Changes the selection state of this view. A view can be selected or not.
16714     * Note that selection is not the same as focus. Views are typically
16715     * selected in the context of an AdapterView like ListView or GridView;
16716     * the selected view is the view that is highlighted.
16717     *
16718     * @param selected true if the view must be selected, false otherwise
16719     */
16720    public void setSelected(boolean selected) {
16721        //noinspection DoubleNegation
16722        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
16723            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
16724            if (!selected) resetPressedState();
16725            invalidate(true);
16726            refreshDrawableState();
16727            dispatchSetSelected(selected);
16728            if (selected) {
16729                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
16730            } else {
16731                notifyViewAccessibilityStateChangedIfNeeded(
16732                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
16733            }
16734        }
16735    }
16736
16737    /**
16738     * Dispatch setSelected to all of this View's children.
16739     *
16740     * @see #setSelected(boolean)
16741     *
16742     * @param selected The new selected state
16743     */
16744    protected void dispatchSetSelected(boolean selected) {
16745    }
16746
16747    /**
16748     * Indicates the selection state of this view.
16749     *
16750     * @return true if the view is selected, false otherwise
16751     */
16752    @ViewDebug.ExportedProperty
16753    public boolean isSelected() {
16754        return (mPrivateFlags & PFLAG_SELECTED) != 0;
16755    }
16756
16757    /**
16758     * Changes the activated state of this view. A view can be activated or not.
16759     * Note that activation is not the same as selection.  Selection is
16760     * a transient property, representing the view (hierarchy) the user is
16761     * currently interacting with.  Activation is a longer-term state that the
16762     * user can move views in and out of.  For example, in a list view with
16763     * single or multiple selection enabled, the views in the current selection
16764     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
16765     * here.)  The activated state is propagated down to children of the view it
16766     * is set on.
16767     *
16768     * @param activated true if the view must be activated, false otherwise
16769     */
16770    public void setActivated(boolean activated) {
16771        //noinspection DoubleNegation
16772        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
16773            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
16774            invalidate(true);
16775            refreshDrawableState();
16776            dispatchSetActivated(activated);
16777        }
16778    }
16779
16780    /**
16781     * Dispatch setActivated to all of this View's children.
16782     *
16783     * @see #setActivated(boolean)
16784     *
16785     * @param activated The new activated state
16786     */
16787    protected void dispatchSetActivated(boolean activated) {
16788    }
16789
16790    /**
16791     * Indicates the activation state of this view.
16792     *
16793     * @return true if the view is activated, false otherwise
16794     */
16795    @ViewDebug.ExportedProperty
16796    public boolean isActivated() {
16797        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
16798    }
16799
16800    /**
16801     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
16802     * observer can be used to get notifications when global events, like
16803     * layout, happen.
16804     *
16805     * The returned ViewTreeObserver observer is not guaranteed to remain
16806     * valid for the lifetime of this View. If the caller of this method keeps
16807     * a long-lived reference to ViewTreeObserver, it should always check for
16808     * the return value of {@link ViewTreeObserver#isAlive()}.
16809     *
16810     * @return The ViewTreeObserver for this view's hierarchy.
16811     */
16812    public ViewTreeObserver getViewTreeObserver() {
16813        if (mAttachInfo != null) {
16814            return mAttachInfo.mTreeObserver;
16815        }
16816        if (mFloatingTreeObserver == null) {
16817            mFloatingTreeObserver = new ViewTreeObserver();
16818        }
16819        return mFloatingTreeObserver;
16820    }
16821
16822    /**
16823     * <p>Finds the topmost view in the current view hierarchy.</p>
16824     *
16825     * @return the topmost view containing this view
16826     */
16827    public View getRootView() {
16828        if (mAttachInfo != null) {
16829            final View v = mAttachInfo.mRootView;
16830            if (v != null) {
16831                return v;
16832            }
16833        }
16834
16835        View parent = this;
16836
16837        while (parent.mParent != null && parent.mParent instanceof View) {
16838            parent = (View) parent.mParent;
16839        }
16840
16841        return parent;
16842    }
16843
16844    /**
16845     * Transforms a motion event from view-local coordinates to on-screen
16846     * coordinates.
16847     *
16848     * @param ev the view-local motion event
16849     * @return false if the transformation could not be applied
16850     * @hide
16851     */
16852    public boolean toGlobalMotionEvent(MotionEvent ev) {
16853        final AttachInfo info = mAttachInfo;
16854        if (info == null) {
16855            return false;
16856        }
16857
16858        final Matrix m = info.mTmpMatrix;
16859        m.set(Matrix.IDENTITY_MATRIX);
16860        transformMatrixToGlobal(m);
16861        ev.transform(m);
16862        return true;
16863    }
16864
16865    /**
16866     * Transforms a motion event from on-screen coordinates to view-local
16867     * coordinates.
16868     *
16869     * @param ev the on-screen motion event
16870     * @return false if the transformation could not be applied
16871     * @hide
16872     */
16873    public boolean toLocalMotionEvent(MotionEvent ev) {
16874        final AttachInfo info = mAttachInfo;
16875        if (info == null) {
16876            return false;
16877        }
16878
16879        final Matrix m = info.mTmpMatrix;
16880        m.set(Matrix.IDENTITY_MATRIX);
16881        transformMatrixToLocal(m);
16882        ev.transform(m);
16883        return true;
16884    }
16885
16886    /**
16887     * Modifies the input matrix such that it maps view-local coordinates to
16888     * on-screen coordinates.
16889     *
16890     * @param m input matrix to modify
16891     * @hide
16892     */
16893    public void transformMatrixToGlobal(Matrix m) {
16894        final ViewParent parent = mParent;
16895        if (parent instanceof View) {
16896            final View vp = (View) parent;
16897            vp.transformMatrixToGlobal(m);
16898            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
16899        } else if (parent instanceof ViewRootImpl) {
16900            final ViewRootImpl vr = (ViewRootImpl) parent;
16901            vr.transformMatrixToGlobal(m);
16902            m.preTranslate(0, -vr.mCurScrollY);
16903        }
16904
16905        m.preTranslate(mLeft, mTop);
16906
16907        if (!hasIdentityMatrix()) {
16908            m.preConcat(getMatrix());
16909        }
16910    }
16911
16912    /**
16913     * Modifies the input matrix such that it maps on-screen coordinates to
16914     * view-local coordinates.
16915     *
16916     * @param m input matrix to modify
16917     * @hide
16918     */
16919    public void transformMatrixToLocal(Matrix m) {
16920        final ViewParent parent = mParent;
16921        if (parent instanceof View) {
16922            final View vp = (View) parent;
16923            vp.transformMatrixToLocal(m);
16924            m.postTranslate(vp.mScrollX, vp.mScrollY);
16925        } else if (parent instanceof ViewRootImpl) {
16926            final ViewRootImpl vr = (ViewRootImpl) parent;
16927            vr.transformMatrixToLocal(m);
16928            m.postTranslate(0, vr.mCurScrollY);
16929        }
16930
16931        m.postTranslate(-mLeft, -mTop);
16932
16933        if (!hasIdentityMatrix()) {
16934            m.postConcat(getInverseMatrix());
16935        }
16936    }
16937
16938    /**
16939     * @hide
16940     */
16941    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
16942            @ViewDebug.IntToString(from = 0, to = "x"),
16943            @ViewDebug.IntToString(from = 1, to = "y")
16944    })
16945    public int[] getLocationOnScreen() {
16946        int[] location = new int[2];
16947        getLocationOnScreen(location);
16948        return location;
16949    }
16950
16951    /**
16952     * <p>Computes the coordinates of this view on the screen. The argument
16953     * must be an array of two integers. After the method returns, the array
16954     * contains the x and y location in that order.</p>
16955     *
16956     * @param location an array of two integers in which to hold the coordinates
16957     */
16958    public void getLocationOnScreen(int[] location) {
16959        getLocationInWindow(location);
16960
16961        final AttachInfo info = mAttachInfo;
16962        if (info != null) {
16963            location[0] += info.mWindowLeft;
16964            location[1] += info.mWindowTop;
16965        }
16966    }
16967
16968    /**
16969     * <p>Computes the coordinates of this view in its window. The argument
16970     * must be an array of two integers. After the method returns, the array
16971     * contains the x and y location in that order.</p>
16972     *
16973     * @param location an array of two integers in which to hold the coordinates
16974     */
16975    public void getLocationInWindow(int[] location) {
16976        if (location == null || location.length < 2) {
16977            throw new IllegalArgumentException("location must be an array of two integers");
16978        }
16979
16980        if (mAttachInfo == null) {
16981            // When the view is not attached to a window, this method does not make sense
16982            location[0] = location[1] = 0;
16983            return;
16984        }
16985
16986        float[] position = mAttachInfo.mTmpTransformLocation;
16987        position[0] = position[1] = 0.0f;
16988
16989        if (!hasIdentityMatrix()) {
16990            getMatrix().mapPoints(position);
16991        }
16992
16993        position[0] += mLeft;
16994        position[1] += mTop;
16995
16996        ViewParent viewParent = mParent;
16997        while (viewParent instanceof View) {
16998            final View view = (View) viewParent;
16999
17000            position[0] -= view.mScrollX;
17001            position[1] -= view.mScrollY;
17002
17003            if (!view.hasIdentityMatrix()) {
17004                view.getMatrix().mapPoints(position);
17005            }
17006
17007            position[0] += view.mLeft;
17008            position[1] += view.mTop;
17009
17010            viewParent = view.mParent;
17011         }
17012
17013        if (viewParent instanceof ViewRootImpl) {
17014            // *cough*
17015            final ViewRootImpl vr = (ViewRootImpl) viewParent;
17016            position[1] -= vr.mCurScrollY;
17017        }
17018
17019        location[0] = (int) (position[0] + 0.5f);
17020        location[1] = (int) (position[1] + 0.5f);
17021    }
17022
17023    /**
17024     * {@hide}
17025     * @param id the id of the view to be found
17026     * @return the view of the specified id, null if cannot be found
17027     */
17028    protected View findViewTraversal(int id) {
17029        if (id == mID) {
17030            return this;
17031        }
17032        return null;
17033    }
17034
17035    /**
17036     * {@hide}
17037     * @param tag the tag of the view to be found
17038     * @return the view of specified tag, null if cannot be found
17039     */
17040    protected View findViewWithTagTraversal(Object tag) {
17041        if (tag != null && tag.equals(mTag)) {
17042            return this;
17043        }
17044        return null;
17045    }
17046
17047    /**
17048     * {@hide}
17049     * @param predicate The predicate to evaluate.
17050     * @param childToSkip If not null, ignores this child during the recursive traversal.
17051     * @return The first view that matches the predicate or null.
17052     */
17053    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
17054        if (predicate.apply(this)) {
17055            return this;
17056        }
17057        return null;
17058    }
17059
17060    /**
17061     * Look for a child view with the given id.  If this view has the given
17062     * id, return this view.
17063     *
17064     * @param id The id to search for.
17065     * @return The view that has the given id in the hierarchy or null
17066     */
17067    public final View findViewById(int id) {
17068        if (id < 0) {
17069            return null;
17070        }
17071        return findViewTraversal(id);
17072    }
17073
17074    /**
17075     * Finds a view by its unuque and stable accessibility id.
17076     *
17077     * @param accessibilityId The searched accessibility id.
17078     * @return The found view.
17079     */
17080    final View findViewByAccessibilityId(int accessibilityId) {
17081        if (accessibilityId < 0) {
17082            return null;
17083        }
17084        return findViewByAccessibilityIdTraversal(accessibilityId);
17085    }
17086
17087    /**
17088     * Performs the traversal to find a view by its unuque and stable accessibility id.
17089     *
17090     * <strong>Note:</strong>This method does not stop at the root namespace
17091     * boundary since the user can touch the screen at an arbitrary location
17092     * potentially crossing the root namespace bounday which will send an
17093     * accessibility event to accessibility services and they should be able
17094     * to obtain the event source. Also accessibility ids are guaranteed to be
17095     * unique in the window.
17096     *
17097     * @param accessibilityId The accessibility id.
17098     * @return The found view.
17099     *
17100     * @hide
17101     */
17102    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17103        if (getAccessibilityViewId() == accessibilityId) {
17104            return this;
17105        }
17106        return null;
17107    }
17108
17109    /**
17110     * Look for a child view with the given tag.  If this view has the given
17111     * tag, return this view.
17112     *
17113     * @param tag The tag to search for, using "tag.equals(getTag())".
17114     * @return The View that has the given tag in the hierarchy or null
17115     */
17116    public final View findViewWithTag(Object tag) {
17117        if (tag == null) {
17118            return null;
17119        }
17120        return findViewWithTagTraversal(tag);
17121    }
17122
17123    /**
17124     * {@hide}
17125     * Look for a child view that matches the specified predicate.
17126     * If this view matches the predicate, return this view.
17127     *
17128     * @param predicate The predicate to evaluate.
17129     * @return The first view that matches the predicate or null.
17130     */
17131    public final View findViewByPredicate(Predicate<View> predicate) {
17132        return findViewByPredicateTraversal(predicate, null);
17133    }
17134
17135    /**
17136     * {@hide}
17137     * Look for a child view that matches the specified predicate,
17138     * starting with the specified view and its descendents and then
17139     * recusively searching the ancestors and siblings of that view
17140     * until this view is reached.
17141     *
17142     * This method is useful in cases where the predicate does not match
17143     * a single unique view (perhaps multiple views use the same id)
17144     * and we are trying to find the view that is "closest" in scope to the
17145     * starting view.
17146     *
17147     * @param start The view to start from.
17148     * @param predicate The predicate to evaluate.
17149     * @return The first view that matches the predicate or null.
17150     */
17151    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17152        View childToSkip = null;
17153        for (;;) {
17154            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17155            if (view != null || start == this) {
17156                return view;
17157            }
17158
17159            ViewParent parent = start.getParent();
17160            if (parent == null || !(parent instanceof View)) {
17161                return null;
17162            }
17163
17164            childToSkip = start;
17165            start = (View) parent;
17166        }
17167    }
17168
17169    /**
17170     * Sets the identifier for this view. The identifier does not have to be
17171     * unique in this view's hierarchy. The identifier should be a positive
17172     * number.
17173     *
17174     * @see #NO_ID
17175     * @see #getId()
17176     * @see #findViewById(int)
17177     *
17178     * @param id a number used to identify the view
17179     *
17180     * @attr ref android.R.styleable#View_id
17181     */
17182    public void setId(int id) {
17183        mID = id;
17184        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17185            mID = generateViewId();
17186        }
17187    }
17188
17189    /**
17190     * {@hide}
17191     *
17192     * @param isRoot true if the view belongs to the root namespace, false
17193     *        otherwise
17194     */
17195    public void setIsRootNamespace(boolean isRoot) {
17196        if (isRoot) {
17197            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17198        } else {
17199            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17200        }
17201    }
17202
17203    /**
17204     * {@hide}
17205     *
17206     * @return true if the view belongs to the root namespace, false otherwise
17207     */
17208    public boolean isRootNamespace() {
17209        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17210    }
17211
17212    /**
17213     * Returns this view's identifier.
17214     *
17215     * @return a positive integer used to identify the view or {@link #NO_ID}
17216     *         if the view has no ID
17217     *
17218     * @see #setId(int)
17219     * @see #findViewById(int)
17220     * @attr ref android.R.styleable#View_id
17221     */
17222    @ViewDebug.CapturedViewProperty
17223    public int getId() {
17224        return mID;
17225    }
17226
17227    /**
17228     * Returns this view's tag.
17229     *
17230     * @return the Object stored in this view as a tag, or {@code null} if not
17231     *         set
17232     *
17233     * @see #setTag(Object)
17234     * @see #getTag(int)
17235     */
17236    @ViewDebug.ExportedProperty
17237    public Object getTag() {
17238        return mTag;
17239    }
17240
17241    /**
17242     * Sets the tag associated with this view. A tag can be used to mark
17243     * a view in its hierarchy and does not have to be unique within the
17244     * hierarchy. Tags can also be used to store data within a view without
17245     * resorting to another data structure.
17246     *
17247     * @param tag an Object to tag the view with
17248     *
17249     * @see #getTag()
17250     * @see #setTag(int, Object)
17251     */
17252    public void setTag(final Object tag) {
17253        mTag = tag;
17254    }
17255
17256    /**
17257     * Returns the tag associated with this view and the specified key.
17258     *
17259     * @param key The key identifying the tag
17260     *
17261     * @return the Object stored in this view as a tag, or {@code null} if not
17262     *         set
17263     *
17264     * @see #setTag(int, Object)
17265     * @see #getTag()
17266     */
17267    public Object getTag(int key) {
17268        if (mKeyedTags != null) return mKeyedTags.get(key);
17269        return null;
17270    }
17271
17272    /**
17273     * Sets a tag associated with this view and a key. A tag can be used
17274     * to mark a view in its hierarchy and does not have to be unique within
17275     * the hierarchy. Tags can also be used to store data within a view
17276     * without resorting to another data structure.
17277     *
17278     * The specified key should be an id declared in the resources of the
17279     * application to ensure it is unique (see the <a
17280     * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17281     * Keys identified as belonging to
17282     * the Android framework or not associated with any package will cause
17283     * an {@link IllegalArgumentException} to be thrown.
17284     *
17285     * @param key The key identifying the tag
17286     * @param tag An Object to tag the view with
17287     *
17288     * @throws IllegalArgumentException If they specified key is not valid
17289     *
17290     * @see #setTag(Object)
17291     * @see #getTag(int)
17292     */
17293    public void setTag(int key, final Object tag) {
17294        // If the package id is 0x00 or 0x01, it's either an undefined package
17295        // or a framework id
17296        if ((key >>> 24) < 2) {
17297            throw new IllegalArgumentException("The key must be an application-specific "
17298                    + "resource id.");
17299        }
17300
17301        setKeyedTag(key, tag);
17302    }
17303
17304    /**
17305     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17306     * framework id.
17307     *
17308     * @hide
17309     */
17310    public void setTagInternal(int key, Object tag) {
17311        if ((key >>> 24) != 0x1) {
17312            throw new IllegalArgumentException("The key must be a framework-specific "
17313                    + "resource id.");
17314        }
17315
17316        setKeyedTag(key, tag);
17317    }
17318
17319    private void setKeyedTag(int key, Object tag) {
17320        if (mKeyedTags == null) {
17321            mKeyedTags = new SparseArray<Object>(2);
17322        }
17323
17324        mKeyedTags.put(key, tag);
17325    }
17326
17327    /**
17328     * Prints information about this view in the log output, with the tag
17329     * {@link #VIEW_LOG_TAG}.
17330     *
17331     * @hide
17332     */
17333    public void debug() {
17334        debug(0);
17335    }
17336
17337    /**
17338     * Prints information about this view in the log output, with the tag
17339     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
17340     * indentation defined by the <code>depth</code>.
17341     *
17342     * @param depth the indentation level
17343     *
17344     * @hide
17345     */
17346    protected void debug(int depth) {
17347        String output = debugIndent(depth - 1);
17348
17349        output += "+ " + this;
17350        int id = getId();
17351        if (id != -1) {
17352            output += " (id=" + id + ")";
17353        }
17354        Object tag = getTag();
17355        if (tag != null) {
17356            output += " (tag=" + tag + ")";
17357        }
17358        Log.d(VIEW_LOG_TAG, output);
17359
17360        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
17361            output = debugIndent(depth) + " FOCUSED";
17362            Log.d(VIEW_LOG_TAG, output);
17363        }
17364
17365        output = debugIndent(depth);
17366        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
17367                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
17368                + "} ";
17369        Log.d(VIEW_LOG_TAG, output);
17370
17371        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
17372                || mPaddingBottom != 0) {
17373            output = debugIndent(depth);
17374            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
17375                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
17376            Log.d(VIEW_LOG_TAG, output);
17377        }
17378
17379        output = debugIndent(depth);
17380        output += "mMeasureWidth=" + mMeasuredWidth +
17381                " mMeasureHeight=" + mMeasuredHeight;
17382        Log.d(VIEW_LOG_TAG, output);
17383
17384        output = debugIndent(depth);
17385        if (mLayoutParams == null) {
17386            output += "BAD! no layout params";
17387        } else {
17388            output = mLayoutParams.debug(output);
17389        }
17390        Log.d(VIEW_LOG_TAG, output);
17391
17392        output = debugIndent(depth);
17393        output += "flags={";
17394        output += View.printFlags(mViewFlags);
17395        output += "}";
17396        Log.d(VIEW_LOG_TAG, output);
17397
17398        output = debugIndent(depth);
17399        output += "privateFlags={";
17400        output += View.printPrivateFlags(mPrivateFlags);
17401        output += "}";
17402        Log.d(VIEW_LOG_TAG, output);
17403    }
17404
17405    /**
17406     * Creates a string of whitespaces used for indentation.
17407     *
17408     * @param depth the indentation level
17409     * @return a String containing (depth * 2 + 3) * 2 white spaces
17410     *
17411     * @hide
17412     */
17413    protected static String debugIndent(int depth) {
17414        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
17415        for (int i = 0; i < (depth * 2) + 3; i++) {
17416            spaces.append(' ').append(' ');
17417        }
17418        return spaces.toString();
17419    }
17420
17421    /**
17422     * <p>Return the offset of the widget's text baseline from the widget's top
17423     * boundary. If this widget does not support baseline alignment, this
17424     * method returns -1. </p>
17425     *
17426     * @return the offset of the baseline within the widget's bounds or -1
17427     *         if baseline alignment is not supported
17428     */
17429    @ViewDebug.ExportedProperty(category = "layout")
17430    public int getBaseline() {
17431        return -1;
17432    }
17433
17434    /**
17435     * Returns whether the view hierarchy is currently undergoing a layout pass. This
17436     * information is useful to avoid situations such as calling {@link #requestLayout()} during
17437     * a layout pass.
17438     *
17439     * @return whether the view hierarchy is currently undergoing a layout pass
17440     */
17441    public boolean isInLayout() {
17442        ViewRootImpl viewRoot = getViewRootImpl();
17443        return (viewRoot != null && viewRoot.isInLayout());
17444    }
17445
17446    /**
17447     * Call this when something has changed which has invalidated the
17448     * layout of this view. This will schedule a layout pass of the view
17449     * tree. This should not be called while the view hierarchy is currently in a layout
17450     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
17451     * end of the current layout pass (and then layout will run again) or after the current
17452     * frame is drawn and the next layout occurs.
17453     *
17454     * <p>Subclasses which override this method should call the superclass method to
17455     * handle possible request-during-layout errors correctly.</p>
17456     */
17457    public void requestLayout() {
17458        if (mMeasureCache != null) mMeasureCache.clear();
17459
17460        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
17461            // Only trigger request-during-layout logic if this is the view requesting it,
17462            // not the views in its parent hierarchy
17463            ViewRootImpl viewRoot = getViewRootImpl();
17464            if (viewRoot != null && viewRoot.isInLayout()) {
17465                if (!viewRoot.requestLayoutDuringLayout(this)) {
17466                    return;
17467                }
17468            }
17469            mAttachInfo.mViewRequestingLayout = this;
17470        }
17471
17472        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17473        mPrivateFlags |= PFLAG_INVALIDATED;
17474
17475        if (mParent != null && !mParent.isLayoutRequested()) {
17476            mParent.requestLayout();
17477        }
17478        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
17479            mAttachInfo.mViewRequestingLayout = null;
17480        }
17481    }
17482
17483    /**
17484     * Forces this view to be laid out during the next layout pass.
17485     * This method does not call requestLayout() or forceLayout()
17486     * on the parent.
17487     */
17488    public void forceLayout() {
17489        if (mMeasureCache != null) mMeasureCache.clear();
17490
17491        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
17492        mPrivateFlags |= PFLAG_INVALIDATED;
17493    }
17494
17495    /**
17496     * <p>
17497     * This is called to find out how big a view should be. The parent
17498     * supplies constraint information in the width and height parameters.
17499     * </p>
17500     *
17501     * <p>
17502     * The actual measurement work of a view is performed in
17503     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
17504     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
17505     * </p>
17506     *
17507     *
17508     * @param widthMeasureSpec Horizontal space requirements as imposed by the
17509     *        parent
17510     * @param heightMeasureSpec Vertical space requirements as imposed by the
17511     *        parent
17512     *
17513     * @see #onMeasure(int, int)
17514     */
17515    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
17516        boolean optical = isLayoutModeOptical(this);
17517        if (optical != isLayoutModeOptical(mParent)) {
17518            Insets insets = getOpticalInsets();
17519            int oWidth  = insets.left + insets.right;
17520            int oHeight = insets.top  + insets.bottom;
17521            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
17522            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
17523        }
17524
17525        // Suppress sign extension for the low bytes
17526        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
17527        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
17528
17529        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
17530        final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
17531                MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
17532        final boolean matchingSize = isExactly &&
17533                getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
17534                getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
17535        if (forceLayout || !matchingSize &&
17536                (widthMeasureSpec != mOldWidthMeasureSpec ||
17537                        heightMeasureSpec != mOldHeightMeasureSpec)) {
17538
17539            // first clears the measured dimension flag
17540            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
17541
17542            resolveRtlPropertiesIfNeeded();
17543
17544            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
17545            if (cacheIndex < 0 || sIgnoreMeasureCache) {
17546                // measure ourselves, this should set the measured dimension flag back
17547                onMeasure(widthMeasureSpec, heightMeasureSpec);
17548                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17549            } else {
17550                long value = mMeasureCache.valueAt(cacheIndex);
17551                // Casting a long to int drops the high 32 bits, no mask needed
17552                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
17553                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
17554            }
17555
17556            // flag not set, setMeasuredDimension() was not invoked, we raise
17557            // an exception to warn the developer
17558            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
17559                throw new IllegalStateException("onMeasure() did not set the"
17560                        + " measured dimension by calling"
17561                        + " setMeasuredDimension()");
17562            }
17563
17564            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
17565        }
17566
17567        mOldWidthMeasureSpec = widthMeasureSpec;
17568        mOldHeightMeasureSpec = heightMeasureSpec;
17569
17570        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
17571                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
17572    }
17573
17574    /**
17575     * <p>
17576     * Measure the view and its content to determine the measured width and the
17577     * measured height. This method is invoked by {@link #measure(int, int)} and
17578     * should be overriden by subclasses to provide accurate and efficient
17579     * measurement of their contents.
17580     * </p>
17581     *
17582     * <p>
17583     * <strong>CONTRACT:</strong> When overriding this method, you
17584     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
17585     * measured width and height of this view. Failure to do so will trigger an
17586     * <code>IllegalStateException</code>, thrown by
17587     * {@link #measure(int, int)}. Calling the superclass'
17588     * {@link #onMeasure(int, int)} is a valid use.
17589     * </p>
17590     *
17591     * <p>
17592     * The base class implementation of measure defaults to the background size,
17593     * unless a larger size is allowed by the MeasureSpec. Subclasses should
17594     * override {@link #onMeasure(int, int)} to provide better measurements of
17595     * their content.
17596     * </p>
17597     *
17598     * <p>
17599     * If this method is overridden, it is the subclass's responsibility to make
17600     * sure the measured height and width are at least the view's minimum height
17601     * and width ({@link #getSuggestedMinimumHeight()} and
17602     * {@link #getSuggestedMinimumWidth()}).
17603     * </p>
17604     *
17605     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
17606     *                         The requirements are encoded with
17607     *                         {@link android.view.View.MeasureSpec}.
17608     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
17609     *                         The requirements are encoded with
17610     *                         {@link android.view.View.MeasureSpec}.
17611     *
17612     * @see #getMeasuredWidth()
17613     * @see #getMeasuredHeight()
17614     * @see #setMeasuredDimension(int, int)
17615     * @see #getSuggestedMinimumHeight()
17616     * @see #getSuggestedMinimumWidth()
17617     * @see android.view.View.MeasureSpec#getMode(int)
17618     * @see android.view.View.MeasureSpec#getSize(int)
17619     */
17620    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
17621        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
17622                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
17623    }
17624
17625    /**
17626     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
17627     * measured width and measured height. Failing to do so will trigger an
17628     * exception at measurement time.</p>
17629     *
17630     * @param measuredWidth The measured width of this view.  May be a complex
17631     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17632     * {@link #MEASURED_STATE_TOO_SMALL}.
17633     * @param measuredHeight The measured height of this view.  May be a complex
17634     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17635     * {@link #MEASURED_STATE_TOO_SMALL}.
17636     */
17637    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
17638        boolean optical = isLayoutModeOptical(this);
17639        if (optical != isLayoutModeOptical(mParent)) {
17640            Insets insets = getOpticalInsets();
17641            int opticalWidth  = insets.left + insets.right;
17642            int opticalHeight = insets.top  + insets.bottom;
17643
17644            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
17645            measuredHeight += optical ? opticalHeight : -opticalHeight;
17646        }
17647        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
17648    }
17649
17650    /**
17651     * Sets the measured dimension without extra processing for things like optical bounds.
17652     * Useful for reapplying consistent values that have already been cooked with adjustments
17653     * for optical bounds, etc. such as those from the measurement cache.
17654     *
17655     * @param measuredWidth The measured width of this view.  May be a complex
17656     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17657     * {@link #MEASURED_STATE_TOO_SMALL}.
17658     * @param measuredHeight The measured height of this view.  May be a complex
17659     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
17660     * {@link #MEASURED_STATE_TOO_SMALL}.
17661     */
17662    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
17663        mMeasuredWidth = measuredWidth;
17664        mMeasuredHeight = measuredHeight;
17665
17666        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
17667    }
17668
17669    /**
17670     * Merge two states as returned by {@link #getMeasuredState()}.
17671     * @param curState The current state as returned from a view or the result
17672     * of combining multiple views.
17673     * @param newState The new view state to combine.
17674     * @return Returns a new integer reflecting the combination of the two
17675     * states.
17676     */
17677    public static int combineMeasuredStates(int curState, int newState) {
17678        return curState | newState;
17679    }
17680
17681    /**
17682     * Version of {@link #resolveSizeAndState(int, int, int)}
17683     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
17684     */
17685    public static int resolveSize(int size, int measureSpec) {
17686        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
17687    }
17688
17689    /**
17690     * Utility to reconcile a desired size and state, with constraints imposed
17691     * by a MeasureSpec.  Will take the desired size, unless a different size
17692     * is imposed by the constraints.  The returned value is a compound integer,
17693     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
17694     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
17695     * size is smaller than the size the view wants to be.
17696     *
17697     * @param size How big the view wants to be
17698     * @param measureSpec Constraints imposed by the parent
17699     * @return Size information bit mask as defined by
17700     * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
17701     */
17702    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
17703        int result = size;
17704        int specMode = MeasureSpec.getMode(measureSpec);
17705        int specSize =  MeasureSpec.getSize(measureSpec);
17706        switch (specMode) {
17707        case MeasureSpec.UNSPECIFIED:
17708            result = size;
17709            break;
17710        case MeasureSpec.AT_MOST:
17711            if (specSize < size) {
17712                result = specSize | MEASURED_STATE_TOO_SMALL;
17713            } else {
17714                result = size;
17715            }
17716            break;
17717        case MeasureSpec.EXACTLY:
17718            result = specSize;
17719            break;
17720        }
17721        return result | (childMeasuredState&MEASURED_STATE_MASK);
17722    }
17723
17724    /**
17725     * Utility to return a default size. Uses the supplied size if the
17726     * MeasureSpec imposed no constraints. Will get larger if allowed
17727     * by the MeasureSpec.
17728     *
17729     * @param size Default size for this view
17730     * @param measureSpec Constraints imposed by the parent
17731     * @return The size this view should be.
17732     */
17733    public static int getDefaultSize(int size, int measureSpec) {
17734        int result = size;
17735        int specMode = MeasureSpec.getMode(measureSpec);
17736        int specSize = MeasureSpec.getSize(measureSpec);
17737
17738        switch (specMode) {
17739        case MeasureSpec.UNSPECIFIED:
17740            result = size;
17741            break;
17742        case MeasureSpec.AT_MOST:
17743        case MeasureSpec.EXACTLY:
17744            result = specSize;
17745            break;
17746        }
17747        return result;
17748    }
17749
17750    /**
17751     * Returns the suggested minimum height that the view should use. This
17752     * returns the maximum of the view's minimum height
17753     * and the background's minimum height
17754     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
17755     * <p>
17756     * When being used in {@link #onMeasure(int, int)}, the caller should still
17757     * ensure the returned height is within the requirements of the parent.
17758     *
17759     * @return The suggested minimum height of the view.
17760     */
17761    protected int getSuggestedMinimumHeight() {
17762        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
17763
17764    }
17765
17766    /**
17767     * Returns the suggested minimum width that the view should use. This
17768     * returns the maximum of the view's minimum width)
17769     * and the background's minimum width
17770     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
17771     * <p>
17772     * When being used in {@link #onMeasure(int, int)}, the caller should still
17773     * ensure the returned width is within the requirements of the parent.
17774     *
17775     * @return The suggested minimum width of the view.
17776     */
17777    protected int getSuggestedMinimumWidth() {
17778        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
17779    }
17780
17781    /**
17782     * Returns the minimum height of the view.
17783     *
17784     * @return the minimum height the view will try to be.
17785     *
17786     * @see #setMinimumHeight(int)
17787     *
17788     * @attr ref android.R.styleable#View_minHeight
17789     */
17790    public int getMinimumHeight() {
17791        return mMinHeight;
17792    }
17793
17794    /**
17795     * Sets the minimum height of the view. It is not guaranteed the view will
17796     * be able to achieve this minimum height (for example, if its parent layout
17797     * constrains it with less available height).
17798     *
17799     * @param minHeight The minimum height the view will try to be.
17800     *
17801     * @see #getMinimumHeight()
17802     *
17803     * @attr ref android.R.styleable#View_minHeight
17804     */
17805    public void setMinimumHeight(int minHeight) {
17806        mMinHeight = minHeight;
17807        requestLayout();
17808    }
17809
17810    /**
17811     * Returns the minimum width of the view.
17812     *
17813     * @return the minimum width the view will try to be.
17814     *
17815     * @see #setMinimumWidth(int)
17816     *
17817     * @attr ref android.R.styleable#View_minWidth
17818     */
17819    public int getMinimumWidth() {
17820        return mMinWidth;
17821    }
17822
17823    /**
17824     * Sets the minimum width of the view. It is not guaranteed the view will
17825     * be able to achieve this minimum width (for example, if its parent layout
17826     * constrains it with less available width).
17827     *
17828     * @param minWidth The minimum width the view will try to be.
17829     *
17830     * @see #getMinimumWidth()
17831     *
17832     * @attr ref android.R.styleable#View_minWidth
17833     */
17834    public void setMinimumWidth(int minWidth) {
17835        mMinWidth = minWidth;
17836        requestLayout();
17837
17838    }
17839
17840    /**
17841     * Get the animation currently associated with this view.
17842     *
17843     * @return The animation that is currently playing or
17844     *         scheduled to play for this view.
17845     */
17846    public Animation getAnimation() {
17847        return mCurrentAnimation;
17848    }
17849
17850    /**
17851     * Start the specified animation now.
17852     *
17853     * @param animation the animation to start now
17854     */
17855    public void startAnimation(Animation animation) {
17856        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
17857        setAnimation(animation);
17858        invalidateParentCaches();
17859        invalidate(true);
17860    }
17861
17862    /**
17863     * Cancels any animations for this view.
17864     */
17865    public void clearAnimation() {
17866        if (mCurrentAnimation != null) {
17867            mCurrentAnimation.detach();
17868        }
17869        mCurrentAnimation = null;
17870        invalidateParentIfNeeded();
17871    }
17872
17873    /**
17874     * Sets the next animation to play for this view.
17875     * If you want the animation to play immediately, use
17876     * {@link #startAnimation(android.view.animation.Animation)} instead.
17877     * This method provides allows fine-grained
17878     * control over the start time and invalidation, but you
17879     * must make sure that 1) the animation has a start time set, and
17880     * 2) the view's parent (which controls animations on its children)
17881     * will be invalidated when the animation is supposed to
17882     * start.
17883     *
17884     * @param animation The next animation, or null.
17885     */
17886    public void setAnimation(Animation animation) {
17887        mCurrentAnimation = animation;
17888
17889        if (animation != null) {
17890            // If the screen is off assume the animation start time is now instead of
17891            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
17892            // would cause the animation to start when the screen turns back on
17893            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
17894                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
17895                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
17896            }
17897            animation.reset();
17898        }
17899    }
17900
17901    /**
17902     * Invoked by a parent ViewGroup to notify the start of the animation
17903     * currently associated with this view. If you override this method,
17904     * always call super.onAnimationStart();
17905     *
17906     * @see #setAnimation(android.view.animation.Animation)
17907     * @see #getAnimation()
17908     */
17909    protected void onAnimationStart() {
17910        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
17911    }
17912
17913    /**
17914     * Invoked by a parent ViewGroup to notify the end of the animation
17915     * currently associated with this view. If you override this method,
17916     * always call super.onAnimationEnd();
17917     *
17918     * @see #setAnimation(android.view.animation.Animation)
17919     * @see #getAnimation()
17920     */
17921    protected void onAnimationEnd() {
17922        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
17923    }
17924
17925    /**
17926     * Invoked if there is a Transform that involves alpha. Subclass that can
17927     * draw themselves with the specified alpha should return true, and then
17928     * respect that alpha when their onDraw() is called. If this returns false
17929     * then the view may be redirected to draw into an offscreen buffer to
17930     * fulfill the request, which will look fine, but may be slower than if the
17931     * subclass handles it internally. The default implementation returns false.
17932     *
17933     * @param alpha The alpha (0..255) to apply to the view's drawing
17934     * @return true if the view can draw with the specified alpha.
17935     */
17936    protected boolean onSetAlpha(int alpha) {
17937        return false;
17938    }
17939
17940    /**
17941     * This is used by the RootView to perform an optimization when
17942     * the view hierarchy contains one or several SurfaceView.
17943     * SurfaceView is always considered transparent, but its children are not,
17944     * therefore all View objects remove themselves from the global transparent
17945     * region (passed as a parameter to this function).
17946     *
17947     * @param region The transparent region for this ViewAncestor (window).
17948     *
17949     * @return Returns true if the effective visibility of the view at this
17950     * point is opaque, regardless of the transparent region; returns false
17951     * if it is possible for underlying windows to be seen behind the view.
17952     *
17953     * {@hide}
17954     */
17955    public boolean gatherTransparentRegion(Region region) {
17956        final AttachInfo attachInfo = mAttachInfo;
17957        if (region != null && attachInfo != null) {
17958            final int pflags = mPrivateFlags;
17959            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
17960                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
17961                // remove it from the transparent region.
17962                final int[] location = attachInfo.mTransparentLocation;
17963                getLocationInWindow(location);
17964                region.op(location[0], location[1], location[0] + mRight - mLeft,
17965                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
17966            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
17967                    mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
17968                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
17969                // exists, so we remove the background drawable's non-transparent
17970                // parts from this transparent region.
17971                applyDrawableToTransparentRegion(mBackground, region);
17972            }
17973        }
17974        return true;
17975    }
17976
17977    /**
17978     * Play a sound effect for this view.
17979     *
17980     * <p>The framework will play sound effects for some built in actions, such as
17981     * clicking, but you may wish to play these effects in your widget,
17982     * for instance, for internal navigation.
17983     *
17984     * <p>The sound effect will only be played if sound effects are enabled by the user, and
17985     * {@link #isSoundEffectsEnabled()} is true.
17986     *
17987     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
17988     */
17989    public void playSoundEffect(int soundConstant) {
17990        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
17991            return;
17992        }
17993        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
17994    }
17995
17996    /**
17997     * BZZZTT!!1!
17998     *
17999     * <p>Provide haptic feedback to the user for this view.
18000     *
18001     * <p>The framework will provide haptic feedback for some built in actions,
18002     * such as long presses, but you may wish to provide feedback for your
18003     * own widget.
18004     *
18005     * <p>The feedback will only be performed if
18006     * {@link #isHapticFeedbackEnabled()} is true.
18007     *
18008     * @param feedbackConstant One of the constants defined in
18009     * {@link HapticFeedbackConstants}
18010     */
18011    public boolean performHapticFeedback(int feedbackConstant) {
18012        return performHapticFeedback(feedbackConstant, 0);
18013    }
18014
18015    /**
18016     * BZZZTT!!1!
18017     *
18018     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
18019     *
18020     * @param feedbackConstant One of the constants defined in
18021     * {@link HapticFeedbackConstants}
18022     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
18023     */
18024    public boolean performHapticFeedback(int feedbackConstant, int flags) {
18025        if (mAttachInfo == null) {
18026            return false;
18027        }
18028        //noinspection SimplifiableIfStatement
18029        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
18030                && !isHapticFeedbackEnabled()) {
18031            return false;
18032        }
18033        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
18034                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
18035    }
18036
18037    /**
18038     * Request that the visibility of the status bar or other screen/window
18039     * decorations be changed.
18040     *
18041     * <p>This method is used to put the over device UI into temporary modes
18042     * where the user's attention is focused more on the application content,
18043     * by dimming or hiding surrounding system affordances.  This is typically
18044     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
18045     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
18046     * to be placed behind the action bar (and with these flags other system
18047     * affordances) so that smooth transitions between hiding and showing them
18048     * can be done.
18049     *
18050     * <p>Two representative examples of the use of system UI visibility is
18051     * implementing a content browsing application (like a magazine reader)
18052     * and a video playing application.
18053     *
18054     * <p>The first code shows a typical implementation of a View in a content
18055     * browsing application.  In this implementation, the application goes
18056     * into a content-oriented mode by hiding the status bar and action bar,
18057     * and putting the navigation elements into lights out mode.  The user can
18058     * then interact with content while in this mode.  Such an application should
18059     * provide an easy way for the user to toggle out of the mode (such as to
18060     * check information in the status bar or access notifications).  In the
18061     * implementation here, this is done simply by tapping on the content.
18062     *
18063     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
18064     *      content}
18065     *
18066     * <p>This second code sample shows a typical implementation of a View
18067     * in a video playing application.  In this situation, while the video is
18068     * playing the application would like to go into a complete full-screen mode,
18069     * to use as much of the display as possible for the video.  When in this state
18070     * the user can not interact with the application; the system intercepts
18071     * touching on the screen to pop the UI out of full screen mode.  See
18072     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
18073     *
18074     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
18075     *      content}
18076     *
18077     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18078     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18079     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18080     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18081     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18082     */
18083    public void setSystemUiVisibility(int visibility) {
18084        if (visibility != mSystemUiVisibility) {
18085            mSystemUiVisibility = visibility;
18086            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18087                mParent.recomputeViewAttributes(this);
18088            }
18089        }
18090    }
18091
18092    /**
18093     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
18094     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18095     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18096     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18097     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18098     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18099     */
18100    public int getSystemUiVisibility() {
18101        return mSystemUiVisibility;
18102    }
18103
18104    /**
18105     * Returns the current system UI visibility that is currently set for
18106     * the entire window.  This is the combination of the
18107     * {@link #setSystemUiVisibility(int)} values supplied by all of the
18108     * views in the window.
18109     */
18110    public int getWindowSystemUiVisibility() {
18111        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18112    }
18113
18114    /**
18115     * Override to find out when the window's requested system UI visibility
18116     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18117     * This is different from the callbacks received through
18118     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18119     * in that this is only telling you about the local request of the window,
18120     * not the actual values applied by the system.
18121     */
18122    public void onWindowSystemUiVisibilityChanged(int visible) {
18123    }
18124
18125    /**
18126     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18127     * the view hierarchy.
18128     */
18129    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18130        onWindowSystemUiVisibilityChanged(visible);
18131    }
18132
18133    /**
18134     * Set a listener to receive callbacks when the visibility of the system bar changes.
18135     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18136     */
18137    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18138        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18139        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18140            mParent.recomputeViewAttributes(this);
18141        }
18142    }
18143
18144    /**
18145     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18146     * the view hierarchy.
18147     */
18148    public void dispatchSystemUiVisibilityChanged(int visibility) {
18149        ListenerInfo li = mListenerInfo;
18150        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18151            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18152                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18153        }
18154    }
18155
18156    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18157        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18158        if (val != mSystemUiVisibility) {
18159            setSystemUiVisibility(val);
18160            return true;
18161        }
18162        return false;
18163    }
18164
18165    /** @hide */
18166    public void setDisabledSystemUiVisibility(int flags) {
18167        if (mAttachInfo != null) {
18168            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18169                mAttachInfo.mDisabledSystemUiVisibility = flags;
18170                if (mParent != null) {
18171                    mParent.recomputeViewAttributes(this);
18172                }
18173            }
18174        }
18175    }
18176
18177    /**
18178     * Creates an image that the system displays during the drag and drop
18179     * operation. This is called a &quot;drag shadow&quot;. The default implementation
18180     * for a DragShadowBuilder based on a View returns an image that has exactly the same
18181     * appearance as the given View. The default also positions the center of the drag shadow
18182     * directly under the touch point. If no View is provided (the constructor with no parameters
18183     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18184     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
18185     * default is an invisible drag shadow.
18186     * <p>
18187     * You are not required to use the View you provide to the constructor as the basis of the
18188     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18189     * anything you want as the drag shadow.
18190     * </p>
18191     * <p>
18192     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
18193     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18194     *  size and position of the drag shadow. It uses this data to construct a
18195     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18196     *  so that your application can draw the shadow image in the Canvas.
18197     * </p>
18198     *
18199     * <div class="special reference">
18200     * <h3>Developer Guides</h3>
18201     * <p>For a guide to implementing drag and drop features, read the
18202     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18203     * </div>
18204     */
18205    public static class DragShadowBuilder {
18206        private final WeakReference<View> mView;
18207
18208        /**
18209         * Constructs a shadow image builder based on a View. By default, the resulting drag
18210         * shadow will have the same appearance and dimensions as the View, with the touch point
18211         * over the center of the View.
18212         * @param view A View. Any View in scope can be used.
18213         */
18214        public DragShadowBuilder(View view) {
18215            mView = new WeakReference<View>(view);
18216        }
18217
18218        /**
18219         * Construct a shadow builder object with no associated View.  This
18220         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18221         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18222         * to supply the drag shadow's dimensions and appearance without
18223         * reference to any View object. If they are not overridden, then the result is an
18224         * invisible drag shadow.
18225         */
18226        public DragShadowBuilder() {
18227            mView = new WeakReference<View>(null);
18228        }
18229
18230        /**
18231         * Returns the View object that had been passed to the
18232         * {@link #View.DragShadowBuilder(View)}
18233         * constructor.  If that View parameter was {@code null} or if the
18234         * {@link #View.DragShadowBuilder()}
18235         * constructor was used to instantiate the builder object, this method will return
18236         * null.
18237         *
18238         * @return The View object associate with this builder object.
18239         */
18240        @SuppressWarnings({"JavadocReference"})
18241        final public View getView() {
18242            return mView.get();
18243        }
18244
18245        /**
18246         * Provides the metrics for the shadow image. These include the dimensions of
18247         * the shadow image, and the point within that shadow that should
18248         * be centered under the touch location while dragging.
18249         * <p>
18250         * The default implementation sets the dimensions of the shadow to be the
18251         * same as the dimensions of the View itself and centers the shadow under
18252         * the touch point.
18253         * </p>
18254         *
18255         * @param shadowSize A {@link android.graphics.Point} containing the width and height
18256         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18257         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18258         * image.
18259         *
18260         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18261         * shadow image that should be underneath the touch point during the drag and drop
18262         * operation. Your application must set {@link android.graphics.Point#x} to the
18263         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18264         */
18265        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18266            final View view = mView.get();
18267            if (view != null) {
18268                shadowSize.set(view.getWidth(), view.getHeight());
18269                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18270            } else {
18271                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18272            }
18273        }
18274
18275        /**
18276         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18277         * based on the dimensions it received from the
18278         * {@link #onProvideShadowMetrics(Point, Point)} callback.
18279         *
18280         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18281         */
18282        public void onDrawShadow(Canvas canvas) {
18283            final View view = mView.get();
18284            if (view != null) {
18285                view.draw(canvas);
18286            } else {
18287                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18288            }
18289        }
18290    }
18291
18292    /**
18293     * Starts a drag and drop operation. When your application calls this method, it passes a
18294     * {@link android.view.View.DragShadowBuilder} object to the system. The
18295     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18296     * to get metrics for the drag shadow, and then calls the object's
18297     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18298     * <p>
18299     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
18300     *  drag events to all the View objects in your application that are currently visible. It does
18301     *  this either by calling the View object's drag listener (an implementation of
18302     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18303     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18304     *  Both are passed a {@link android.view.DragEvent} object that has a
18305     *  {@link android.view.DragEvent#getAction()} value of
18306     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
18307     * </p>
18308     * <p>
18309     * Your application can invoke startDrag() on any attached View object. The View object does not
18310     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
18311     * be related to the View the user selected for dragging.
18312     * </p>
18313     * @param data A {@link android.content.ClipData} object pointing to the data to be
18314     * transferred by the drag and drop operation.
18315     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
18316     * drag shadow.
18317     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
18318     * drop operation. This Object is put into every DragEvent object sent by the system during the
18319     * current drag.
18320     * <p>
18321     * myLocalState is a lightweight mechanism for the sending information from the dragged View
18322     * to the target Views. For example, it can contain flags that differentiate between a
18323     * a copy operation and a move operation.
18324     * </p>
18325     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
18326     * so the parameter should be set to 0.
18327     * @return {@code true} if the method completes successfully, or
18328     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
18329     * do a drag, and so no drag operation is in progress.
18330     */
18331    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
18332            Object myLocalState, int flags) {
18333        if (ViewDebug.DEBUG_DRAG) {
18334            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
18335        }
18336        boolean okay = false;
18337
18338        Point shadowSize = new Point();
18339        Point shadowTouchPoint = new Point();
18340        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
18341
18342        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
18343                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
18344            throw new IllegalStateException("Drag shadow dimensions must not be negative");
18345        }
18346
18347        if (ViewDebug.DEBUG_DRAG) {
18348            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
18349                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
18350        }
18351        Surface surface = new Surface();
18352        try {
18353            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
18354                    flags, shadowSize.x, shadowSize.y, surface);
18355            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
18356                    + " surface=" + surface);
18357            if (token != null) {
18358                Canvas canvas = surface.lockCanvas(null);
18359                try {
18360                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
18361                    shadowBuilder.onDrawShadow(canvas);
18362                } finally {
18363                    surface.unlockCanvasAndPost(canvas);
18364                }
18365
18366                final ViewRootImpl root = getViewRootImpl();
18367
18368                // Cache the local state object for delivery with DragEvents
18369                root.setLocalDragState(myLocalState);
18370
18371                // repurpose 'shadowSize' for the last touch point
18372                root.getLastTouchPoint(shadowSize);
18373
18374                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
18375                        shadowSize.x, shadowSize.y,
18376                        shadowTouchPoint.x, shadowTouchPoint.y, data);
18377                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
18378
18379                // Off and running!  Release our local surface instance; the drag
18380                // shadow surface is now managed by the system process.
18381                surface.release();
18382            }
18383        } catch (Exception e) {
18384            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
18385            surface.destroy();
18386        }
18387
18388        return okay;
18389    }
18390
18391    /**
18392     * Handles drag events sent by the system following a call to
18393     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
18394     *<p>
18395     * When the system calls this method, it passes a
18396     * {@link android.view.DragEvent} object. A call to
18397     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
18398     * in DragEvent. The method uses these to determine what is happening in the drag and drop
18399     * operation.
18400     * @param event The {@link android.view.DragEvent} sent by the system.
18401     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
18402     * in DragEvent, indicating the type of drag event represented by this object.
18403     * @return {@code true} if the method was successful, otherwise {@code false}.
18404     * <p>
18405     *  The method should return {@code true} in response to an action type of
18406     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
18407     *  operation.
18408     * </p>
18409     * <p>
18410     *  The method should also return {@code true} in response to an action type of
18411     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
18412     *  {@code false} if it didn't.
18413     * </p>
18414     */
18415    public boolean onDragEvent(DragEvent event) {
18416        return false;
18417    }
18418
18419    /**
18420     * Detects if this View is enabled and has a drag event listener.
18421     * If both are true, then it calls the drag event listener with the
18422     * {@link android.view.DragEvent} it received. If the drag event listener returns
18423     * {@code true}, then dispatchDragEvent() returns {@code true}.
18424     * <p>
18425     * For all other cases, the method calls the
18426     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
18427     * method and returns its result.
18428     * </p>
18429     * <p>
18430     * This ensures that a drag event is always consumed, even if the View does not have a drag
18431     * event listener. However, if the View has a listener and the listener returns true, then
18432     * onDragEvent() is not called.
18433     * </p>
18434     */
18435    public boolean dispatchDragEvent(DragEvent event) {
18436        ListenerInfo li = mListenerInfo;
18437        //noinspection SimplifiableIfStatement
18438        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
18439                && li.mOnDragListener.onDrag(this, event)) {
18440            return true;
18441        }
18442        return onDragEvent(event);
18443    }
18444
18445    boolean canAcceptDrag() {
18446        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
18447    }
18448
18449    /**
18450     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
18451     * it is ever exposed at all.
18452     * @hide
18453     */
18454    public void onCloseSystemDialogs(String reason) {
18455    }
18456
18457    /**
18458     * Given a Drawable whose bounds have been set to draw into this view,
18459     * update a Region being computed for
18460     * {@link #gatherTransparentRegion(android.graphics.Region)} so
18461     * that any non-transparent parts of the Drawable are removed from the
18462     * given transparent region.
18463     *
18464     * @param dr The Drawable whose transparency is to be applied to the region.
18465     * @param region A Region holding the current transparency information,
18466     * where any parts of the region that are set are considered to be
18467     * transparent.  On return, this region will be modified to have the
18468     * transparency information reduced by the corresponding parts of the
18469     * Drawable that are not transparent.
18470     * {@hide}
18471     */
18472    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
18473        if (DBG) {
18474            Log.i("View", "Getting transparent region for: " + this);
18475        }
18476        final Region r = dr.getTransparentRegion();
18477        final Rect db = dr.getBounds();
18478        final AttachInfo attachInfo = mAttachInfo;
18479        if (r != null && attachInfo != null) {
18480            final int w = getRight()-getLeft();
18481            final int h = getBottom()-getTop();
18482            if (db.left > 0) {
18483                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
18484                r.op(0, 0, db.left, h, Region.Op.UNION);
18485            }
18486            if (db.right < w) {
18487                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
18488                r.op(db.right, 0, w, h, Region.Op.UNION);
18489            }
18490            if (db.top > 0) {
18491                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
18492                r.op(0, 0, w, db.top, Region.Op.UNION);
18493            }
18494            if (db.bottom < h) {
18495                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
18496                r.op(0, db.bottom, w, h, Region.Op.UNION);
18497            }
18498            final int[] location = attachInfo.mTransparentLocation;
18499            getLocationInWindow(location);
18500            r.translate(location[0], location[1]);
18501            region.op(r, Region.Op.INTERSECT);
18502        } else {
18503            region.op(db, Region.Op.DIFFERENCE);
18504        }
18505    }
18506
18507    private void checkForLongClick(int delayOffset) {
18508        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
18509            mHasPerformedLongPress = false;
18510
18511            if (mPendingCheckForLongPress == null) {
18512                mPendingCheckForLongPress = new CheckForLongPress();
18513            }
18514            mPendingCheckForLongPress.rememberWindowAttachCount();
18515            postDelayed(mPendingCheckForLongPress,
18516                    ViewConfiguration.getLongPressTimeout() - delayOffset);
18517        }
18518    }
18519
18520    /**
18521     * Inflate a view from an XML resource.  This convenience method wraps the {@link
18522     * LayoutInflater} class, which provides a full range of options for view inflation.
18523     *
18524     * @param context The Context object for your activity or application.
18525     * @param resource The resource ID to inflate
18526     * @param root A view group that will be the parent.  Used to properly inflate the
18527     * layout_* parameters.
18528     * @see LayoutInflater
18529     */
18530    public static View inflate(Context context, int resource, ViewGroup root) {
18531        LayoutInflater factory = LayoutInflater.from(context);
18532        return factory.inflate(resource, root);
18533    }
18534
18535    /**
18536     * Scroll the view with standard behavior for scrolling beyond the normal
18537     * content boundaries. Views that call this method should override
18538     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
18539     * results of an over-scroll operation.
18540     *
18541     * Views can use this method to handle any touch or fling-based scrolling.
18542     *
18543     * @param deltaX Change in X in pixels
18544     * @param deltaY Change in Y in pixels
18545     * @param scrollX Current X scroll value in pixels before applying deltaX
18546     * @param scrollY Current Y scroll value in pixels before applying deltaY
18547     * @param scrollRangeX Maximum content scroll range along the X axis
18548     * @param scrollRangeY Maximum content scroll range along the Y axis
18549     * @param maxOverScrollX Number of pixels to overscroll by in either direction
18550     *          along the X axis.
18551     * @param maxOverScrollY Number of pixels to overscroll by in either direction
18552     *          along the Y axis.
18553     * @param isTouchEvent true if this scroll operation is the result of a touch event.
18554     * @return true if scrolling was clamped to an over-scroll boundary along either
18555     *          axis, false otherwise.
18556     */
18557    @SuppressWarnings({"UnusedParameters"})
18558    protected boolean overScrollBy(int deltaX, int deltaY,
18559            int scrollX, int scrollY,
18560            int scrollRangeX, int scrollRangeY,
18561            int maxOverScrollX, int maxOverScrollY,
18562            boolean isTouchEvent) {
18563        final int overScrollMode = mOverScrollMode;
18564        final boolean canScrollHorizontal =
18565                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
18566        final boolean canScrollVertical =
18567                computeVerticalScrollRange() > computeVerticalScrollExtent();
18568        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
18569                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
18570        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
18571                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
18572
18573        int newScrollX = scrollX + deltaX;
18574        if (!overScrollHorizontal) {
18575            maxOverScrollX = 0;
18576        }
18577
18578        int newScrollY = scrollY + deltaY;
18579        if (!overScrollVertical) {
18580            maxOverScrollY = 0;
18581        }
18582
18583        // Clamp values if at the limits and record
18584        final int left = -maxOverScrollX;
18585        final int right = maxOverScrollX + scrollRangeX;
18586        final int top = -maxOverScrollY;
18587        final int bottom = maxOverScrollY + scrollRangeY;
18588
18589        boolean clampedX = false;
18590        if (newScrollX > right) {
18591            newScrollX = right;
18592            clampedX = true;
18593        } else if (newScrollX < left) {
18594            newScrollX = left;
18595            clampedX = true;
18596        }
18597
18598        boolean clampedY = false;
18599        if (newScrollY > bottom) {
18600            newScrollY = bottom;
18601            clampedY = true;
18602        } else if (newScrollY < top) {
18603            newScrollY = top;
18604            clampedY = true;
18605        }
18606
18607        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
18608
18609        return clampedX || clampedY;
18610    }
18611
18612    /**
18613     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
18614     * respond to the results of an over-scroll operation.
18615     *
18616     * @param scrollX New X scroll value in pixels
18617     * @param scrollY New Y scroll value in pixels
18618     * @param clampedX True if scrollX was clamped to an over-scroll boundary
18619     * @param clampedY True if scrollY was clamped to an over-scroll boundary
18620     */
18621    protected void onOverScrolled(int scrollX, int scrollY,
18622            boolean clampedX, boolean clampedY) {
18623        // Intentionally empty.
18624    }
18625
18626    /**
18627     * Returns the over-scroll mode for this view. The result will be
18628     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18629     * (allow over-scrolling only if the view content is larger than the container),
18630     * or {@link #OVER_SCROLL_NEVER}.
18631     *
18632     * @return This view's over-scroll mode.
18633     */
18634    public int getOverScrollMode() {
18635        return mOverScrollMode;
18636    }
18637
18638    /**
18639     * Set the over-scroll mode for this view. Valid over-scroll modes are
18640     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
18641     * (allow over-scrolling only if the view content is larger than the container),
18642     * or {@link #OVER_SCROLL_NEVER}.
18643     *
18644     * Setting the over-scroll mode of a view will have an effect only if the
18645     * view is capable of scrolling.
18646     *
18647     * @param overScrollMode The new over-scroll mode for this view.
18648     */
18649    public void setOverScrollMode(int overScrollMode) {
18650        if (overScrollMode != OVER_SCROLL_ALWAYS &&
18651                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
18652                overScrollMode != OVER_SCROLL_NEVER) {
18653            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
18654        }
18655        mOverScrollMode = overScrollMode;
18656    }
18657
18658    /**
18659     * Enable or disable nested scrolling for this view.
18660     *
18661     * <p>If this property is set to true the view will be permitted to initiate nested
18662     * scrolling operations with a compatible parent view in the current hierarchy. If this
18663     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
18664     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
18665     * the nested scroll.</p>
18666     *
18667     * @param enabled true to enable nested scrolling, false to disable
18668     *
18669     * @see #isNestedScrollingEnabled()
18670     */
18671    public void setNestedScrollingEnabled(boolean enabled) {
18672        if (enabled) {
18673            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
18674        } else {
18675            stopNestedScroll();
18676            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
18677        }
18678    }
18679
18680    /**
18681     * Returns true if nested scrolling is enabled for this view.
18682     *
18683     * <p>If nested scrolling is enabled and this View class implementation supports it,
18684     * this view will act as a nested scrolling child view when applicable, forwarding data
18685     * about the scroll operation in progress to a compatible and cooperating nested scrolling
18686     * parent.</p>
18687     *
18688     * @return true if nested scrolling is enabled
18689     *
18690     * @see #setNestedScrollingEnabled(boolean)
18691     */
18692    public boolean isNestedScrollingEnabled() {
18693        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
18694                PFLAG3_NESTED_SCROLLING_ENABLED;
18695    }
18696
18697    /**
18698     * Begin a nestable scroll operation along the given axes.
18699     *
18700     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
18701     *
18702     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
18703     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
18704     * In the case of touch scrolling the nested scroll will be terminated automatically in
18705     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
18706     * In the event of programmatic scrolling the caller must explicitly call
18707     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
18708     *
18709     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
18710     * If it returns false the caller may ignore the rest of this contract until the next scroll.
18711     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
18712     *
18713     * <p>At each incremental step of the scroll the caller should invoke
18714     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
18715     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
18716     * parent at least partially consumed the scroll and the caller should adjust the amount it
18717     * scrolls by.</p>
18718     *
18719     * <p>After applying the remainder of the scroll delta the caller should invoke
18720     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
18721     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
18722     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
18723     * </p>
18724     *
18725     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
18726     *             {@link #SCROLL_AXIS_VERTICAL}.
18727     * @return true if a cooperative parent was found and nested scrolling has been enabled for
18728     *         the current gesture.
18729     *
18730     * @see #stopNestedScroll()
18731     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18732     * @see #dispatchNestedScroll(int, int, int, int, int[])
18733     */
18734    public boolean startNestedScroll(int axes) {
18735        if (hasNestedScrollingParent()) {
18736            // Already in progress
18737            return true;
18738        }
18739        if (isNestedScrollingEnabled()) {
18740            ViewParent p = getParent();
18741            View child = this;
18742            while (p != null) {
18743                try {
18744                    if (p.onStartNestedScroll(child, this, axes)) {
18745                        mNestedScrollingParent = p;
18746                        p.onNestedScrollAccepted(child, this, axes);
18747                        return true;
18748                    }
18749                } catch (AbstractMethodError e) {
18750                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
18751                            "method onStartNestedScroll", e);
18752                    // Allow the search upward to continue
18753                }
18754                if (p instanceof View) {
18755                    child = (View) p;
18756                }
18757                p = p.getParent();
18758            }
18759        }
18760        return false;
18761    }
18762
18763    /**
18764     * Stop a nested scroll in progress.
18765     *
18766     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
18767     *
18768     * @see #startNestedScroll(int)
18769     */
18770    public void stopNestedScroll() {
18771        if (mNestedScrollingParent != null) {
18772            mNestedScrollingParent.onStopNestedScroll(this);
18773            mNestedScrollingParent = null;
18774        }
18775    }
18776
18777    /**
18778     * Returns true if this view has a nested scrolling parent.
18779     *
18780     * <p>The presence of a nested scrolling parent indicates that this view has initiated
18781     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
18782     *
18783     * @return whether this view has a nested scrolling parent
18784     */
18785    public boolean hasNestedScrollingParent() {
18786        return mNestedScrollingParent != null;
18787    }
18788
18789    /**
18790     * Dispatch one step of a nested scroll in progress.
18791     *
18792     * <p>Implementations of views that support nested scrolling should call this to report
18793     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
18794     * is not currently in progress or nested scrolling is not
18795     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
18796     *
18797     * <p>Compatible View implementations should also call
18798     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
18799     * consuming a component of the scroll event themselves.</p>
18800     *
18801     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
18802     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
18803     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
18804     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
18805     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18806     *                       in local view coordinates of this view from before this operation
18807     *                       to after it completes. View implementations may use this to adjust
18808     *                       expected input coordinate tracking.
18809     * @return true if the event was dispatched, false if it could not be dispatched.
18810     * @see #dispatchNestedPreScroll(int, int, int[], int[])
18811     */
18812    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
18813            int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
18814        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18815            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
18816                int startX = 0;
18817                int startY = 0;
18818                if (offsetInWindow != null) {
18819                    getLocationInWindow(offsetInWindow);
18820                    startX = offsetInWindow[0];
18821                    startY = offsetInWindow[1];
18822                }
18823
18824                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
18825                        dxUnconsumed, dyUnconsumed);
18826
18827                if (offsetInWindow != null) {
18828                    getLocationInWindow(offsetInWindow);
18829                    offsetInWindow[0] -= startX;
18830                    offsetInWindow[1] -= startY;
18831                }
18832                return true;
18833            } else if (offsetInWindow != null) {
18834                // No motion, no dispatch. Keep offsetInWindow up to date.
18835                offsetInWindow[0] = 0;
18836                offsetInWindow[1] = 0;
18837            }
18838        }
18839        return false;
18840    }
18841
18842    /**
18843     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
18844     *
18845     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
18846     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
18847     * scrolling operation to consume some or all of the scroll operation before the child view
18848     * consumes it.</p>
18849     *
18850     * @param dx Horizontal scroll distance in pixels
18851     * @param dy Vertical scroll distance in pixels
18852     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
18853     *                 and consumed[1] the consumed dy.
18854     * @param offsetInWindow Optional. If not null, on return this will contain the offset
18855     *                       in local view coordinates of this view from before this operation
18856     *                       to after it completes. View implementations may use this to adjust
18857     *                       expected input coordinate tracking.
18858     * @return true if the parent consumed some or all of the scroll delta
18859     * @see #dispatchNestedScroll(int, int, int, int, int[])
18860     */
18861    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
18862        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18863            if (dx != 0 || dy != 0) {
18864                int startX = 0;
18865                int startY = 0;
18866                if (offsetInWindow != null) {
18867                    getLocationInWindow(offsetInWindow);
18868                    startX = offsetInWindow[0];
18869                    startY = offsetInWindow[1];
18870                }
18871
18872                if (consumed == null) {
18873                    if (mTempNestedScrollConsumed == null) {
18874                        mTempNestedScrollConsumed = new int[2];
18875                    }
18876                    consumed = mTempNestedScrollConsumed;
18877                }
18878                consumed[0] = 0;
18879                consumed[1] = 0;
18880                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
18881
18882                if (offsetInWindow != null) {
18883                    getLocationInWindow(offsetInWindow);
18884                    offsetInWindow[0] -= startX;
18885                    offsetInWindow[1] -= startY;
18886                }
18887                return consumed[0] != 0 || consumed[1] != 0;
18888            } else if (offsetInWindow != null) {
18889                offsetInWindow[0] = 0;
18890                offsetInWindow[1] = 0;
18891            }
18892        }
18893        return false;
18894    }
18895
18896    /**
18897     * Dispatch a fling to a nested scrolling parent.
18898     *
18899     * <p>This method should be used to indicate that a nested scrolling child has detected
18900     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
18901     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
18902     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
18903     * along a scrollable axis.</p>
18904     *
18905     * <p>If a nested scrolling child view would normally fling but it is at the edge of
18906     * its own content, it can use this method to delegate the fling to its nested scrolling
18907     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
18908     *
18909     * @param velocityX Horizontal fling velocity in pixels per second
18910     * @param velocityY Vertical fling velocity in pixels per second
18911     * @param consumed true if the child consumed the fling, false otherwise
18912     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
18913     */
18914    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
18915        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18916            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
18917        }
18918        return false;
18919    }
18920
18921    /**
18922     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
18923     *
18924     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
18925     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
18926     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
18927     * before the child view consumes it. If this method returns <code>true</code>, a nested
18928     * parent view consumed the fling and this view should not scroll as a result.</p>
18929     *
18930     * <p>For a better user experience, only one view in a nested scrolling chain should consume
18931     * the fling at a time. If a parent view consumed the fling this method will return false.
18932     * Custom view implementations should account for this in two ways:</p>
18933     *
18934     * <ul>
18935     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
18936     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
18937     *     position regardless.</li>
18938     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
18939     *     even to settle back to a valid idle position.</li>
18940     * </ul>
18941     *
18942     * <p>Views should also not offer fling velocities to nested parent views along an axis
18943     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
18944     * should not offer a horizontal fling velocity to its parents since scrolling along that
18945     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
18946     *
18947     * @param velocityX Horizontal fling velocity in pixels per second
18948     * @param velocityY Vertical fling velocity in pixels per second
18949     * @return true if a nested scrolling parent consumed the fling
18950     */
18951    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
18952        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
18953            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
18954        }
18955        return false;
18956    }
18957
18958    /**
18959     * Gets a scale factor that determines the distance the view should scroll
18960     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
18961     * @return The vertical scroll scale factor.
18962     * @hide
18963     */
18964    protected float getVerticalScrollFactor() {
18965        if (mVerticalScrollFactor == 0) {
18966            TypedValue outValue = new TypedValue();
18967            if (!mContext.getTheme().resolveAttribute(
18968                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
18969                throw new IllegalStateException(
18970                        "Expected theme to define listPreferredItemHeight.");
18971            }
18972            mVerticalScrollFactor = outValue.getDimension(
18973                    mContext.getResources().getDisplayMetrics());
18974        }
18975        return mVerticalScrollFactor;
18976    }
18977
18978    /**
18979     * Gets a scale factor that determines the distance the view should scroll
18980     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
18981     * @return The horizontal scroll scale factor.
18982     * @hide
18983     */
18984    protected float getHorizontalScrollFactor() {
18985        // TODO: Should use something else.
18986        return getVerticalScrollFactor();
18987    }
18988
18989    /**
18990     * Return the value specifying the text direction or policy that was set with
18991     * {@link #setTextDirection(int)}.
18992     *
18993     * @return the defined text direction. It can be one of:
18994     *
18995     * {@link #TEXT_DIRECTION_INHERIT},
18996     * {@link #TEXT_DIRECTION_FIRST_STRONG}
18997     * {@link #TEXT_DIRECTION_ANY_RTL},
18998     * {@link #TEXT_DIRECTION_LTR},
18999     * {@link #TEXT_DIRECTION_RTL},
19000     * {@link #TEXT_DIRECTION_LOCALE}
19001     *
19002     * @attr ref android.R.styleable#View_textDirection
19003     *
19004     * @hide
19005     */
19006    @ViewDebug.ExportedProperty(category = "text", mapping = {
19007            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19008            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19009            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19010            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19011            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19012            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19013    })
19014    public int getRawTextDirection() {
19015        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
19016    }
19017
19018    /**
19019     * Set the text direction.
19020     *
19021     * @param textDirection the direction to set. Should be one of:
19022     *
19023     * {@link #TEXT_DIRECTION_INHERIT},
19024     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19025     * {@link #TEXT_DIRECTION_ANY_RTL},
19026     * {@link #TEXT_DIRECTION_LTR},
19027     * {@link #TEXT_DIRECTION_RTL},
19028     * {@link #TEXT_DIRECTION_LOCALE}
19029     *
19030     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
19031     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
19032     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
19033     *
19034     * @attr ref android.R.styleable#View_textDirection
19035     */
19036    public void setTextDirection(int textDirection) {
19037        if (getRawTextDirection() != textDirection) {
19038            // Reset the current text direction and the resolved one
19039            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
19040            resetResolvedTextDirection();
19041            // Set the new text direction
19042            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
19043            // Do resolution
19044            resolveTextDirection();
19045            // Notify change
19046            onRtlPropertiesChanged(getLayoutDirection());
19047            // Refresh
19048            requestLayout();
19049            invalidate(true);
19050        }
19051    }
19052
19053    /**
19054     * Return the resolved text direction.
19055     *
19056     * @return the resolved text direction. Returns one of:
19057     *
19058     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19059     * {@link #TEXT_DIRECTION_ANY_RTL},
19060     * {@link #TEXT_DIRECTION_LTR},
19061     * {@link #TEXT_DIRECTION_RTL},
19062     * {@link #TEXT_DIRECTION_LOCALE}
19063     *
19064     * @attr ref android.R.styleable#View_textDirection
19065     */
19066    @ViewDebug.ExportedProperty(category = "text", mapping = {
19067            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19068            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19069            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19070            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19071            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19072            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19073    })
19074    public int getTextDirection() {
19075        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
19076    }
19077
19078    /**
19079     * Resolve the text direction.
19080     *
19081     * @return true if resolution has been done, false otherwise.
19082     *
19083     * @hide
19084     */
19085    public boolean resolveTextDirection() {
19086        // Reset any previous text direction resolution
19087        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19088
19089        if (hasRtlSupport()) {
19090            // Set resolved text direction flag depending on text direction flag
19091            final int textDirection = getRawTextDirection();
19092            switch(textDirection) {
19093                case TEXT_DIRECTION_INHERIT:
19094                    if (!canResolveTextDirection()) {
19095                        // We cannot do the resolution if there is no parent, so use the default one
19096                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19097                        // Resolution will need to happen again later
19098                        return false;
19099                    }
19100
19101                    // Parent has not yet resolved, so we still return the default
19102                    try {
19103                        if (!mParent.isTextDirectionResolved()) {
19104                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19105                            // Resolution will need to happen again later
19106                            return false;
19107                        }
19108                    } catch (AbstractMethodError e) {
19109                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19110                                " does not fully implement ViewParent", e);
19111                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19112                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19113                        return true;
19114                    }
19115
19116                    // Set current resolved direction to the same value as the parent's one
19117                    int parentResolvedDirection;
19118                    try {
19119                        parentResolvedDirection = mParent.getTextDirection();
19120                    } catch (AbstractMethodError e) {
19121                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19122                                " does not fully implement ViewParent", e);
19123                        parentResolvedDirection = TEXT_DIRECTION_LTR;
19124                    }
19125                    switch (parentResolvedDirection) {
19126                        case TEXT_DIRECTION_FIRST_STRONG:
19127                        case TEXT_DIRECTION_ANY_RTL:
19128                        case TEXT_DIRECTION_LTR:
19129                        case TEXT_DIRECTION_RTL:
19130                        case TEXT_DIRECTION_LOCALE:
19131                            mPrivateFlags2 |=
19132                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19133                            break;
19134                        default:
19135                            // Default resolved direction is "first strong" heuristic
19136                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19137                    }
19138                    break;
19139                case TEXT_DIRECTION_FIRST_STRONG:
19140                case TEXT_DIRECTION_ANY_RTL:
19141                case TEXT_DIRECTION_LTR:
19142                case TEXT_DIRECTION_RTL:
19143                case TEXT_DIRECTION_LOCALE:
19144                    // Resolved direction is the same as text direction
19145                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19146                    break;
19147                default:
19148                    // Default resolved direction is "first strong" heuristic
19149                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19150            }
19151        } else {
19152            // Default resolved direction is "first strong" heuristic
19153            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19154        }
19155
19156        // Set to resolved
19157        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19158        return true;
19159    }
19160
19161    /**
19162     * Check if text direction resolution can be done.
19163     *
19164     * @return true if text direction resolution can be done otherwise return false.
19165     */
19166    public boolean canResolveTextDirection() {
19167        switch (getRawTextDirection()) {
19168            case TEXT_DIRECTION_INHERIT:
19169                if (mParent != null) {
19170                    try {
19171                        return mParent.canResolveTextDirection();
19172                    } catch (AbstractMethodError e) {
19173                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19174                                " does not fully implement ViewParent", e);
19175                    }
19176                }
19177                return false;
19178
19179            default:
19180                return true;
19181        }
19182    }
19183
19184    /**
19185     * Reset resolved text direction. Text direction will be resolved during a call to
19186     * {@link #onMeasure(int, int)}.
19187     *
19188     * @hide
19189     */
19190    public void resetResolvedTextDirection() {
19191        // Reset any previous text direction resolution
19192        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19193        // Set to default value
19194        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19195    }
19196
19197    /**
19198     * @return true if text direction is inherited.
19199     *
19200     * @hide
19201     */
19202    public boolean isTextDirectionInherited() {
19203        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19204    }
19205
19206    /**
19207     * @return true if text direction is resolved.
19208     */
19209    public boolean isTextDirectionResolved() {
19210        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19211    }
19212
19213    /**
19214     * Return the value specifying the text alignment or policy that was set with
19215     * {@link #setTextAlignment(int)}.
19216     *
19217     * @return the defined text alignment. It can be one of:
19218     *
19219     * {@link #TEXT_ALIGNMENT_INHERIT},
19220     * {@link #TEXT_ALIGNMENT_GRAVITY},
19221     * {@link #TEXT_ALIGNMENT_CENTER},
19222     * {@link #TEXT_ALIGNMENT_TEXT_START},
19223     * {@link #TEXT_ALIGNMENT_TEXT_END},
19224     * {@link #TEXT_ALIGNMENT_VIEW_START},
19225     * {@link #TEXT_ALIGNMENT_VIEW_END}
19226     *
19227     * @attr ref android.R.styleable#View_textAlignment
19228     *
19229     * @hide
19230     */
19231    @ViewDebug.ExportedProperty(category = "text", mapping = {
19232            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19233            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19234            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19235            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19236            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19237            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19238            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19239    })
19240    @TextAlignment
19241    public int getRawTextAlignment() {
19242        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19243    }
19244
19245    /**
19246     * Set the text alignment.
19247     *
19248     * @param textAlignment The text alignment to set. Should be one of
19249     *
19250     * {@link #TEXT_ALIGNMENT_INHERIT},
19251     * {@link #TEXT_ALIGNMENT_GRAVITY},
19252     * {@link #TEXT_ALIGNMENT_CENTER},
19253     * {@link #TEXT_ALIGNMENT_TEXT_START},
19254     * {@link #TEXT_ALIGNMENT_TEXT_END},
19255     * {@link #TEXT_ALIGNMENT_VIEW_START},
19256     * {@link #TEXT_ALIGNMENT_VIEW_END}
19257     *
19258     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19259     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19260     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19261     *
19262     * @attr ref android.R.styleable#View_textAlignment
19263     */
19264    public void setTextAlignment(@TextAlignment int textAlignment) {
19265        if (textAlignment != getRawTextAlignment()) {
19266            // Reset the current and resolved text alignment
19267            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19268            resetResolvedTextAlignment();
19269            // Set the new text alignment
19270            mPrivateFlags2 |=
19271                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19272            // Do resolution
19273            resolveTextAlignment();
19274            // Notify change
19275            onRtlPropertiesChanged(getLayoutDirection());
19276            // Refresh
19277            requestLayout();
19278            invalidate(true);
19279        }
19280    }
19281
19282    /**
19283     * Return the resolved text alignment.
19284     *
19285     * @return the resolved text alignment. Returns one of:
19286     *
19287     * {@link #TEXT_ALIGNMENT_GRAVITY},
19288     * {@link #TEXT_ALIGNMENT_CENTER},
19289     * {@link #TEXT_ALIGNMENT_TEXT_START},
19290     * {@link #TEXT_ALIGNMENT_TEXT_END},
19291     * {@link #TEXT_ALIGNMENT_VIEW_START},
19292     * {@link #TEXT_ALIGNMENT_VIEW_END}
19293     *
19294     * @attr ref android.R.styleable#View_textAlignment
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 getTextAlignment() {
19307        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
19308                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
19309    }
19310
19311    /**
19312     * Resolve the text alignment.
19313     *
19314     * @return true if resolution has been done, false otherwise.
19315     *
19316     * @hide
19317     */
19318    public boolean resolveTextAlignment() {
19319        // Reset any previous text alignment resolution
19320        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19321
19322        if (hasRtlSupport()) {
19323            // Set resolved text alignment flag depending on text alignment flag
19324            final int textAlignment = getRawTextAlignment();
19325            switch (textAlignment) {
19326                case TEXT_ALIGNMENT_INHERIT:
19327                    // Check if we can resolve the text alignment
19328                    if (!canResolveTextAlignment()) {
19329                        // We cannot do the resolution if there is no parent so use the default
19330                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19331                        // Resolution will need to happen again later
19332                        return false;
19333                    }
19334
19335                    // Parent has not yet resolved, so we still return the default
19336                    try {
19337                        if (!mParent.isTextAlignmentResolved()) {
19338                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19339                            // Resolution will need to happen again later
19340                            return false;
19341                        }
19342                    } catch (AbstractMethodError e) {
19343                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19344                                " does not fully implement ViewParent", e);
19345                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
19346                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19347                        return true;
19348                    }
19349
19350                    int parentResolvedTextAlignment;
19351                    try {
19352                        parentResolvedTextAlignment = mParent.getTextAlignment();
19353                    } catch (AbstractMethodError e) {
19354                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19355                                " does not fully implement ViewParent", e);
19356                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
19357                    }
19358                    switch (parentResolvedTextAlignment) {
19359                        case TEXT_ALIGNMENT_GRAVITY:
19360                        case TEXT_ALIGNMENT_TEXT_START:
19361                        case TEXT_ALIGNMENT_TEXT_END:
19362                        case TEXT_ALIGNMENT_CENTER:
19363                        case TEXT_ALIGNMENT_VIEW_START:
19364                        case TEXT_ALIGNMENT_VIEW_END:
19365                            // Resolved text alignment is the same as the parent resolved
19366                            // text alignment
19367                            mPrivateFlags2 |=
19368                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19369                            break;
19370                        default:
19371                            // Use default resolved text alignment
19372                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19373                    }
19374                    break;
19375                case TEXT_ALIGNMENT_GRAVITY:
19376                case TEXT_ALIGNMENT_TEXT_START:
19377                case TEXT_ALIGNMENT_TEXT_END:
19378                case TEXT_ALIGNMENT_CENTER:
19379                case TEXT_ALIGNMENT_VIEW_START:
19380                case TEXT_ALIGNMENT_VIEW_END:
19381                    // Resolved text alignment is the same as text alignment
19382                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19383                    break;
19384                default:
19385                    // Use default resolved text alignment
19386                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19387            }
19388        } else {
19389            // Use default resolved text alignment
19390            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19391        }
19392
19393        // Set the resolved
19394        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19395        return true;
19396    }
19397
19398    /**
19399     * Check if text alignment resolution can be done.
19400     *
19401     * @return true if text alignment resolution can be done otherwise return false.
19402     */
19403    public boolean canResolveTextAlignment() {
19404        switch (getRawTextAlignment()) {
19405            case TEXT_DIRECTION_INHERIT:
19406                if (mParent != null) {
19407                    try {
19408                        return mParent.canResolveTextAlignment();
19409                    } catch (AbstractMethodError e) {
19410                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19411                                " does not fully implement ViewParent", e);
19412                    }
19413                }
19414                return false;
19415
19416            default:
19417                return true;
19418        }
19419    }
19420
19421    /**
19422     * Reset resolved text alignment. Text alignment will be resolved during a call to
19423     * {@link #onMeasure(int, int)}.
19424     *
19425     * @hide
19426     */
19427    public void resetResolvedTextAlignment() {
19428        // Reset any previous text alignment resolution
19429        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19430        // Set to default
19431        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19432    }
19433
19434    /**
19435     * @return true if text alignment is inherited.
19436     *
19437     * @hide
19438     */
19439    public boolean isTextAlignmentInherited() {
19440        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
19441    }
19442
19443    /**
19444     * @return true if text alignment is resolved.
19445     */
19446    public boolean isTextAlignmentResolved() {
19447        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19448    }
19449
19450    /**
19451     * Generate a value suitable for use in {@link #setId(int)}.
19452     * This value will not collide with ID values generated at build time by aapt for R.id.
19453     *
19454     * @return a generated ID value
19455     */
19456    public static int generateViewId() {
19457        for (;;) {
19458            final int result = sNextGeneratedId.get();
19459            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
19460            int newValue = result + 1;
19461            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
19462            if (sNextGeneratedId.compareAndSet(result, newValue)) {
19463                return result;
19464            }
19465        }
19466    }
19467
19468    /**
19469     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
19470     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
19471     *                           a normal View or a ViewGroup with
19472     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
19473     * @hide
19474     */
19475    public void captureTransitioningViews(List<View> transitioningViews) {
19476        if (getVisibility() == View.VISIBLE) {
19477            transitioningViews.add(this);
19478        }
19479    }
19480
19481    /**
19482     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
19483     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
19484     * @hide
19485     */
19486    public void findNamedViews(Map<String, View> namedElements) {
19487        if (getVisibility() == VISIBLE || mGhostView != null) {
19488            String transitionName = getTransitionName();
19489            if (transitionName != null) {
19490                namedElements.put(transitionName, this);
19491            }
19492        }
19493    }
19494
19495    //
19496    // Properties
19497    //
19498    /**
19499     * A Property wrapper around the <code>alpha</code> functionality handled by the
19500     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
19501     */
19502    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
19503        @Override
19504        public void setValue(View object, float value) {
19505            object.setAlpha(value);
19506        }
19507
19508        @Override
19509        public Float get(View object) {
19510            return object.getAlpha();
19511        }
19512    };
19513
19514    /**
19515     * A Property wrapper around the <code>translationX</code> functionality handled by the
19516     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
19517     */
19518    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
19519        @Override
19520        public void setValue(View object, float value) {
19521            object.setTranslationX(value);
19522        }
19523
19524                @Override
19525        public Float get(View object) {
19526            return object.getTranslationX();
19527        }
19528    };
19529
19530    /**
19531     * A Property wrapper around the <code>translationY</code> functionality handled by the
19532     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
19533     */
19534    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
19535        @Override
19536        public void setValue(View object, float value) {
19537            object.setTranslationY(value);
19538        }
19539
19540        @Override
19541        public Float get(View object) {
19542            return object.getTranslationY();
19543        }
19544    };
19545
19546    /**
19547     * A Property wrapper around the <code>translationZ</code> functionality handled by the
19548     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
19549     */
19550    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
19551        @Override
19552        public void setValue(View object, float value) {
19553            object.setTranslationZ(value);
19554        }
19555
19556        @Override
19557        public Float get(View object) {
19558            return object.getTranslationZ();
19559        }
19560    };
19561
19562    /**
19563     * A Property wrapper around the <code>x</code> functionality handled by the
19564     * {@link View#setX(float)} and {@link View#getX()} methods.
19565     */
19566    public static final Property<View, Float> X = new FloatProperty<View>("x") {
19567        @Override
19568        public void setValue(View object, float value) {
19569            object.setX(value);
19570        }
19571
19572        @Override
19573        public Float get(View object) {
19574            return object.getX();
19575        }
19576    };
19577
19578    /**
19579     * A Property wrapper around the <code>y</code> functionality handled by the
19580     * {@link View#setY(float)} and {@link View#getY()} methods.
19581     */
19582    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
19583        @Override
19584        public void setValue(View object, float value) {
19585            object.setY(value);
19586        }
19587
19588        @Override
19589        public Float get(View object) {
19590            return object.getY();
19591        }
19592    };
19593
19594    /**
19595     * A Property wrapper around the <code>z</code> functionality handled by the
19596     * {@link View#setZ(float)} and {@link View#getZ()} methods.
19597     */
19598    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
19599        @Override
19600        public void setValue(View object, float value) {
19601            object.setZ(value);
19602        }
19603
19604        @Override
19605        public Float get(View object) {
19606            return object.getZ();
19607        }
19608    };
19609
19610    /**
19611     * A Property wrapper around the <code>rotation</code> functionality handled by the
19612     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
19613     */
19614    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
19615        @Override
19616        public void setValue(View object, float value) {
19617            object.setRotation(value);
19618        }
19619
19620        @Override
19621        public Float get(View object) {
19622            return object.getRotation();
19623        }
19624    };
19625
19626    /**
19627     * A Property wrapper around the <code>rotationX</code> functionality handled by the
19628     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
19629     */
19630    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
19631        @Override
19632        public void setValue(View object, float value) {
19633            object.setRotationX(value);
19634        }
19635
19636        @Override
19637        public Float get(View object) {
19638            return object.getRotationX();
19639        }
19640    };
19641
19642    /**
19643     * A Property wrapper around the <code>rotationY</code> functionality handled by the
19644     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
19645     */
19646    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
19647        @Override
19648        public void setValue(View object, float value) {
19649            object.setRotationY(value);
19650        }
19651
19652        @Override
19653        public Float get(View object) {
19654            return object.getRotationY();
19655        }
19656    };
19657
19658    /**
19659     * A Property wrapper around the <code>scaleX</code> functionality handled by the
19660     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
19661     */
19662    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
19663        @Override
19664        public void setValue(View object, float value) {
19665            object.setScaleX(value);
19666        }
19667
19668        @Override
19669        public Float get(View object) {
19670            return object.getScaleX();
19671        }
19672    };
19673
19674    /**
19675     * A Property wrapper around the <code>scaleY</code> functionality handled by the
19676     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
19677     */
19678    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
19679        @Override
19680        public void setValue(View object, float value) {
19681            object.setScaleY(value);
19682        }
19683
19684        @Override
19685        public Float get(View object) {
19686            return object.getScaleY();
19687        }
19688    };
19689
19690    /**
19691     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
19692     * Each MeasureSpec represents a requirement for either the width or the height.
19693     * A MeasureSpec is comprised of a size and a mode. There are three possible
19694     * modes:
19695     * <dl>
19696     * <dt>UNSPECIFIED</dt>
19697     * <dd>
19698     * The parent has not imposed any constraint on the child. It can be whatever size
19699     * it wants.
19700     * </dd>
19701     *
19702     * <dt>EXACTLY</dt>
19703     * <dd>
19704     * The parent has determined an exact size for the child. The child is going to be
19705     * given those bounds regardless of how big it wants to be.
19706     * </dd>
19707     *
19708     * <dt>AT_MOST</dt>
19709     * <dd>
19710     * The child can be as large as it wants up to the specified size.
19711     * </dd>
19712     * </dl>
19713     *
19714     * MeasureSpecs are implemented as ints to reduce object allocation. This class
19715     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
19716     */
19717    public static class MeasureSpec {
19718        private static final int MODE_SHIFT = 30;
19719        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
19720
19721        /**
19722         * Measure specification mode: The parent has not imposed any constraint
19723         * on the child. It can be whatever size it wants.
19724         */
19725        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
19726
19727        /**
19728         * Measure specification mode: The parent has determined an exact size
19729         * for the child. The child is going to be given those bounds regardless
19730         * of how big it wants to be.
19731         */
19732        public static final int EXACTLY     = 1 << MODE_SHIFT;
19733
19734        /**
19735         * Measure specification mode: The child can be as large as it wants up
19736         * to the specified size.
19737         */
19738        public static final int AT_MOST     = 2 << MODE_SHIFT;
19739
19740        /**
19741         * Creates a measure specification based on the supplied size and mode.
19742         *
19743         * The mode must always be one of the following:
19744         * <ul>
19745         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
19746         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
19747         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
19748         * </ul>
19749         *
19750         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
19751         * implementation was such that the order of arguments did not matter
19752         * and overflow in either value could impact the resulting MeasureSpec.
19753         * {@link android.widget.RelativeLayout} was affected by this bug.
19754         * Apps targeting API levels greater than 17 will get the fixed, more strict
19755         * behavior.</p>
19756         *
19757         * @param size the size of the measure specification
19758         * @param mode the mode of the measure specification
19759         * @return the measure specification based on size and mode
19760         */
19761        public static int makeMeasureSpec(int size, int mode) {
19762            if (sUseBrokenMakeMeasureSpec) {
19763                return size + mode;
19764            } else {
19765                return (size & ~MODE_MASK) | (mode & MODE_MASK);
19766            }
19767        }
19768
19769        /**
19770         * Extracts the mode from the supplied measure specification.
19771         *
19772         * @param measureSpec the measure specification to extract the mode from
19773         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
19774         *         {@link android.view.View.MeasureSpec#AT_MOST} or
19775         *         {@link android.view.View.MeasureSpec#EXACTLY}
19776         */
19777        public static int getMode(int measureSpec) {
19778            return (measureSpec & MODE_MASK);
19779        }
19780
19781        /**
19782         * Extracts the size from the supplied measure specification.
19783         *
19784         * @param measureSpec the measure specification to extract the size from
19785         * @return the size in pixels defined in the supplied measure specification
19786         */
19787        public static int getSize(int measureSpec) {
19788            return (measureSpec & ~MODE_MASK);
19789        }
19790
19791        static int adjust(int measureSpec, int delta) {
19792            final int mode = getMode(measureSpec);
19793            if (mode == UNSPECIFIED) {
19794                // No need to adjust size for UNSPECIFIED mode.
19795                return makeMeasureSpec(0, UNSPECIFIED);
19796            }
19797            int size = getSize(measureSpec) + delta;
19798            if (size < 0) {
19799                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
19800                        ") spec: " + toString(measureSpec) + " delta: " + delta);
19801                size = 0;
19802            }
19803            return makeMeasureSpec(size, mode);
19804        }
19805
19806        /**
19807         * Returns a String representation of the specified measure
19808         * specification.
19809         *
19810         * @param measureSpec the measure specification to convert to a String
19811         * @return a String with the following format: "MeasureSpec: MODE SIZE"
19812         */
19813        public static String toString(int measureSpec) {
19814            int mode = getMode(measureSpec);
19815            int size = getSize(measureSpec);
19816
19817            StringBuilder sb = new StringBuilder("MeasureSpec: ");
19818
19819            if (mode == UNSPECIFIED)
19820                sb.append("UNSPECIFIED ");
19821            else if (mode == EXACTLY)
19822                sb.append("EXACTLY ");
19823            else if (mode == AT_MOST)
19824                sb.append("AT_MOST ");
19825            else
19826                sb.append(mode).append(" ");
19827
19828            sb.append(size);
19829            return sb.toString();
19830        }
19831    }
19832
19833    private final class CheckForLongPress implements Runnable {
19834        private int mOriginalWindowAttachCount;
19835
19836        @Override
19837        public void run() {
19838            if (isPressed() && (mParent != null)
19839                    && mOriginalWindowAttachCount == mWindowAttachCount) {
19840                if (performLongClick()) {
19841                    mHasPerformedLongPress = true;
19842                }
19843            }
19844        }
19845
19846        public void rememberWindowAttachCount() {
19847            mOriginalWindowAttachCount = mWindowAttachCount;
19848        }
19849    }
19850
19851    private final class CheckForTap implements Runnable {
19852        public float x;
19853        public float y;
19854
19855        @Override
19856        public void run() {
19857            mPrivateFlags &= ~PFLAG_PREPRESSED;
19858            setPressed(true, x, y);
19859            checkForLongClick(ViewConfiguration.getTapTimeout());
19860        }
19861    }
19862
19863    private final class PerformClick implements Runnable {
19864        @Override
19865        public void run() {
19866            performClick();
19867        }
19868    }
19869
19870    /** @hide */
19871    public void hackTurnOffWindowResizeAnim(boolean off) {
19872        mAttachInfo.mTurnOffWindowResizeAnim = off;
19873    }
19874
19875    /**
19876     * This method returns a ViewPropertyAnimator object, which can be used to animate
19877     * specific properties on this View.
19878     *
19879     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
19880     */
19881    public ViewPropertyAnimator animate() {
19882        if (mAnimator == null) {
19883            mAnimator = new ViewPropertyAnimator(this);
19884        }
19885        return mAnimator;
19886    }
19887
19888    /**
19889     * Sets the name of the View to be used to identify Views in Transitions.
19890     * Names should be unique in the View hierarchy.
19891     *
19892     * @param transitionName The name of the View to uniquely identify it for Transitions.
19893     */
19894    public final void setTransitionName(String transitionName) {
19895        mTransitionName = transitionName;
19896    }
19897
19898    /**
19899     * Returns the name of the View to be used to identify Views in Transitions.
19900     * Names should be unique in the View hierarchy.
19901     *
19902     * <p>This returns null if the View has not been given a name.</p>
19903     *
19904     * @return The name used of the View to be used to identify Views in Transitions or null
19905     * if no name has been given.
19906     */
19907    @ViewDebug.ExportedProperty
19908    public String getTransitionName() {
19909        return mTransitionName;
19910    }
19911
19912    /**
19913     * Interface definition for a callback to be invoked when a hardware key event is
19914     * dispatched to this view. The callback will be invoked before the key event is
19915     * given to the view. This is only useful for hardware keyboards; a software input
19916     * method has no obligation to trigger this listener.
19917     */
19918    public interface OnKeyListener {
19919        /**
19920         * Called when a hardware key is dispatched to a view. This allows listeners to
19921         * get a chance to respond before the target view.
19922         * <p>Key presses in software keyboards will generally NOT trigger this method,
19923         * although some may elect to do so in some situations. Do not assume a
19924         * software input method has to be key-based; even if it is, it may use key presses
19925         * in a different way than you expect, so there is no way to reliably catch soft
19926         * input key presses.
19927         *
19928         * @param v The view the key has been dispatched to.
19929         * @param keyCode The code for the physical key that was pressed
19930         * @param event The KeyEvent object containing full information about
19931         *        the event.
19932         * @return True if the listener has consumed the event, false otherwise.
19933         */
19934        boolean onKey(View v, int keyCode, KeyEvent event);
19935    }
19936
19937    /**
19938     * Interface definition for a callback to be invoked when a touch event is
19939     * dispatched to this view. The callback will be invoked before the touch
19940     * event is given to the view.
19941     */
19942    public interface OnTouchListener {
19943        /**
19944         * Called when a touch event is dispatched to a view. This allows listeners to
19945         * get a chance to respond before the target view.
19946         *
19947         * @param v The view the touch event has been dispatched to.
19948         * @param event The MotionEvent object containing full information about
19949         *        the event.
19950         * @return True if the listener has consumed the event, false otherwise.
19951         */
19952        boolean onTouch(View v, MotionEvent event);
19953    }
19954
19955    /**
19956     * Interface definition for a callback to be invoked when a hover event is
19957     * dispatched to this view. The callback will be invoked before the hover
19958     * event is given to the view.
19959     */
19960    public interface OnHoverListener {
19961        /**
19962         * Called when a hover event is dispatched to a view. This allows listeners to
19963         * get a chance to respond before the target view.
19964         *
19965         * @param v The view the hover event has been dispatched to.
19966         * @param event The MotionEvent object containing full information about
19967         *        the event.
19968         * @return True if the listener has consumed the event, false otherwise.
19969         */
19970        boolean onHover(View v, MotionEvent event);
19971    }
19972
19973    /**
19974     * Interface definition for a callback to be invoked when a generic motion event is
19975     * dispatched to this view. The callback will be invoked before the generic motion
19976     * event is given to the view.
19977     */
19978    public interface OnGenericMotionListener {
19979        /**
19980         * Called when a generic motion event is dispatched to a view. This allows listeners to
19981         * get a chance to respond before the target view.
19982         *
19983         * @param v The view the generic motion event has been dispatched to.
19984         * @param event The MotionEvent object containing full information about
19985         *        the event.
19986         * @return True if the listener has consumed the event, false otherwise.
19987         */
19988        boolean onGenericMotion(View v, MotionEvent event);
19989    }
19990
19991    /**
19992     * Interface definition for a callback to be invoked when a view has been clicked and held.
19993     */
19994    public interface OnLongClickListener {
19995        /**
19996         * Called when a view has been clicked and held.
19997         *
19998         * @param v The view that was clicked and held.
19999         *
20000         * @return true if the callback consumed the long click, false otherwise.
20001         */
20002        boolean onLongClick(View v);
20003    }
20004
20005    /**
20006     * Interface definition for a callback to be invoked when a drag is being dispatched
20007     * to this view.  The callback will be invoked before the hosting view's own
20008     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
20009     * onDrag(event) behavior, it should return 'false' from this callback.
20010     *
20011     * <div class="special reference">
20012     * <h3>Developer Guides</h3>
20013     * <p>For a guide to implementing drag and drop features, read the
20014     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20015     * </div>
20016     */
20017    public interface OnDragListener {
20018        /**
20019         * Called when a drag event is dispatched to a view. This allows listeners
20020         * to get a chance to override base View behavior.
20021         *
20022         * @param v The View that received the drag event.
20023         * @param event The {@link android.view.DragEvent} object for the drag event.
20024         * @return {@code true} if the drag event was handled successfully, or {@code false}
20025         * if the drag event was not handled. Note that {@code false} will trigger the View
20026         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
20027         */
20028        boolean onDrag(View v, DragEvent event);
20029    }
20030
20031    /**
20032     * Interface definition for a callback to be invoked when the focus state of
20033     * a view changed.
20034     */
20035    public interface OnFocusChangeListener {
20036        /**
20037         * Called when the focus state of a view has changed.
20038         *
20039         * @param v The view whose state has changed.
20040         * @param hasFocus The new focus state of v.
20041         */
20042        void onFocusChange(View v, boolean hasFocus);
20043    }
20044
20045    /**
20046     * Interface definition for a callback to be invoked when a view is clicked.
20047     */
20048    public interface OnClickListener {
20049        /**
20050         * Called when a view has been clicked.
20051         *
20052         * @param v The view that was clicked.
20053         */
20054        void onClick(View v);
20055    }
20056
20057    /**
20058     * Interface definition for a callback to be invoked when the context menu
20059     * for this view is being built.
20060     */
20061    public interface OnCreateContextMenuListener {
20062        /**
20063         * Called when the context menu for this view is being built. It is not
20064         * safe to hold onto the menu after this method returns.
20065         *
20066         * @param menu The context menu that is being built
20067         * @param v The view for which the context menu is being built
20068         * @param menuInfo Extra information about the item for which the
20069         *            context menu should be shown. This information will vary
20070         *            depending on the class of v.
20071         */
20072        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
20073    }
20074
20075    /**
20076     * Interface definition for a callback to be invoked when the status bar changes
20077     * visibility.  This reports <strong>global</strong> changes to the system UI
20078     * state, not what the application is requesting.
20079     *
20080     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
20081     */
20082    public interface OnSystemUiVisibilityChangeListener {
20083        /**
20084         * Called when the status bar changes visibility because of a call to
20085         * {@link View#setSystemUiVisibility(int)}.
20086         *
20087         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20088         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
20089         * This tells you the <strong>global</strong> state of these UI visibility
20090         * flags, not what your app is currently applying.
20091         */
20092        public void onSystemUiVisibilityChange(int visibility);
20093    }
20094
20095    /**
20096     * Interface definition for a callback to be invoked when this view is attached
20097     * or detached from its window.
20098     */
20099    public interface OnAttachStateChangeListener {
20100        /**
20101         * Called when the view is attached to a window.
20102         * @param v The view that was attached
20103         */
20104        public void onViewAttachedToWindow(View v);
20105        /**
20106         * Called when the view is detached from a window.
20107         * @param v The view that was detached
20108         */
20109        public void onViewDetachedFromWindow(View v);
20110    }
20111
20112    /**
20113     * Listener for applying window insets on a view in a custom way.
20114     *
20115     * <p>Apps may choose to implement this interface if they want to apply custom policy
20116     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20117     * is set, its
20118     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20119     * method will be called instead of the View's own
20120     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20121     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20122     * the View's normal behavior as part of its own.</p>
20123     */
20124    public interface OnApplyWindowInsetsListener {
20125        /**
20126         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20127         * on a View, this listener method will be called instead of the view's own
20128         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20129         *
20130         * @param v The view applying window insets
20131         * @param insets The insets to apply
20132         * @return The insets supplied, minus any insets that were consumed
20133         */
20134        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20135    }
20136
20137    private final class UnsetPressedState implements Runnable {
20138        @Override
20139        public void run() {
20140            setPressed(false);
20141        }
20142    }
20143
20144    /**
20145     * Base class for derived classes that want to save and restore their own
20146     * state in {@link android.view.View#onSaveInstanceState()}.
20147     */
20148    public static class BaseSavedState extends AbsSavedState {
20149        /**
20150         * Constructor used when reading from a parcel. Reads the state of the superclass.
20151         *
20152         * @param source
20153         */
20154        public BaseSavedState(Parcel source) {
20155            super(source);
20156        }
20157
20158        /**
20159         * Constructor called by derived classes when creating their SavedState objects
20160         *
20161         * @param superState The state of the superclass of this view
20162         */
20163        public BaseSavedState(Parcelable superState) {
20164            super(superState);
20165        }
20166
20167        public static final Parcelable.Creator<BaseSavedState> CREATOR =
20168                new Parcelable.Creator<BaseSavedState>() {
20169            public BaseSavedState createFromParcel(Parcel in) {
20170                return new BaseSavedState(in);
20171            }
20172
20173            public BaseSavedState[] newArray(int size) {
20174                return new BaseSavedState[size];
20175            }
20176        };
20177    }
20178
20179    /**
20180     * A set of information given to a view when it is attached to its parent
20181     * window.
20182     */
20183    final static class AttachInfo {
20184        interface Callbacks {
20185            void playSoundEffect(int effectId);
20186            boolean performHapticFeedback(int effectId, boolean always);
20187        }
20188
20189        /**
20190         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20191         * to a Handler. This class contains the target (View) to invalidate and
20192         * the coordinates of the dirty rectangle.
20193         *
20194         * For performance purposes, this class also implements a pool of up to
20195         * POOL_LIMIT objects that get reused. This reduces memory allocations
20196         * whenever possible.
20197         */
20198        static class InvalidateInfo {
20199            private static final int POOL_LIMIT = 10;
20200
20201            private static final SynchronizedPool<InvalidateInfo> sPool =
20202                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20203
20204            View target;
20205
20206            int left;
20207            int top;
20208            int right;
20209            int bottom;
20210
20211            public static InvalidateInfo obtain() {
20212                InvalidateInfo instance = sPool.acquire();
20213                return (instance != null) ? instance : new InvalidateInfo();
20214            }
20215
20216            public void recycle() {
20217                target = null;
20218                sPool.release(this);
20219            }
20220        }
20221
20222        final IWindowSession mSession;
20223
20224        final IWindow mWindow;
20225
20226        final IBinder mWindowToken;
20227
20228        final Display mDisplay;
20229
20230        final Callbacks mRootCallbacks;
20231
20232        IWindowId mIWindowId;
20233        WindowId mWindowId;
20234
20235        /**
20236         * The top view of the hierarchy.
20237         */
20238        View mRootView;
20239
20240        IBinder mPanelParentWindowToken;
20241
20242        boolean mHardwareAccelerated;
20243        boolean mHardwareAccelerationRequested;
20244        HardwareRenderer mHardwareRenderer;
20245        List<RenderNode> mPendingAnimatingRenderNodes;
20246
20247        /**
20248         * The state of the display to which the window is attached, as reported
20249         * by {@link Display#getState()}.  Note that the display state constants
20250         * declared by {@link Display} do not exactly line up with the screen state
20251         * constants declared by {@link View} (there are more display states than
20252         * screen states).
20253         */
20254        int mDisplayState = Display.STATE_UNKNOWN;
20255
20256        /**
20257         * Scale factor used by the compatibility mode
20258         */
20259        float mApplicationScale;
20260
20261        /**
20262         * Indicates whether the application is in compatibility mode
20263         */
20264        boolean mScalingRequired;
20265
20266        /**
20267         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20268         */
20269        boolean mTurnOffWindowResizeAnim;
20270
20271        /**
20272         * Left position of this view's window
20273         */
20274        int mWindowLeft;
20275
20276        /**
20277         * Top position of this view's window
20278         */
20279        int mWindowTop;
20280
20281        /**
20282         * Indicates whether views need to use 32-bit drawing caches
20283         */
20284        boolean mUse32BitDrawingCache;
20285
20286        /**
20287         * For windows that are full-screen but using insets to layout inside
20288         * of the screen areas, these are the current insets to appear inside
20289         * the overscan area of the display.
20290         */
20291        final Rect mOverscanInsets = new Rect();
20292
20293        /**
20294         * For windows that are full-screen but using insets to layout inside
20295         * of the screen decorations, these are the current insets for the
20296         * content of the window.
20297         */
20298        final Rect mContentInsets = new Rect();
20299
20300        /**
20301         * For windows that are full-screen but using insets to layout inside
20302         * of the screen decorations, these are the current insets for the
20303         * actual visible parts of the window.
20304         */
20305        final Rect mVisibleInsets = new Rect();
20306
20307        /**
20308         * For windows that are full-screen but using insets to layout inside
20309         * of the screen decorations, these are the current insets for the
20310         * stable system windows.
20311         */
20312        final Rect mStableInsets = new Rect();
20313
20314        /**
20315         * The internal insets given by this window.  This value is
20316         * supplied by the client (through
20317         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
20318         * be given to the window manager when changed to be used in laying
20319         * out windows behind it.
20320         */
20321        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
20322                = new ViewTreeObserver.InternalInsetsInfo();
20323
20324        /**
20325         * Set to true when mGivenInternalInsets is non-empty.
20326         */
20327        boolean mHasNonEmptyGivenInternalInsets;
20328
20329        /**
20330         * All views in the window's hierarchy that serve as scroll containers,
20331         * used to determine if the window can be resized or must be panned
20332         * to adjust for a soft input area.
20333         */
20334        final ArrayList<View> mScrollContainers = new ArrayList<View>();
20335
20336        final KeyEvent.DispatcherState mKeyDispatchState
20337                = new KeyEvent.DispatcherState();
20338
20339        /**
20340         * Indicates whether the view's window currently has the focus.
20341         */
20342        boolean mHasWindowFocus;
20343
20344        /**
20345         * The current visibility of the window.
20346         */
20347        int mWindowVisibility;
20348
20349        /**
20350         * Indicates the time at which drawing started to occur.
20351         */
20352        long mDrawingTime;
20353
20354        /**
20355         * Indicates whether or not ignoring the DIRTY_MASK flags.
20356         */
20357        boolean mIgnoreDirtyState;
20358
20359        /**
20360         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
20361         * to avoid clearing that flag prematurely.
20362         */
20363        boolean mSetIgnoreDirtyState = false;
20364
20365        /**
20366         * Indicates whether the view's window is currently in touch mode.
20367         */
20368        boolean mInTouchMode;
20369
20370        /**
20371         * Indicates whether the view has requested unbuffered input dispatching for the current
20372         * event stream.
20373         */
20374        boolean mUnbufferedDispatchRequested;
20375
20376        /**
20377         * Indicates that ViewAncestor should trigger a global layout change
20378         * the next time it performs a traversal
20379         */
20380        boolean mRecomputeGlobalAttributes;
20381
20382        /**
20383         * Always report new attributes at next traversal.
20384         */
20385        boolean mForceReportNewAttributes;
20386
20387        /**
20388         * Set during a traveral if any views want to keep the screen on.
20389         */
20390        boolean mKeepScreenOn;
20391
20392        /**
20393         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
20394         */
20395        int mSystemUiVisibility;
20396
20397        /**
20398         * Hack to force certain system UI visibility flags to be cleared.
20399         */
20400        int mDisabledSystemUiVisibility;
20401
20402        /**
20403         * Last global system UI visibility reported by the window manager.
20404         */
20405        int mGlobalSystemUiVisibility;
20406
20407        /**
20408         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
20409         * attached.
20410         */
20411        boolean mHasSystemUiListeners;
20412
20413        /**
20414         * Set if the window has requested to extend into the overscan region
20415         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
20416         */
20417        boolean mOverscanRequested;
20418
20419        /**
20420         * Set if the visibility of any views has changed.
20421         */
20422        boolean mViewVisibilityChanged;
20423
20424        /**
20425         * Set to true if a view has been scrolled.
20426         */
20427        boolean mViewScrollChanged;
20428
20429        /**
20430         * Set to true if high contrast mode enabled
20431         */
20432        boolean mHighContrastText;
20433
20434        /**
20435         * Global to the view hierarchy used as a temporary for dealing with
20436         * x/y points in the transparent region computations.
20437         */
20438        final int[] mTransparentLocation = new int[2];
20439
20440        /**
20441         * Global to the view hierarchy used as a temporary for dealing with
20442         * x/y points in the ViewGroup.invalidateChild implementation.
20443         */
20444        final int[] mInvalidateChildLocation = new int[2];
20445
20446        /**
20447         * Global to the view hierarchy used as a temporary for dealng with
20448         * computing absolute on-screen location.
20449         */
20450        final int[] mTmpLocation = new int[2];
20451
20452        /**
20453         * Global to the view hierarchy used as a temporary for dealing with
20454         * x/y location when view is transformed.
20455         */
20456        final float[] mTmpTransformLocation = new float[2];
20457
20458        /**
20459         * The view tree observer used to dispatch global events like
20460         * layout, pre-draw, touch mode change, etc.
20461         */
20462        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
20463
20464        /**
20465         * A Canvas used by the view hierarchy to perform bitmap caching.
20466         */
20467        Canvas mCanvas;
20468
20469        /**
20470         * The view root impl.
20471         */
20472        final ViewRootImpl mViewRootImpl;
20473
20474        /**
20475         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
20476         * handler can be used to pump events in the UI events queue.
20477         */
20478        final Handler mHandler;
20479
20480        /**
20481         * Temporary for use in computing invalidate rectangles while
20482         * calling up the hierarchy.
20483         */
20484        final Rect mTmpInvalRect = new Rect();
20485
20486        /**
20487         * Temporary for use in computing hit areas with transformed views
20488         */
20489        final RectF mTmpTransformRect = new RectF();
20490
20491        /**
20492         * Temporary for use in computing hit areas with transformed views
20493         */
20494        final RectF mTmpTransformRect1 = new RectF();
20495
20496        /**
20497         * Temporary list of rectanges.
20498         */
20499        final List<RectF> mTmpRectList = new ArrayList<>();
20500
20501        /**
20502         * Temporary for use in transforming invalidation rect
20503         */
20504        final Matrix mTmpMatrix = new Matrix();
20505
20506        /**
20507         * Temporary for use in transforming invalidation rect
20508         */
20509        final Transformation mTmpTransformation = new Transformation();
20510
20511        /**
20512         * Temporary for use in querying outlines from OutlineProviders
20513         */
20514        final Outline mTmpOutline = new Outline();
20515
20516        /**
20517         * Temporary list for use in collecting focusable descendents of a view.
20518         */
20519        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
20520
20521        /**
20522         * The id of the window for accessibility purposes.
20523         */
20524        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
20525
20526        /**
20527         * Flags related to accessibility processing.
20528         *
20529         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
20530         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
20531         */
20532        int mAccessibilityFetchFlags;
20533
20534        /**
20535         * The drawable for highlighting accessibility focus.
20536         */
20537        Drawable mAccessibilityFocusDrawable;
20538
20539        /**
20540         * Show where the margins, bounds and layout bounds are for each view.
20541         */
20542        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
20543
20544        /**
20545         * Point used to compute visible regions.
20546         */
20547        final Point mPoint = new Point();
20548
20549        /**
20550         * Used to track which View originated a requestLayout() call, used when
20551         * requestLayout() is called during layout.
20552         */
20553        View mViewRequestingLayout;
20554
20555        /**
20556         * Creates a new set of attachment information with the specified
20557         * events handler and thread.
20558         *
20559         * @param handler the events handler the view must use
20560         */
20561        AttachInfo(IWindowSession session, IWindow window, Display display,
20562                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
20563            mSession = session;
20564            mWindow = window;
20565            mWindowToken = window.asBinder();
20566            mDisplay = display;
20567            mViewRootImpl = viewRootImpl;
20568            mHandler = handler;
20569            mRootCallbacks = effectPlayer;
20570        }
20571    }
20572
20573    /**
20574     * <p>ScrollabilityCache holds various fields used by a View when scrolling
20575     * is supported. This avoids keeping too many unused fields in most
20576     * instances of View.</p>
20577     */
20578    private static class ScrollabilityCache implements Runnable {
20579
20580        /**
20581         * Scrollbars are not visible
20582         */
20583        public static final int OFF = 0;
20584
20585        /**
20586         * Scrollbars are visible
20587         */
20588        public static final int ON = 1;
20589
20590        /**
20591         * Scrollbars are fading away
20592         */
20593        public static final int FADING = 2;
20594
20595        public boolean fadeScrollBars;
20596
20597        public int fadingEdgeLength;
20598        public int scrollBarDefaultDelayBeforeFade;
20599        public int scrollBarFadeDuration;
20600
20601        public int scrollBarSize;
20602        public ScrollBarDrawable scrollBar;
20603        public float[] interpolatorValues;
20604        public View host;
20605
20606        public final Paint paint;
20607        public final Matrix matrix;
20608        public Shader shader;
20609
20610        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
20611
20612        private static final float[] OPAQUE = { 255 };
20613        private static final float[] TRANSPARENT = { 0.0f };
20614
20615        /**
20616         * When fading should start. This time moves into the future every time
20617         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
20618         */
20619        public long fadeStartTime;
20620
20621
20622        /**
20623         * The current state of the scrollbars: ON, OFF, or FADING
20624         */
20625        public int state = OFF;
20626
20627        private int mLastColor;
20628
20629        public ScrollabilityCache(ViewConfiguration configuration, View host) {
20630            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
20631            scrollBarSize = configuration.getScaledScrollBarSize();
20632            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
20633            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
20634
20635            paint = new Paint();
20636            matrix = new Matrix();
20637            // use use a height of 1, and then wack the matrix each time we
20638            // actually use it.
20639            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20640            paint.setShader(shader);
20641            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20642
20643            this.host = host;
20644        }
20645
20646        public void setFadeColor(int color) {
20647            if (color != mLastColor) {
20648                mLastColor = color;
20649
20650                if (color != 0) {
20651                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
20652                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
20653                    paint.setShader(shader);
20654                    // Restore the default transfer mode (src_over)
20655                    paint.setXfermode(null);
20656                } else {
20657                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
20658                    paint.setShader(shader);
20659                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
20660                }
20661            }
20662        }
20663
20664        public void run() {
20665            long now = AnimationUtils.currentAnimationTimeMillis();
20666            if (now >= fadeStartTime) {
20667
20668                // the animation fades the scrollbars out by changing
20669                // the opacity (alpha) from fully opaque to fully
20670                // transparent
20671                int nextFrame = (int) now;
20672                int framesCount = 0;
20673
20674                Interpolator interpolator = scrollBarInterpolator;
20675
20676                // Start opaque
20677                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
20678
20679                // End transparent
20680                nextFrame += scrollBarFadeDuration;
20681                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
20682
20683                state = FADING;
20684
20685                // Kick off the fade animation
20686                host.invalidate(true);
20687            }
20688        }
20689    }
20690
20691    /**
20692     * Resuable callback for sending
20693     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
20694     */
20695    private class SendViewScrolledAccessibilityEvent implements Runnable {
20696        public volatile boolean mIsPending;
20697
20698        public void run() {
20699            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
20700            mIsPending = false;
20701        }
20702    }
20703
20704    /**
20705     * <p>
20706     * This class represents a delegate that can be registered in a {@link View}
20707     * to enhance accessibility support via composition rather via inheritance.
20708     * It is specifically targeted to widget developers that extend basic View
20709     * classes i.e. classes in package android.view, that would like their
20710     * applications to be backwards compatible.
20711     * </p>
20712     * <div class="special reference">
20713     * <h3>Developer Guides</h3>
20714     * <p>For more information about making applications accessible, read the
20715     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
20716     * developer guide.</p>
20717     * </div>
20718     * <p>
20719     * A scenario in which a developer would like to use an accessibility delegate
20720     * is overriding a method introduced in a later API version then the minimal API
20721     * version supported by the application. For example, the method
20722     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
20723     * in API version 4 when the accessibility APIs were first introduced. If a
20724     * developer would like his application to run on API version 4 devices (assuming
20725     * all other APIs used by the application are version 4 or lower) and take advantage
20726     * of this method, instead of overriding the method which would break the application's
20727     * backwards compatibility, he can override the corresponding method in this
20728     * delegate and register the delegate in the target View if the API version of
20729     * the system is high enough i.e. the API version is same or higher to the API
20730     * version that introduced
20731     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
20732     * </p>
20733     * <p>
20734     * Here is an example implementation:
20735     * </p>
20736     * <code><pre><p>
20737     * if (Build.VERSION.SDK_INT >= 14) {
20738     *     // If the API version is equal of higher than the version in
20739     *     // which onInitializeAccessibilityNodeInfo was introduced we
20740     *     // register a delegate with a customized implementation.
20741     *     View view = findViewById(R.id.view_id);
20742     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
20743     *         public void onInitializeAccessibilityNodeInfo(View host,
20744     *                 AccessibilityNodeInfo info) {
20745     *             // Let the default implementation populate the info.
20746     *             super.onInitializeAccessibilityNodeInfo(host, info);
20747     *             // Set some other information.
20748     *             info.setEnabled(host.isEnabled());
20749     *         }
20750     *     });
20751     * }
20752     * </code></pre></p>
20753     * <p>
20754     * This delegate contains methods that correspond to the accessibility methods
20755     * in View. If a delegate has been specified the implementation in View hands
20756     * off handling to the corresponding method in this delegate. The default
20757     * implementation the delegate methods behaves exactly as the corresponding
20758     * method in View for the case of no accessibility delegate been set. Hence,
20759     * to customize the behavior of a View method, clients can override only the
20760     * corresponding delegate method without altering the behavior of the rest
20761     * accessibility related methods of the host view.
20762     * </p>
20763     */
20764    public static class AccessibilityDelegate {
20765
20766        /**
20767         * Sends an accessibility event of the given type. If accessibility is not
20768         * enabled this method has no effect.
20769         * <p>
20770         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
20771         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
20772         * been set.
20773         * </p>
20774         *
20775         * @param host The View hosting the delegate.
20776         * @param eventType The type of the event to send.
20777         *
20778         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
20779         */
20780        public void sendAccessibilityEvent(View host, int eventType) {
20781            host.sendAccessibilityEventInternal(eventType);
20782        }
20783
20784        /**
20785         * Performs the specified accessibility action on the view. For
20786         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
20787         * <p>
20788         * The default implementation behaves as
20789         * {@link View#performAccessibilityAction(int, Bundle)
20790         *  View#performAccessibilityAction(int, Bundle)} for the case of
20791         *  no accessibility delegate been set.
20792         * </p>
20793         *
20794         * @param action The action to perform.
20795         * @return Whether the action was performed.
20796         *
20797         * @see View#performAccessibilityAction(int, Bundle)
20798         *      View#performAccessibilityAction(int, Bundle)
20799         */
20800        public boolean performAccessibilityAction(View host, int action, Bundle args) {
20801            return host.performAccessibilityActionInternal(action, args);
20802        }
20803
20804        /**
20805         * Sends an accessibility event. This method behaves exactly as
20806         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
20807         * empty {@link AccessibilityEvent} and does not perform a check whether
20808         * accessibility is enabled.
20809         * <p>
20810         * The default implementation behaves as
20811         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20812         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
20813         * the case of no accessibility delegate been set.
20814         * </p>
20815         *
20816         * @param host The View hosting the delegate.
20817         * @param event The event to send.
20818         *
20819         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20820         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
20821         */
20822        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
20823            host.sendAccessibilityEventUncheckedInternal(event);
20824        }
20825
20826        /**
20827         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
20828         * to its children for adding their text content to the event.
20829         * <p>
20830         * The default implementation behaves as
20831         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20832         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
20833         * the case of no accessibility delegate been set.
20834         * </p>
20835         *
20836         * @param host The View hosting the delegate.
20837         * @param event The event.
20838         * @return True if the event population was completed.
20839         *
20840         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20841         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
20842         */
20843        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20844            return host.dispatchPopulateAccessibilityEventInternal(event);
20845        }
20846
20847        /**
20848         * Gives a chance to the host View to populate the accessibility event with its
20849         * text content.
20850         * <p>
20851         * The default implementation behaves as
20852         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
20853         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
20854         * the case of no accessibility delegate been set.
20855         * </p>
20856         *
20857         * @param host The View hosting the delegate.
20858         * @param event The accessibility event which to populate.
20859         *
20860         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
20861         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
20862         */
20863        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
20864            host.onPopulateAccessibilityEventInternal(event);
20865        }
20866
20867        /**
20868         * Initializes an {@link AccessibilityEvent} with information about the
20869         * the host View which is the event source.
20870         * <p>
20871         * The default implementation behaves as
20872         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
20873         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
20874         * the case of no accessibility delegate been set.
20875         * </p>
20876         *
20877         * @param host The View hosting the delegate.
20878         * @param event The event to initialize.
20879         *
20880         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
20881         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
20882         */
20883        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
20884            host.onInitializeAccessibilityEventInternal(event);
20885        }
20886
20887        /**
20888         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
20889         * <p>
20890         * The default implementation behaves as
20891         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20892         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
20893         * the case of no accessibility delegate been set.
20894         * </p>
20895         *
20896         * @param host The View hosting the delegate.
20897         * @param info The instance to initialize.
20898         *
20899         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20900         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
20901         */
20902        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
20903            host.onInitializeAccessibilityNodeInfoInternal(info);
20904        }
20905
20906        /**
20907         * Called when a child of the host View has requested sending an
20908         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
20909         * to augment the event.
20910         * <p>
20911         * The default implementation behaves as
20912         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20913         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
20914         * the case of no accessibility delegate been set.
20915         * </p>
20916         *
20917         * @param host The View hosting the delegate.
20918         * @param child The child which requests sending the event.
20919         * @param event The event to be sent.
20920         * @return True if the event should be sent
20921         *
20922         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20923         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
20924         */
20925        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
20926                AccessibilityEvent event) {
20927            return host.onRequestSendAccessibilityEventInternal(child, event);
20928        }
20929
20930        /**
20931         * Gets the provider for managing a virtual view hierarchy rooted at this View
20932         * and reported to {@link android.accessibilityservice.AccessibilityService}s
20933         * that explore the window content.
20934         * <p>
20935         * The default implementation behaves as
20936         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
20937         * the case of no accessibility delegate been set.
20938         * </p>
20939         *
20940         * @return The provider.
20941         *
20942         * @see AccessibilityNodeProvider
20943         */
20944        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
20945            return null;
20946        }
20947
20948        /**
20949         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
20950         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
20951         * This method is responsible for obtaining an accessibility node info from a
20952         * pool of reusable instances and calling
20953         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
20954         * view to initialize the former.
20955         * <p>
20956         * <strong>Note:</strong> The client is responsible for recycling the obtained
20957         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
20958         * creation.
20959         * </p>
20960         * <p>
20961         * The default implementation behaves as
20962         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
20963         * the case of no accessibility delegate been set.
20964         * </p>
20965         * @return A populated {@link AccessibilityNodeInfo}.
20966         *
20967         * @see AccessibilityNodeInfo
20968         *
20969         * @hide
20970         */
20971        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
20972            return host.createAccessibilityNodeInfoInternal();
20973        }
20974    }
20975
20976    private class MatchIdPredicate implements Predicate<View> {
20977        public int mId;
20978
20979        @Override
20980        public boolean apply(View view) {
20981            return (view.mID == mId);
20982        }
20983    }
20984
20985    private class MatchLabelForPredicate implements Predicate<View> {
20986        private int mLabeledId;
20987
20988        @Override
20989        public boolean apply(View view) {
20990            return (view.mLabelForId == mLabeledId);
20991        }
20992    }
20993
20994    private class SendViewStateChangedAccessibilityEvent implements Runnable {
20995        private int mChangeTypes = 0;
20996        private boolean mPosted;
20997        private boolean mPostedWithDelay;
20998        private long mLastEventTimeMillis;
20999
21000        @Override
21001        public void run() {
21002            mPosted = false;
21003            mPostedWithDelay = false;
21004            mLastEventTimeMillis = SystemClock.uptimeMillis();
21005            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21006                final AccessibilityEvent event = AccessibilityEvent.obtain();
21007                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
21008                event.setContentChangeTypes(mChangeTypes);
21009                sendAccessibilityEventUnchecked(event);
21010            }
21011            mChangeTypes = 0;
21012        }
21013
21014        public void runOrPost(int changeType) {
21015            mChangeTypes |= changeType;
21016
21017            // If this is a live region or the child of a live region, collect
21018            // all events from this frame and send them on the next frame.
21019            if (inLiveRegion()) {
21020                // If we're already posted with a delay, remove that.
21021                if (mPostedWithDelay) {
21022                    removeCallbacks(this);
21023                    mPostedWithDelay = false;
21024                }
21025                // Only post if we're not already posted.
21026                if (!mPosted) {
21027                    post(this);
21028                    mPosted = true;
21029                }
21030                return;
21031            }
21032
21033            if (mPosted) {
21034                return;
21035            }
21036
21037            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
21038            final long minEventIntevalMillis =
21039                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
21040            if (timeSinceLastMillis >= minEventIntevalMillis) {
21041                removeCallbacks(this);
21042                run();
21043            } else {
21044                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
21045                mPostedWithDelay = true;
21046            }
21047        }
21048    }
21049
21050    private boolean inLiveRegion() {
21051        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21052            return true;
21053        }
21054
21055        ViewParent parent = getParent();
21056        while (parent instanceof View) {
21057            if (((View) parent).getAccessibilityLiveRegion()
21058                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21059                return true;
21060            }
21061            parent = parent.getParent();
21062        }
21063
21064        return false;
21065    }
21066
21067    /**
21068     * Dump all private flags in readable format, useful for documentation and
21069     * sanity checking.
21070     */
21071    private static void dumpFlags() {
21072        final HashMap<String, String> found = Maps.newHashMap();
21073        try {
21074            for (Field field : View.class.getDeclaredFields()) {
21075                final int modifiers = field.getModifiers();
21076                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
21077                    if (field.getType().equals(int.class)) {
21078                        final int value = field.getInt(null);
21079                        dumpFlag(found, field.getName(), value);
21080                    } else if (field.getType().equals(int[].class)) {
21081                        final int[] values = (int[]) field.get(null);
21082                        for (int i = 0; i < values.length; i++) {
21083                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
21084                        }
21085                    }
21086                }
21087            }
21088        } catch (IllegalAccessException e) {
21089            throw new RuntimeException(e);
21090        }
21091
21092        final ArrayList<String> keys = Lists.newArrayList();
21093        keys.addAll(found.keySet());
21094        Collections.sort(keys);
21095        for (String key : keys) {
21096            Log.d(VIEW_LOG_TAG, found.get(key));
21097        }
21098    }
21099
21100    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21101        // Sort flags by prefix, then by bits, always keeping unique keys
21102        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21103        final int prefix = name.indexOf('_');
21104        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21105        final String output = bits + " " + name;
21106        found.put(key, output);
21107    }
21108}
21109