View.java revision db22741540a8e838c1aabe57e9790c8dd97687c7
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.AnimatorInflater;
20import android.animation.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.LayoutRes;
28import android.annotation.NonNull;
29import android.annotation.Nullable;
30import android.annotation.Size;
31import android.content.ClipData;
32import android.content.Context;
33import android.content.res.ColorStateList;
34import android.content.res.Configuration;
35import android.content.res.Resources;
36import android.content.res.TypedArray;
37import android.graphics.Bitmap;
38import android.graphics.Canvas;
39import android.graphics.Insets;
40import android.graphics.Interpolator;
41import android.graphics.LinearGradient;
42import android.graphics.Matrix;
43import android.graphics.Outline;
44import android.graphics.Paint;
45import android.graphics.PixelFormat;
46import android.graphics.Point;
47import android.graphics.PorterDuff;
48import android.graphics.PorterDuffXfermode;
49import android.graphics.Rect;
50import android.graphics.RectF;
51import android.graphics.Region;
52import android.graphics.Shader;
53import android.graphics.drawable.ColorDrawable;
54import android.graphics.drawable.Drawable;
55import android.hardware.display.DisplayManagerGlobal;
56import android.os.Bundle;
57import android.os.Handler;
58import android.os.IBinder;
59import android.os.Parcel;
60import android.os.Parcelable;
61import android.os.RemoteException;
62import android.os.SystemClock;
63import android.os.SystemProperties;
64import android.os.Trace;
65import android.text.TextUtils;
66import android.util.AttributeSet;
67import android.util.FloatProperty;
68import android.util.LayoutDirection;
69import android.util.Log;
70import android.util.LongSparseLongArray;
71import android.util.Pools.SynchronizedPool;
72import android.util.Property;
73import android.util.SparseArray;
74import android.util.StateSet;
75import android.util.SuperNotCalledException;
76import android.util.TypedValue;
77import android.view.ContextMenu.ContextMenuInfo;
78import android.view.AccessibilityIterators.TextSegmentIterator;
79import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
80import android.view.AccessibilityIterators.WordTextSegmentIterator;
81import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
82import android.view.accessibility.AccessibilityEvent;
83import android.view.accessibility.AccessibilityEventSource;
84import android.view.accessibility.AccessibilityManager;
85import android.view.accessibility.AccessibilityNodeInfo;
86import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
87import android.view.accessibility.AccessibilityNodeProvider;
88import android.view.animation.Animation;
89import android.view.animation.AnimationUtils;
90import android.view.animation.Transformation;
91import android.view.inputmethod.EditorInfo;
92import android.view.inputmethod.InputConnection;
93import android.view.inputmethod.InputMethodManager;
94import android.widget.Checkable;
95import android.widget.ScrollBarDrawable;
96
97import static android.os.Build.VERSION_CODES.*;
98import static java.lang.Math.max;
99
100import com.android.internal.R;
101import com.android.internal.util.Predicate;
102import com.android.internal.view.menu.MenuBuilder;
103import com.google.android.collect.Lists;
104import com.google.android.collect.Maps;
105
106import java.lang.annotation.Retention;
107import java.lang.annotation.RetentionPolicy;
108import java.lang.ref.WeakReference;
109import java.lang.reflect.Field;
110import java.lang.reflect.InvocationTargetException;
111import java.lang.reflect.Method;
112import java.lang.reflect.Modifier;
113import java.util.ArrayList;
114import java.util.Arrays;
115import java.util.Collections;
116import java.util.HashMap;
117import java.util.List;
118import java.util.Locale;
119import java.util.Map;
120import java.util.concurrent.CopyOnWriteArrayList;
121import java.util.concurrent.atomic.AtomicInteger;
122
123/**
124 * <p>
125 * This class represents the basic building block for user interface components. A View
126 * occupies a rectangular area on the screen and is responsible for drawing and
127 * event handling. View is the base class for <em>widgets</em>, which are
128 * used to create interactive UI components (buttons, text fields, etc.). The
129 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
130 * are invisible containers that hold other Views (or other ViewGroups) and define
131 * their layout properties.
132 * </p>
133 *
134 * <div class="special reference">
135 * <h3>Developer Guides</h3>
136 * <p>For information about using this class to develop your application's user interface,
137 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
138 * </div>
139 *
140 * <a name="Using"></a>
141 * <h3>Using Views</h3>
142 * <p>
143 * All of the views in a window are arranged in a single tree. You can add views
144 * either from code or by specifying a tree of views in one or more XML layout
145 * files. There are many specialized subclasses of views that act as controls or
146 * are capable of displaying text, images, or other content.
147 * </p>
148 * <p>
149 * Once you have created a tree of views, there are typically a few types of
150 * common operations you may wish to perform:
151 * <ul>
152 * <li><strong>Set properties:</strong> for example setting the text of a
153 * {@link android.widget.TextView}. The available properties and the methods
154 * that set them will vary among the different subclasses of views. Note that
155 * properties that are known at build time can be set in the XML layout
156 * files.</li>
157 * <li><strong>Set focus:</strong> The framework will handled moving focus in
158 * response to user input. To force focus to a specific view, call
159 * {@link #requestFocus}.</li>
160 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
161 * that will be notified when something interesting happens to the view. For
162 * example, all views will let you set a listener to be notified when the view
163 * gains or loses focus. You can register such a listener using
164 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
165 * Other view subclasses offer more specialized listeners. For example, a Button
166 * exposes a listener to notify clients when the button is clicked.</li>
167 * <li><strong>Set visibility:</strong> You can hide or show views using
168 * {@link #setVisibility(int)}.</li>
169 * </ul>
170 * </p>
171 * <p><em>
172 * Note: The Android framework is responsible for measuring, laying out and
173 * drawing views. You should not call methods that perform these actions on
174 * views yourself unless you are actually implementing a
175 * {@link android.view.ViewGroup}.
176 * </em></p>
177 *
178 * <a name="Lifecycle"></a>
179 * <h3>Implementing a Custom View</h3>
180 *
181 * <p>
182 * To implement a custom view, you will usually begin by providing overrides for
183 * some of the standard methods that the framework calls on all views. You do
184 * not need to override all of these methods. In fact, you can start by just
185 * overriding {@link #onDraw(android.graphics.Canvas)}.
186 * <table border="2" width="85%" align="center" cellpadding="5">
187 *     <thead>
188 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
189 *     </thead>
190 *
191 *     <tbody>
192 *     <tr>
193 *         <td rowspan="2">Creation</td>
194 *         <td>Constructors</td>
195 *         <td>There is a form of the constructor that are called when the view
196 *         is created from code and a form that is called when the view is
197 *         inflated from a layout file. The second form should parse and apply
198 *         any attributes defined in the layout file.
199 *         </td>
200 *     </tr>
201 *     <tr>
202 *         <td><code>{@link #onFinishInflate()}</code></td>
203 *         <td>Called after a view and all of its children has been inflated
204 *         from XML.</td>
205 *     </tr>
206 *
207 *     <tr>
208 *         <td rowspan="3">Layout</td>
209 *         <td><code>{@link #onMeasure(int, int)}</code></td>
210 *         <td>Called to determine the size requirements for this view and all
211 *         of its children.
212 *         </td>
213 *     </tr>
214 *     <tr>
215 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
216 *         <td>Called when this view should assign a size and position to all
217 *         of its children.
218 *         </td>
219 *     </tr>
220 *     <tr>
221 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
222 *         <td>Called when the size of this view has changed.
223 *         </td>
224 *     </tr>
225 *
226 *     <tr>
227 *         <td>Drawing</td>
228 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
229 *         <td>Called when the view should render its content.
230 *         </td>
231 *     </tr>
232 *
233 *     <tr>
234 *         <td rowspan="4">Event processing</td>
235 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
236 *         <td>Called when a new hardware key event occurs.
237 *         </td>
238 *     </tr>
239 *     <tr>
240 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
241 *         <td>Called when a hardware key up event occurs.
242 *         </td>
243 *     </tr>
244 *     <tr>
245 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
246 *         <td>Called when a trackball motion event occurs.
247 *         </td>
248 *     </tr>
249 *     <tr>
250 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
251 *         <td>Called when a touch screen motion event occurs.
252 *         </td>
253 *     </tr>
254 *
255 *     <tr>
256 *         <td rowspan="2">Focus</td>
257 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
258 *         <td>Called when the view gains or loses focus.
259 *         </td>
260 *     </tr>
261 *
262 *     <tr>
263 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
264 *         <td>Called when the window containing the view gains or loses focus.
265 *         </td>
266 *     </tr>
267 *
268 *     <tr>
269 *         <td rowspan="3">Attaching</td>
270 *         <td><code>{@link #onAttachedToWindow()}</code></td>
271 *         <td>Called when the view is attached to a window.
272 *         </td>
273 *     </tr>
274 *
275 *     <tr>
276 *         <td><code>{@link #onDetachedFromWindow}</code></td>
277 *         <td>Called when the view is detached from its window.
278 *         </td>
279 *     </tr>
280 *
281 *     <tr>
282 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
283 *         <td>Called when the visibility of the window containing the view
284 *         has changed.
285 *         </td>
286 *     </tr>
287 *     </tbody>
288 *
289 * </table>
290 * </p>
291 *
292 * <a name="IDs"></a>
293 * <h3>IDs</h3>
294 * Views may have an integer id associated with them. These ids are typically
295 * assigned in the layout XML files, and are used to find specific views within
296 * the view tree. A common pattern is to:
297 * <ul>
298 * <li>Define a Button in the layout file and assign it a unique ID.
299 * <pre>
300 * &lt;Button
301 *     android:id="@+id/my_button"
302 *     android:layout_width="wrap_content"
303 *     android:layout_height="wrap_content"
304 *     android:text="@string/my_button_text"/&gt;
305 * </pre></li>
306 * <li>From the onCreate method of an Activity, find the Button
307 * <pre class="prettyprint">
308 *      Button myButton = (Button) findViewById(R.id.my_button);
309 * </pre></li>
310 * </ul>
311 * <p>
312 * View IDs need not be unique throughout the tree, but it is good practice to
313 * ensure that they are at least unique within the part of the tree you are
314 * searching.
315 * </p>
316 *
317 * <a name="Position"></a>
318 * <h3>Position</h3>
319 * <p>
320 * The geometry of a view is that of a rectangle. A view has a location,
321 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
322 * two dimensions, expressed as a width and a height. The unit for location
323 * and dimensions is the pixel.
324 * </p>
325 *
326 * <p>
327 * It is possible to retrieve the location of a view by invoking the methods
328 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
329 * coordinate of the rectangle representing the view. The latter returns the
330 * top, or Y, coordinate of the rectangle representing the view. These methods
331 * both return the location of the view relative to its parent. For instance,
332 * when getLeft() returns 20, that means the view is located 20 pixels to the
333 * right of the left edge of its direct parent.
334 * </p>
335 *
336 * <p>
337 * In addition, several convenience methods are offered to avoid unnecessary
338 * computations, namely {@link #getRight()} and {@link #getBottom()}.
339 * These methods return the coordinates of the right and bottom edges of the
340 * rectangle representing the view. For instance, calling {@link #getRight()}
341 * is similar to the following computation: <code>getLeft() + getWidth()</code>
342 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
343 * </p>
344 *
345 * <a name="SizePaddingMargins"></a>
346 * <h3>Size, padding and margins</h3>
347 * <p>
348 * The size of a view is expressed with a width and a height. A view actually
349 * possess two pairs of width and height values.
350 * </p>
351 *
352 * <p>
353 * The first pair is known as <em>measured width</em> and
354 * <em>measured height</em>. These dimensions define how big a view wants to be
355 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
356 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
357 * and {@link #getMeasuredHeight()}.
358 * </p>
359 *
360 * <p>
361 * The second pair is simply known as <em>width</em> and <em>height</em>, or
362 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
363 * dimensions define the actual size of the view on screen, at drawing time and
364 * after layout. These values may, but do not have to, be different from the
365 * measured width and height. The width and height can be obtained by calling
366 * {@link #getWidth()} and {@link #getHeight()}.
367 * </p>
368 *
369 * <p>
370 * To measure its dimensions, a view takes into account its padding. The padding
371 * is expressed in pixels for the left, top, right and bottom parts of the view.
372 * Padding can be used to offset the content of the view by a specific amount of
373 * pixels. For instance, a left padding of 2 will push the view's content by
374 * 2 pixels to the right of the left edge. Padding can be set using the
375 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
376 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
377 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
378 * {@link #getPaddingEnd()}.
379 * </p>
380 *
381 * <p>
382 * Even though a view can define a padding, it does not provide any support for
383 * margins. However, view groups provide such a support. Refer to
384 * {@link android.view.ViewGroup} and
385 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
386 * </p>
387 *
388 * <a name="Layout"></a>
389 * <h3>Layout</h3>
390 * <p>
391 * Layout is a two pass process: a measure pass and a layout pass. The measuring
392 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
393 * of the view tree. Each view pushes dimension specifications down the tree
394 * during the recursion. At the end of the measure pass, every view has stored
395 * its measurements. The second pass happens in
396 * {@link #layout(int,int,int,int)} and is also top-down. During
397 * this pass each parent is responsible for positioning all of its children
398 * using the sizes computed in the measure pass.
399 * </p>
400 *
401 * <p>
402 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
403 * {@link #getMeasuredHeight()} values must be set, along with those for all of
404 * that view's descendants. A view's measured width and measured height values
405 * must respect the constraints imposed by the view's parents. This guarantees
406 * that at the end of the measure pass, all parents accept all of their
407 * children's measurements. A parent view may call measure() more than once on
408 * its children. For example, the parent may measure each child once with
409 * unspecified dimensions to find out how big they want to be, then call
410 * measure() on them again with actual numbers if the sum of all the children's
411 * unconstrained sizes is too big or too small.
412 * </p>
413 *
414 * <p>
415 * The measure pass uses two classes to communicate dimensions. The
416 * {@link MeasureSpec} class is used by views to tell their parents how they
417 * want to be measured and positioned. The base LayoutParams class just
418 * describes how big the view wants to be for both width and height. For each
419 * dimension, it can specify one of:
420 * <ul>
421 * <li> an exact number
422 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
423 * (minus padding)
424 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
425 * enclose its content (plus padding).
426 * </ul>
427 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
428 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
429 * an X and Y value.
430 * </p>
431 *
432 * <p>
433 * MeasureSpecs are used to push requirements down the tree from parent to
434 * child. A MeasureSpec can be in one of three modes:
435 * <ul>
436 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
437 * of a child view. For example, a LinearLayout may call measure() on its child
438 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
439 * tall the child view wants to be given a width of 240 pixels.
440 * <li>EXACTLY: This is used by the parent to impose an exact size on the
441 * child. The child must use this size, and guarantee that all of its
442 * descendants will fit within this size.
443 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
444 * child. The child must guarantee that it and all of its descendants will fit
445 * within this size.
446 * </ul>
447 * </p>
448 *
449 * <p>
450 * To initiate a layout, call {@link #requestLayout}. This method is typically
451 * called by a view on itself when it believes that is can no longer fit within
452 * its current bounds.
453 * </p>
454 *
455 * <a name="Drawing"></a>
456 * <h3>Drawing</h3>
457 * <p>
458 * Drawing is handled by walking the tree and recording the drawing commands of
459 * any View that needs to update. After this, the drawing commands of the
460 * entire tree are issued to screen, clipped to the newly damaged area.
461 * </p>
462 *
463 * <p>
464 * The tree is largely recorded and drawn in order, with parents drawn before
465 * (i.e., behind) their children, with siblings drawn in the order they appear
466 * in the tree. If you set a background drawable for a View, then the View will
467 * draw it before calling back to its <code>onDraw()</code> method. The child
468 * drawing order can be overridden with
469 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
470 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
471 * </p>
472 *
473 * <p>
474 * To force a view to draw, call {@link #invalidate()}.
475 * </p>
476 *
477 * <a name="EventHandlingThreading"></a>
478 * <h3>Event Handling and Threading</h3>
479 * <p>
480 * The basic cycle of a view is as follows:
481 * <ol>
482 * <li>An event comes in and is dispatched to the appropriate view. The view
483 * handles the event and notifies any listeners.</li>
484 * <li>If in the course of processing the event, the view's bounds may need
485 * to be changed, the view will call {@link #requestLayout()}.</li>
486 * <li>Similarly, if in the course of processing the event the view's appearance
487 * may need to be changed, the view will call {@link #invalidate()}.</li>
488 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
489 * the framework will take care of measuring, laying out, and drawing the tree
490 * as appropriate.</li>
491 * </ol>
492 * </p>
493 *
494 * <p><em>Note: The entire view tree is single threaded. You must always be on
495 * the UI thread when calling any method on any view.</em>
496 * If you are doing work on other threads and want to update the state of a view
497 * from that thread, you should use a {@link Handler}.
498 * </p>
499 *
500 * <a name="FocusHandling"></a>
501 * <h3>Focus Handling</h3>
502 * <p>
503 * The framework will handle routine focus movement in response to user input.
504 * This includes changing the focus as views are removed or hidden, or as new
505 * views become available. Views indicate their willingness to take focus
506 * through the {@link #isFocusable} method. To change whether a view can take
507 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
508 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
509 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
510 * </p>
511 * <p>
512 * Focus movement is based on an algorithm which finds the nearest neighbor in a
513 * given direction. In rare cases, the default algorithm may not match the
514 * intended behavior of the developer. In these situations, you can provide
515 * explicit overrides by using these XML attributes in the layout file:
516 * <pre>
517 * nextFocusDown
518 * nextFocusLeft
519 * nextFocusRight
520 * nextFocusUp
521 * </pre>
522 * </p>
523 *
524 *
525 * <p>
526 * To get a particular view to take focus, call {@link #requestFocus()}.
527 * </p>
528 *
529 * <a name="TouchMode"></a>
530 * <h3>Touch Mode</h3>
531 * <p>
532 * When a user is navigating a user interface via directional keys such as a D-pad, it is
533 * necessary to give focus to actionable items such as buttons so the user can see
534 * what will take input.  If the device has touch capabilities, however, and the user
535 * begins interacting with the interface by touching it, it is no longer necessary to
536 * always highlight, or give focus to, a particular view.  This motivates a mode
537 * for interaction named 'touch mode'.
538 * </p>
539 * <p>
540 * For a touch capable device, once the user touches the screen, the device
541 * will enter touch mode.  From this point onward, only views for which
542 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
543 * Other views that are touchable, like buttons, will not take focus when touched; they will
544 * only fire the on click listeners.
545 * </p>
546 * <p>
547 * Any time a user hits a directional key, such as a D-pad direction, the view device will
548 * exit touch mode, and find a view to take focus, so that the user may resume interacting
549 * with the user interface without touching the screen again.
550 * </p>
551 * <p>
552 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
553 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
554 * </p>
555 *
556 * <a name="Scrolling"></a>
557 * <h3>Scrolling</h3>
558 * <p>
559 * The framework provides basic support for views that wish to internally
560 * scroll their content. This includes keeping track of the X and Y scroll
561 * offset as well as mechanisms for drawing scrollbars. See
562 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
563 * {@link #awakenScrollBars()} for more details.
564 * </p>
565 *
566 * <a name="Tags"></a>
567 * <h3>Tags</h3>
568 * <p>
569 * Unlike IDs, tags are not used to identify views. Tags are essentially an
570 * extra piece of information that can be associated with a view. They are most
571 * often used as a convenience to store data related to views in the views
572 * themselves rather than by putting them in a separate structure.
573 * </p>
574 *
575 * <a name="Properties"></a>
576 * <h3>Properties</h3>
577 * <p>
578 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
579 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
580 * available both in the {@link Property} form as well as in similarly-named setter/getter
581 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
582 * be used to set persistent state associated with these rendering-related properties on the view.
583 * The properties and methods can also be used in conjunction with
584 * {@link android.animation.Animator Animator}-based animations, described more in the
585 * <a href="#Animation">Animation</a> section.
586 * </p>
587 *
588 * <a name="Animation"></a>
589 * <h3>Animation</h3>
590 * <p>
591 * Starting with Android 3.0, the preferred way of animating views is to use the
592 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
593 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
594 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
595 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
596 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
597 * makes animating these View properties particularly easy and efficient.
598 * </p>
599 * <p>
600 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
601 * You can attach an {@link Animation} object to a view using
602 * {@link #setAnimation(Animation)} or
603 * {@link #startAnimation(Animation)}. The animation can alter the scale,
604 * rotation, translation and alpha of a view over time. If the animation is
605 * attached to a view that has children, the animation will affect the entire
606 * subtree rooted by that node. When an animation is started, the framework will
607 * take care of redrawing the appropriate views until the animation completes.
608 * </p>
609 *
610 * <a name="Security"></a>
611 * <h3>Security</h3>
612 * <p>
613 * Sometimes it is essential that an application be able to verify that an action
614 * is being performed with the full knowledge and consent of the user, such as
615 * granting a permission request, making a purchase or clicking on an advertisement.
616 * Unfortunately, a malicious application could try to spoof the user into
617 * performing these actions, unaware, by concealing the intended purpose of the view.
618 * As a remedy, the framework offers a touch filtering mechanism that can be used to
619 * improve the security of views that provide access to sensitive functionality.
620 * </p><p>
621 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
622 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
623 * will discard touches that are received whenever the view's window is obscured by
624 * another visible window.  As a result, the view will not receive touches whenever a
625 * toast, dialog or other window appears above the view's window.
626 * </p><p>
627 * For more fine-grained control over security, consider overriding the
628 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
629 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
630 * </p>
631 *
632 * @attr ref android.R.styleable#View_alpha
633 * @attr ref android.R.styleable#View_background
634 * @attr ref android.R.styleable#View_clickable
635 * @attr ref android.R.styleable#View_contentDescription
636 * @attr ref android.R.styleable#View_drawingCacheQuality
637 * @attr ref android.R.styleable#View_duplicateParentState
638 * @attr ref android.R.styleable#View_id
639 * @attr ref android.R.styleable#View_requiresFadingEdge
640 * @attr ref android.R.styleable#View_fadeScrollbars
641 * @attr ref android.R.styleable#View_fadingEdgeLength
642 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
643 * @attr ref android.R.styleable#View_fitsSystemWindows
644 * @attr ref android.R.styleable#View_isScrollContainer
645 * @attr ref android.R.styleable#View_focusable
646 * @attr ref android.R.styleable#View_focusableInTouchMode
647 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
648 * @attr ref android.R.styleable#View_keepScreenOn
649 * @attr ref android.R.styleable#View_layerType
650 * @attr ref android.R.styleable#View_layoutDirection
651 * @attr ref android.R.styleable#View_longClickable
652 * @attr ref android.R.styleable#View_minHeight
653 * @attr ref android.R.styleable#View_minWidth
654 * @attr ref android.R.styleable#View_nextFocusDown
655 * @attr ref android.R.styleable#View_nextFocusLeft
656 * @attr ref android.R.styleable#View_nextFocusRight
657 * @attr ref android.R.styleable#View_nextFocusUp
658 * @attr ref android.R.styleable#View_onClick
659 * @attr ref android.R.styleable#View_padding
660 * @attr ref android.R.styleable#View_paddingBottom
661 * @attr ref android.R.styleable#View_paddingLeft
662 * @attr ref android.R.styleable#View_paddingRight
663 * @attr ref android.R.styleable#View_paddingTop
664 * @attr ref android.R.styleable#View_paddingStart
665 * @attr ref android.R.styleable#View_paddingEnd
666 * @attr ref android.R.styleable#View_saveEnabled
667 * @attr ref android.R.styleable#View_rotation
668 * @attr ref android.R.styleable#View_rotationX
669 * @attr ref android.R.styleable#View_rotationY
670 * @attr ref android.R.styleable#View_scaleX
671 * @attr ref android.R.styleable#View_scaleY
672 * @attr ref android.R.styleable#View_scrollX
673 * @attr ref android.R.styleable#View_scrollY
674 * @attr ref android.R.styleable#View_scrollbarSize
675 * @attr ref android.R.styleable#View_scrollbarStyle
676 * @attr ref android.R.styleable#View_scrollbars
677 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
678 * @attr ref android.R.styleable#View_scrollbarFadeDuration
679 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
680 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
681 * @attr ref android.R.styleable#View_scrollbarThumbVertical
682 * @attr ref android.R.styleable#View_scrollbarTrackVertical
683 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
684 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
685 * @attr ref android.R.styleable#View_stateListAnimator
686 * @attr ref android.R.styleable#View_transitionName
687 * @attr ref android.R.styleable#View_soundEffectsEnabled
688 * @attr ref android.R.styleable#View_tag
689 * @attr ref android.R.styleable#View_textAlignment
690 * @attr ref android.R.styleable#View_textDirection
691 * @attr ref android.R.styleable#View_transformPivotX
692 * @attr ref android.R.styleable#View_transformPivotY
693 * @attr ref android.R.styleable#View_translationX
694 * @attr ref android.R.styleable#View_translationY
695 * @attr ref android.R.styleable#View_translationZ
696 * @attr ref android.R.styleable#View_visibility
697 *
698 * @see android.view.ViewGroup
699 */
700public class View implements Drawable.Callback, KeyEvent.Callback,
701        AccessibilityEventSource {
702    private static final boolean DBG = false;
703
704    /**
705     * The logging tag used by this class with android.util.Log.
706     */
707    protected static final String VIEW_LOG_TAG = "View";
708
709    /**
710     * When set to true, apps will draw debugging information about their layouts.
711     *
712     * @hide
713     */
714    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
715
716    /**
717     * When set to true, this view will save its attribute data.
718     *
719     * @hide
720     */
721    public static boolean mDebugViewAttributes = false;
722
723    /**
724     * Used to mark a View that has no ID.
725     */
726    public static final int NO_ID = -1;
727
728    /**
729     * Signals that compatibility booleans have been initialized according to
730     * target SDK versions.
731     */
732    private static boolean sCompatibilityDone = false;
733
734    /**
735     * Use the old (broken) way of building MeasureSpecs.
736     */
737    private static boolean sUseBrokenMakeMeasureSpec = false;
738
739    /**
740     * Ignore any optimizations using the measure cache.
741     */
742    private static boolean sIgnoreMeasureCache = false;
743
744    /**
745     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
746     * calling setFlags.
747     */
748    private static final int NOT_FOCUSABLE = 0x00000000;
749
750    /**
751     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
752     * setFlags.
753     */
754    private static final int FOCUSABLE = 0x00000001;
755
756    /**
757     * Mask for use with setFlags indicating bits used for focus.
758     */
759    private static final int FOCUSABLE_MASK = 0x00000001;
760
761    /**
762     * This view will adjust its padding to fit sytem windows (e.g. status bar)
763     */
764    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
765
766    /** @hide */
767    @IntDef({VISIBLE, INVISIBLE, GONE})
768    @Retention(RetentionPolicy.SOURCE)
769    public @interface Visibility {}
770
771    /**
772     * This view is visible.
773     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
774     * android:visibility}.
775     */
776    public static final int VISIBLE = 0x00000000;
777
778    /**
779     * This view is invisible, but it still takes up space for layout purposes.
780     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
781     * android:visibility}.
782     */
783    public static final int INVISIBLE = 0x00000004;
784
785    /**
786     * This view is invisible, and it doesn't take any space for layout
787     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
788     * android:visibility}.
789     */
790    public static final int GONE = 0x00000008;
791
792    /**
793     * Mask for use with setFlags indicating bits used for visibility.
794     * {@hide}
795     */
796    static final int VISIBILITY_MASK = 0x0000000C;
797
798    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
799
800    /**
801     * This view is enabled. Interpretation varies by subclass.
802     * Use with ENABLED_MASK when calling setFlags.
803     * {@hide}
804     */
805    static final int ENABLED = 0x00000000;
806
807    /**
808     * This view is disabled. Interpretation varies by subclass.
809     * Use with ENABLED_MASK when calling setFlags.
810     * {@hide}
811     */
812    static final int DISABLED = 0x00000020;
813
814   /**
815    * Mask for use with setFlags indicating bits used for indicating whether
816    * this view is enabled
817    * {@hide}
818    */
819    static final int ENABLED_MASK = 0x00000020;
820
821    /**
822     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
823     * called and further optimizations will be performed. It is okay to have
824     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
825     * {@hide}
826     */
827    static final int WILL_NOT_DRAW = 0x00000080;
828
829    /**
830     * Mask for use with setFlags indicating bits used for indicating whether
831     * this view is will draw
832     * {@hide}
833     */
834    static final int DRAW_MASK = 0x00000080;
835
836    /**
837     * <p>This view doesn't show scrollbars.</p>
838     * {@hide}
839     */
840    static final int SCROLLBARS_NONE = 0x00000000;
841
842    /**
843     * <p>This view shows horizontal scrollbars.</p>
844     * {@hide}
845     */
846    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
847
848    /**
849     * <p>This view shows vertical scrollbars.</p>
850     * {@hide}
851     */
852    static final int SCROLLBARS_VERTICAL = 0x00000200;
853
854    /**
855     * <p>Mask for use with setFlags indicating bits used for indicating which
856     * scrollbars are enabled.</p>
857     * {@hide}
858     */
859    static final int SCROLLBARS_MASK = 0x00000300;
860
861    /**
862     * Indicates that the view should filter touches when its window is obscured.
863     * Refer to the class comments for more information about this security feature.
864     * {@hide}
865     */
866    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
867
868    /**
869     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
870     * that they are optional and should be skipped if the window has
871     * requested system UI flags that ignore those insets for layout.
872     */
873    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
874
875    /**
876     * <p>This view doesn't show fading edges.</p>
877     * {@hide}
878     */
879    static final int FADING_EDGE_NONE = 0x00000000;
880
881    /**
882     * <p>This view shows horizontal fading edges.</p>
883     * {@hide}
884     */
885    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
886
887    /**
888     * <p>This view shows vertical fading edges.</p>
889     * {@hide}
890     */
891    static final int FADING_EDGE_VERTICAL = 0x00002000;
892
893    /**
894     * <p>Mask for use with setFlags indicating bits used for indicating which
895     * fading edges are enabled.</p>
896     * {@hide}
897     */
898    static final int FADING_EDGE_MASK = 0x00003000;
899
900    /**
901     * <p>Indicates this view can be clicked. When clickable, a View reacts
902     * to clicks by notifying the OnClickListener.<p>
903     * {@hide}
904     */
905    static final int CLICKABLE = 0x00004000;
906
907    /**
908     * <p>Indicates this view is caching its drawing into a bitmap.</p>
909     * {@hide}
910     */
911    static final int DRAWING_CACHE_ENABLED = 0x00008000;
912
913    /**
914     * <p>Indicates that no icicle should be saved for this view.<p>
915     * {@hide}
916     */
917    static final int SAVE_DISABLED = 0x000010000;
918
919    /**
920     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
921     * property.</p>
922     * {@hide}
923     */
924    static final int SAVE_DISABLED_MASK = 0x000010000;
925
926    /**
927     * <p>Indicates that no drawing cache should ever be created for this view.<p>
928     * {@hide}
929     */
930    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
931
932    /**
933     * <p>Indicates this view can take / keep focus when int touch mode.</p>
934     * {@hide}
935     */
936    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
937
938    /** @hide */
939    @Retention(RetentionPolicy.SOURCE)
940    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
941    public @interface DrawingCacheQuality {}
942
943    /**
944     * <p>Enables low quality mode for the drawing cache.</p>
945     */
946    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
947
948    /**
949     * <p>Enables high quality mode for the drawing cache.</p>
950     */
951    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
952
953    /**
954     * <p>Enables automatic quality mode for the drawing cache.</p>
955     */
956    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
957
958    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
959            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
960    };
961
962    /**
963     * <p>Mask for use with setFlags indicating bits used for the cache
964     * quality property.</p>
965     * {@hide}
966     */
967    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
968
969    /**
970     * <p>
971     * Indicates this view can be long clicked. When long clickable, a View
972     * reacts to long clicks by notifying the OnLongClickListener or showing a
973     * context menu.
974     * </p>
975     * {@hide}
976     */
977    static final int LONG_CLICKABLE = 0x00200000;
978
979    /**
980     * <p>Indicates that this view gets its drawable states from its direct parent
981     * and ignores its original internal states.</p>
982     *
983     * @hide
984     */
985    static final int DUPLICATE_PARENT_STATE = 0x00400000;
986
987    /** @hide */
988    @IntDef({
989        SCROLLBARS_INSIDE_OVERLAY,
990        SCROLLBARS_INSIDE_INSET,
991        SCROLLBARS_OUTSIDE_OVERLAY,
992        SCROLLBARS_OUTSIDE_INSET
993    })
994    @Retention(RetentionPolicy.SOURCE)
995    public @interface ScrollBarStyle {}
996
997    /**
998     * The scrollbar style to display the scrollbars inside the content area,
999     * without increasing the padding. The scrollbars will be overlaid with
1000     * translucency on the view's content.
1001     */
1002    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1003
1004    /**
1005     * The scrollbar style to display the scrollbars inside the padded area,
1006     * increasing the padding of the view. The scrollbars will not overlap the
1007     * content area of the view.
1008     */
1009    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1010
1011    /**
1012     * The scrollbar style to display the scrollbars at the edge of the view,
1013     * without increasing the padding. The scrollbars will be overlaid with
1014     * translucency.
1015     */
1016    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1017
1018    /**
1019     * The scrollbar style to display the scrollbars at the edge of the view,
1020     * increasing the padding of the view. The scrollbars will only overlap the
1021     * background, if any.
1022     */
1023    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1024
1025    /**
1026     * Mask to check if the scrollbar style is overlay or inset.
1027     * {@hide}
1028     */
1029    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1030
1031    /**
1032     * Mask to check if the scrollbar style is inside or outside.
1033     * {@hide}
1034     */
1035    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1036
1037    /**
1038     * Mask for scrollbar style.
1039     * {@hide}
1040     */
1041    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1042
1043    /**
1044     * View flag indicating that the screen should remain on while the
1045     * window containing this view is visible to the user.  This effectively
1046     * takes care of automatically setting the WindowManager's
1047     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1048     */
1049    public static final int KEEP_SCREEN_ON = 0x04000000;
1050
1051    /**
1052     * View flag indicating whether this view should have sound effects enabled
1053     * for events such as clicking and touching.
1054     */
1055    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1056
1057    /**
1058     * View flag indicating whether this view should have haptic feedback
1059     * enabled for events such as long presses.
1060     */
1061    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1062
1063    /**
1064     * <p>Indicates that the view hierarchy should stop saving state when
1065     * it reaches this view.  If state saving is initiated immediately at
1066     * the view, it will be allowed.
1067     * {@hide}
1068     */
1069    static final int PARENT_SAVE_DISABLED = 0x20000000;
1070
1071    /**
1072     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1073     * {@hide}
1074     */
1075    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1076
1077    /** @hide */
1078    @IntDef(flag = true,
1079            value = {
1080                FOCUSABLES_ALL,
1081                FOCUSABLES_TOUCH_MODE
1082            })
1083    @Retention(RetentionPolicy.SOURCE)
1084    public @interface FocusableMode {}
1085
1086    /**
1087     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1088     * should add all focusable Views regardless if they are focusable in touch mode.
1089     */
1090    public static final int FOCUSABLES_ALL = 0x00000000;
1091
1092    /**
1093     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1094     * should add only Views focusable in touch mode.
1095     */
1096    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1097
1098    /** @hide */
1099    @IntDef({
1100            FOCUS_BACKWARD,
1101            FOCUS_FORWARD,
1102            FOCUS_LEFT,
1103            FOCUS_UP,
1104            FOCUS_RIGHT,
1105            FOCUS_DOWN
1106    })
1107    @Retention(RetentionPolicy.SOURCE)
1108    public @interface FocusDirection {}
1109
1110    /** @hide */
1111    @IntDef({
1112            FOCUS_LEFT,
1113            FOCUS_UP,
1114            FOCUS_RIGHT,
1115            FOCUS_DOWN
1116    })
1117    @Retention(RetentionPolicy.SOURCE)
1118    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1119
1120    /**
1121     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1122     * item.
1123     */
1124    public static final int FOCUS_BACKWARD = 0x00000001;
1125
1126    /**
1127     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1128     * item.
1129     */
1130    public static final int FOCUS_FORWARD = 0x00000002;
1131
1132    /**
1133     * Use with {@link #focusSearch(int)}. Move focus to the left.
1134     */
1135    public static final int FOCUS_LEFT = 0x00000011;
1136
1137    /**
1138     * Use with {@link #focusSearch(int)}. Move focus up.
1139     */
1140    public static final int FOCUS_UP = 0x00000021;
1141
1142    /**
1143     * Use with {@link #focusSearch(int)}. Move focus to the right.
1144     */
1145    public static final int FOCUS_RIGHT = 0x00000042;
1146
1147    /**
1148     * Use with {@link #focusSearch(int)}. Move focus down.
1149     */
1150    public static final int FOCUS_DOWN = 0x00000082;
1151
1152    /**
1153     * Bits of {@link #getMeasuredWidthAndState()} and
1154     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1155     */
1156    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1157
1158    /**
1159     * Bits of {@link #getMeasuredWidthAndState()} and
1160     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1161     */
1162    public static final int MEASURED_STATE_MASK = 0xff000000;
1163
1164    /**
1165     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1166     * for functions that combine both width and height into a single int,
1167     * such as {@link #getMeasuredState()} and the childState argument of
1168     * {@link #resolveSizeAndState(int, int, int)}.
1169     */
1170    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1171
1172    /**
1173     * Bit of {@link #getMeasuredWidthAndState()} and
1174     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1175     * is smaller that the space the view would like to have.
1176     */
1177    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1178
1179    /**
1180     * Base View state sets
1181     */
1182    // Singles
1183    /**
1184     * Indicates the view has no states set. States are used with
1185     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1186     * view depending on its state.
1187     *
1188     * @see android.graphics.drawable.Drawable
1189     * @see #getDrawableState()
1190     */
1191    protected static final int[] EMPTY_STATE_SET;
1192    /**
1193     * Indicates the view is enabled. States are used with
1194     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1195     * view depending on its state.
1196     *
1197     * @see android.graphics.drawable.Drawable
1198     * @see #getDrawableState()
1199     */
1200    protected static final int[] ENABLED_STATE_SET;
1201    /**
1202     * Indicates the view is focused. States are used with
1203     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1204     * view depending on its state.
1205     *
1206     * @see android.graphics.drawable.Drawable
1207     * @see #getDrawableState()
1208     */
1209    protected static final int[] FOCUSED_STATE_SET;
1210    /**
1211     * Indicates the view is selected. States are used with
1212     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1213     * view depending on its state.
1214     *
1215     * @see android.graphics.drawable.Drawable
1216     * @see #getDrawableState()
1217     */
1218    protected static final int[] SELECTED_STATE_SET;
1219    /**
1220     * Indicates the view is pressed. States are used with
1221     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1222     * view depending on its state.
1223     *
1224     * @see android.graphics.drawable.Drawable
1225     * @see #getDrawableState()
1226     */
1227    protected static final int[] PRESSED_STATE_SET;
1228    /**
1229     * Indicates the view's window has focus. States are used with
1230     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1231     * view depending on its state.
1232     *
1233     * @see android.graphics.drawable.Drawable
1234     * @see #getDrawableState()
1235     */
1236    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1237    // Doubles
1238    /**
1239     * Indicates the view is enabled and has the focus.
1240     *
1241     * @see #ENABLED_STATE_SET
1242     * @see #FOCUSED_STATE_SET
1243     */
1244    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1245    /**
1246     * Indicates the view is enabled and selected.
1247     *
1248     * @see #ENABLED_STATE_SET
1249     * @see #SELECTED_STATE_SET
1250     */
1251    protected static final int[] ENABLED_SELECTED_STATE_SET;
1252    /**
1253     * Indicates the view is enabled and that its window has focus.
1254     *
1255     * @see #ENABLED_STATE_SET
1256     * @see #WINDOW_FOCUSED_STATE_SET
1257     */
1258    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1259    /**
1260     * Indicates the view is focused and selected.
1261     *
1262     * @see #FOCUSED_STATE_SET
1263     * @see #SELECTED_STATE_SET
1264     */
1265    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1266    /**
1267     * Indicates the view has the focus and that its window has the focus.
1268     *
1269     * @see #FOCUSED_STATE_SET
1270     * @see #WINDOW_FOCUSED_STATE_SET
1271     */
1272    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1273    /**
1274     * Indicates the view is selected and that its window has the focus.
1275     *
1276     * @see #SELECTED_STATE_SET
1277     * @see #WINDOW_FOCUSED_STATE_SET
1278     */
1279    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1280    // Triples
1281    /**
1282     * Indicates the view is enabled, focused and selected.
1283     *
1284     * @see #ENABLED_STATE_SET
1285     * @see #FOCUSED_STATE_SET
1286     * @see #SELECTED_STATE_SET
1287     */
1288    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1289    /**
1290     * Indicates the view is enabled, focused and its window has the focus.
1291     *
1292     * @see #ENABLED_STATE_SET
1293     * @see #FOCUSED_STATE_SET
1294     * @see #WINDOW_FOCUSED_STATE_SET
1295     */
1296    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1297    /**
1298     * Indicates the view is enabled, selected and its window has the focus.
1299     *
1300     * @see #ENABLED_STATE_SET
1301     * @see #SELECTED_STATE_SET
1302     * @see #WINDOW_FOCUSED_STATE_SET
1303     */
1304    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1305    /**
1306     * Indicates the view is focused, selected and its window has the focus.
1307     *
1308     * @see #FOCUSED_STATE_SET
1309     * @see #SELECTED_STATE_SET
1310     * @see #WINDOW_FOCUSED_STATE_SET
1311     */
1312    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1313    /**
1314     * Indicates the view is enabled, focused, selected and its window
1315     * has the focus.
1316     *
1317     * @see #ENABLED_STATE_SET
1318     * @see #FOCUSED_STATE_SET
1319     * @see #SELECTED_STATE_SET
1320     * @see #WINDOW_FOCUSED_STATE_SET
1321     */
1322    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1323    /**
1324     * Indicates the view is pressed and its window has the focus.
1325     *
1326     * @see #PRESSED_STATE_SET
1327     * @see #WINDOW_FOCUSED_STATE_SET
1328     */
1329    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1330    /**
1331     * Indicates the view is pressed and selected.
1332     *
1333     * @see #PRESSED_STATE_SET
1334     * @see #SELECTED_STATE_SET
1335     */
1336    protected static final int[] PRESSED_SELECTED_STATE_SET;
1337    /**
1338     * Indicates the view is pressed, selected and its window has the focus.
1339     *
1340     * @see #PRESSED_STATE_SET
1341     * @see #SELECTED_STATE_SET
1342     * @see #WINDOW_FOCUSED_STATE_SET
1343     */
1344    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1345    /**
1346     * Indicates the view is pressed and focused.
1347     *
1348     * @see #PRESSED_STATE_SET
1349     * @see #FOCUSED_STATE_SET
1350     */
1351    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1352    /**
1353     * Indicates the view is pressed, focused and its window has the focus.
1354     *
1355     * @see #PRESSED_STATE_SET
1356     * @see #FOCUSED_STATE_SET
1357     * @see #WINDOW_FOCUSED_STATE_SET
1358     */
1359    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1360    /**
1361     * Indicates the view is pressed, focused and selected.
1362     *
1363     * @see #PRESSED_STATE_SET
1364     * @see #SELECTED_STATE_SET
1365     * @see #FOCUSED_STATE_SET
1366     */
1367    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1368    /**
1369     * Indicates the view is pressed, focused, selected and its window has the focus.
1370     *
1371     * @see #PRESSED_STATE_SET
1372     * @see #FOCUSED_STATE_SET
1373     * @see #SELECTED_STATE_SET
1374     * @see #WINDOW_FOCUSED_STATE_SET
1375     */
1376    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1377    /**
1378     * Indicates the view is pressed and enabled.
1379     *
1380     * @see #PRESSED_STATE_SET
1381     * @see #ENABLED_STATE_SET
1382     */
1383    protected static final int[] PRESSED_ENABLED_STATE_SET;
1384    /**
1385     * Indicates the view is pressed, enabled and its window has the focus.
1386     *
1387     * @see #PRESSED_STATE_SET
1388     * @see #ENABLED_STATE_SET
1389     * @see #WINDOW_FOCUSED_STATE_SET
1390     */
1391    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1392    /**
1393     * Indicates the view is pressed, enabled and selected.
1394     *
1395     * @see #PRESSED_STATE_SET
1396     * @see #ENABLED_STATE_SET
1397     * @see #SELECTED_STATE_SET
1398     */
1399    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1400    /**
1401     * Indicates the view is pressed, enabled, selected and its window has the
1402     * focus.
1403     *
1404     * @see #PRESSED_STATE_SET
1405     * @see #ENABLED_STATE_SET
1406     * @see #SELECTED_STATE_SET
1407     * @see #WINDOW_FOCUSED_STATE_SET
1408     */
1409    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1410    /**
1411     * Indicates the view is pressed, enabled and focused.
1412     *
1413     * @see #PRESSED_STATE_SET
1414     * @see #ENABLED_STATE_SET
1415     * @see #FOCUSED_STATE_SET
1416     */
1417    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1418    /**
1419     * Indicates the view is pressed, enabled, focused and its window has the
1420     * focus.
1421     *
1422     * @see #PRESSED_STATE_SET
1423     * @see #ENABLED_STATE_SET
1424     * @see #FOCUSED_STATE_SET
1425     * @see #WINDOW_FOCUSED_STATE_SET
1426     */
1427    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1428    /**
1429     * Indicates the view is pressed, enabled, focused and selected.
1430     *
1431     * @see #PRESSED_STATE_SET
1432     * @see #ENABLED_STATE_SET
1433     * @see #SELECTED_STATE_SET
1434     * @see #FOCUSED_STATE_SET
1435     */
1436    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1437    /**
1438     * Indicates the view is pressed, enabled, focused, selected and its window
1439     * has the focus.
1440     *
1441     * @see #PRESSED_STATE_SET
1442     * @see #ENABLED_STATE_SET
1443     * @see #SELECTED_STATE_SET
1444     * @see #FOCUSED_STATE_SET
1445     * @see #WINDOW_FOCUSED_STATE_SET
1446     */
1447    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1448
1449    static {
1450        EMPTY_STATE_SET = StateSet.get(0);
1451
1452        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1453
1454        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1455        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1456                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1457
1458        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1459        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1460                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1461        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1462                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1463        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1464                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1465                        | StateSet.VIEW_STATE_FOCUSED);
1466
1467        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1468        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1469                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1470        ENABLED_SELECTED_STATE_SET = StateSet.get(
1471                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1472        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1473                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1474                        | StateSet.VIEW_STATE_ENABLED);
1475        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1476                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1477        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1478                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1479                        | StateSet.VIEW_STATE_ENABLED);
1480        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1481                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1482                        | StateSet.VIEW_STATE_ENABLED);
1483        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1484                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1485                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1486
1487        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1488        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1489                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1490        PRESSED_SELECTED_STATE_SET = StateSet.get(
1491                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1492        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1493                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1494                        | StateSet.VIEW_STATE_PRESSED);
1495        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1496                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1497        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1498                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1499                        | StateSet.VIEW_STATE_PRESSED);
1500        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1501                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1502                        | StateSet.VIEW_STATE_PRESSED);
1503        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1504                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1505                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1506        PRESSED_ENABLED_STATE_SET = StateSet.get(
1507                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1508        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1509                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1510                        | StateSet.VIEW_STATE_PRESSED);
1511        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1512                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1513                        | StateSet.VIEW_STATE_PRESSED);
1514        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1515                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1516                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1517        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1518                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1519                        | StateSet.VIEW_STATE_PRESSED);
1520        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1521                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1522                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1523        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1524                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1525                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1526        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1527                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1528                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1529                        | StateSet.VIEW_STATE_PRESSED);
1530    }
1531
1532    /**
1533     * Accessibility event types that are dispatched for text population.
1534     */
1535    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1536            AccessibilityEvent.TYPE_VIEW_CLICKED
1537            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1538            | AccessibilityEvent.TYPE_VIEW_SELECTED
1539            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1540            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1541            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1542            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1543            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1544            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1545            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1546            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1547
1548    /**
1549     * Temporary Rect currently for use in setBackground().  This will probably
1550     * be extended in the future to hold our own class with more than just
1551     * a Rect. :)
1552     */
1553    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1554
1555    /**
1556     * Map used to store views' tags.
1557     */
1558    private SparseArray<Object> mKeyedTags;
1559
1560    /**
1561     * The next available accessibility id.
1562     */
1563    private static int sNextAccessibilityViewId;
1564
1565    /**
1566     * The animation currently associated with this view.
1567     * @hide
1568     */
1569    protected Animation mCurrentAnimation = null;
1570
1571    /**
1572     * Width as measured during measure pass.
1573     * {@hide}
1574     */
1575    @ViewDebug.ExportedProperty(category = "measurement")
1576    int mMeasuredWidth;
1577
1578    /**
1579     * Height as measured during measure pass.
1580     * {@hide}
1581     */
1582    @ViewDebug.ExportedProperty(category = "measurement")
1583    int mMeasuredHeight;
1584
1585    /**
1586     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1587     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1588     * its display list. This flag, used only when hw accelerated, allows us to clear the
1589     * flag while retaining this information until it's needed (at getDisplayList() time and
1590     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1591     *
1592     * {@hide}
1593     */
1594    boolean mRecreateDisplayList = false;
1595
1596    /**
1597     * The view's identifier.
1598     * {@hide}
1599     *
1600     * @see #setId(int)
1601     * @see #getId()
1602     */
1603    @IdRes
1604    @ViewDebug.ExportedProperty(resolveId = true)
1605    int mID = NO_ID;
1606
1607    /**
1608     * The stable ID of this view for accessibility purposes.
1609     */
1610    int mAccessibilityViewId = NO_ID;
1611
1612    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1613
1614    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1615
1616    /**
1617     * The view's tag.
1618     * {@hide}
1619     *
1620     * @see #setTag(Object)
1621     * @see #getTag()
1622     */
1623    protected Object mTag = null;
1624
1625    // for mPrivateFlags:
1626    /** {@hide} */
1627    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1628    /** {@hide} */
1629    static final int PFLAG_FOCUSED                     = 0x00000002;
1630    /** {@hide} */
1631    static final int PFLAG_SELECTED                    = 0x00000004;
1632    /** {@hide} */
1633    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1634    /** {@hide} */
1635    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1636    /** {@hide} */
1637    static final int PFLAG_DRAWN                       = 0x00000020;
1638    /**
1639     * When this flag is set, this view is running an animation on behalf of its
1640     * children and should therefore not cancel invalidate requests, even if they
1641     * lie outside of this view's bounds.
1642     *
1643     * {@hide}
1644     */
1645    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1646    /** {@hide} */
1647    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1648    /** {@hide} */
1649    static final int PFLAG_ONLY_DRAWS_BACKGROUND       = 0x00000100;
1650    /** {@hide} */
1651    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1652    /** {@hide} */
1653    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1654    /** {@hide} */
1655    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1656    /** {@hide} */
1657    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1658    /** {@hide} */
1659    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1660
1661    private static final int PFLAG_PRESSED             = 0x00004000;
1662
1663    /** {@hide} */
1664    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1665    /**
1666     * Flag used to indicate that this view should be drawn once more (and only once
1667     * more) after its animation has completed.
1668     * {@hide}
1669     */
1670    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1671
1672    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1673
1674    /**
1675     * Indicates that the View returned true when onSetAlpha() was called and that
1676     * the alpha must be restored.
1677     * {@hide}
1678     */
1679    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1680
1681    /**
1682     * Set by {@link #setScrollContainer(boolean)}.
1683     */
1684    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1685
1686    /**
1687     * Set by {@link #setScrollContainer(boolean)}.
1688     */
1689    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1690
1691    /**
1692     * View flag indicating whether this view was invalidated (fully or partially.)
1693     *
1694     * @hide
1695     */
1696    static final int PFLAG_DIRTY                       = 0x00200000;
1697
1698    /**
1699     * View flag indicating whether this view was invalidated by an opaque
1700     * invalidate request.
1701     *
1702     * @hide
1703     */
1704    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1705
1706    /**
1707     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1708     *
1709     * @hide
1710     */
1711    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1712
1713    /**
1714     * Indicates whether the background is opaque.
1715     *
1716     * @hide
1717     */
1718    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1719
1720    /**
1721     * Indicates whether the scrollbars are opaque.
1722     *
1723     * @hide
1724     */
1725    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1726
1727    /**
1728     * Indicates whether the view is opaque.
1729     *
1730     * @hide
1731     */
1732    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1733
1734    /**
1735     * Indicates a prepressed state;
1736     * the short time between ACTION_DOWN and recognizing
1737     * a 'real' press. Prepressed is used to recognize quick taps
1738     * even when they are shorter than ViewConfiguration.getTapTimeout().
1739     *
1740     * @hide
1741     */
1742    private static final int PFLAG_PREPRESSED          = 0x02000000;
1743
1744    /**
1745     * Indicates whether the view is temporarily detached.
1746     *
1747     * @hide
1748     */
1749    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1750
1751    /**
1752     * Indicates that we should awaken scroll bars once attached
1753     *
1754     * @hide
1755     */
1756    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1757
1758    /**
1759     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1760     * @hide
1761     */
1762    private static final int PFLAG_HOVERED             = 0x10000000;
1763
1764    /**
1765     * no longer needed, should be reused
1766     */
1767    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1768
1769    /** {@hide} */
1770    static final int PFLAG_ACTIVATED                   = 0x40000000;
1771
1772    /**
1773     * Indicates that this view was specifically invalidated, not just dirtied because some
1774     * child view was invalidated. The flag is used to determine when we need to recreate
1775     * a view's display list (as opposed to just returning a reference to its existing
1776     * display list).
1777     *
1778     * @hide
1779     */
1780    static final int PFLAG_INVALIDATED                 = 0x80000000;
1781
1782    /**
1783     * Masks for mPrivateFlags2, as generated by dumpFlags():
1784     *
1785     * |-------|-------|-------|-------|
1786     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1787     *                                1  PFLAG2_DRAG_HOVERED
1788     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1789     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1790     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1791     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1792     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1793     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1794     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1795     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1796     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1797     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1798     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1799     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1800     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1801     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1802     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1803     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1804     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1805     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1806     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1807     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1808     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1809     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1810     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1811     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1812     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1813     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1814     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1815     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1816     *    1                              PFLAG2_PADDING_RESOLVED
1817     *   1                               PFLAG2_DRAWABLE_RESOLVED
1818     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1819     * |-------|-------|-------|-------|
1820     */
1821
1822    /**
1823     * Indicates that this view has reported that it can accept the current drag's content.
1824     * Cleared when the drag operation concludes.
1825     * @hide
1826     */
1827    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1828
1829    /**
1830     * Indicates that this view is currently directly under the drag location in a
1831     * drag-and-drop operation involving content that it can accept.  Cleared when
1832     * the drag exits the view, or when the drag operation concludes.
1833     * @hide
1834     */
1835    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1836
1837    /** @hide */
1838    @IntDef({
1839        LAYOUT_DIRECTION_LTR,
1840        LAYOUT_DIRECTION_RTL,
1841        LAYOUT_DIRECTION_INHERIT,
1842        LAYOUT_DIRECTION_LOCALE
1843    })
1844    @Retention(RetentionPolicy.SOURCE)
1845    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1846    public @interface LayoutDir {}
1847
1848    /** @hide */
1849    @IntDef({
1850        LAYOUT_DIRECTION_LTR,
1851        LAYOUT_DIRECTION_RTL
1852    })
1853    @Retention(RetentionPolicy.SOURCE)
1854    public @interface ResolvedLayoutDir {}
1855
1856    /**
1857     * Horizontal layout direction of this view is from Left to Right.
1858     * Use with {@link #setLayoutDirection}.
1859     */
1860    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1861
1862    /**
1863     * Horizontal layout direction of this view is from Right to Left.
1864     * Use with {@link #setLayoutDirection}.
1865     */
1866    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1867
1868    /**
1869     * Horizontal layout direction of this view is inherited from its parent.
1870     * Use with {@link #setLayoutDirection}.
1871     */
1872    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1873
1874    /**
1875     * Horizontal layout direction of this view is from deduced from the default language
1876     * script for the locale. Use with {@link #setLayoutDirection}.
1877     */
1878    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1879
1880    /**
1881     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1882     * @hide
1883     */
1884    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1885
1886    /**
1887     * Mask for use with private flags indicating bits used for horizontal layout direction.
1888     * @hide
1889     */
1890    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1891
1892    /**
1893     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1894     * right-to-left direction.
1895     * @hide
1896     */
1897    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1898
1899    /**
1900     * Indicates whether the view horizontal layout direction has been resolved.
1901     * @hide
1902     */
1903    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1904
1905    /**
1906     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1907     * @hide
1908     */
1909    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1910            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1911
1912    /*
1913     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1914     * flag value.
1915     * @hide
1916     */
1917    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1918            LAYOUT_DIRECTION_LTR,
1919            LAYOUT_DIRECTION_RTL,
1920            LAYOUT_DIRECTION_INHERIT,
1921            LAYOUT_DIRECTION_LOCALE
1922    };
1923
1924    /**
1925     * Default horizontal layout direction.
1926     */
1927    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1928
1929    /**
1930     * Default horizontal layout direction.
1931     * @hide
1932     */
1933    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1934
1935    /**
1936     * Text direction is inherited through {@link ViewGroup}
1937     */
1938    public static final int TEXT_DIRECTION_INHERIT = 0;
1939
1940    /**
1941     * Text direction is using "first strong algorithm". The first strong directional character
1942     * determines the paragraph direction. If there is no strong directional character, the
1943     * paragraph direction is the view's resolved layout direction.
1944     */
1945    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1946
1947    /**
1948     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1949     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1950     * If there are neither, the paragraph direction is the view's resolved layout direction.
1951     */
1952    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1953
1954    /**
1955     * Text direction is forced to LTR.
1956     */
1957    public static final int TEXT_DIRECTION_LTR = 3;
1958
1959    /**
1960     * Text direction is forced to RTL.
1961     */
1962    public static final int TEXT_DIRECTION_RTL = 4;
1963
1964    /**
1965     * Text direction is coming from the system Locale.
1966     */
1967    public static final int TEXT_DIRECTION_LOCALE = 5;
1968
1969    /**
1970     * Default text direction is inherited
1971     */
1972    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
1973
1974    /**
1975     * Default resolved text direction
1976     * @hide
1977     */
1978    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
1979
1980    /**
1981     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1982     * @hide
1983     */
1984    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
1985
1986    /**
1987     * Mask for use with private flags indicating bits used for text direction.
1988     * @hide
1989     */
1990    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1991            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
1992
1993    /**
1994     * Array of text direction flags for mapping attribute "textDirection" to correct
1995     * flag value.
1996     * @hide
1997     */
1998    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1999            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2000            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2001            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2002            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2003            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2004            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2005    };
2006
2007    /**
2008     * Indicates whether the view text direction has been resolved.
2009     * @hide
2010     */
2011    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2012            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2013
2014    /**
2015     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2016     * @hide
2017     */
2018    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2019
2020    /**
2021     * Mask for use with private flags indicating bits used for resolved text direction.
2022     * @hide
2023     */
2024    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2025            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2026
2027    /**
2028     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2029     * @hide
2030     */
2031    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2032            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2033
2034    /** @hide */
2035    @IntDef({
2036        TEXT_ALIGNMENT_INHERIT,
2037        TEXT_ALIGNMENT_GRAVITY,
2038        TEXT_ALIGNMENT_CENTER,
2039        TEXT_ALIGNMENT_TEXT_START,
2040        TEXT_ALIGNMENT_TEXT_END,
2041        TEXT_ALIGNMENT_VIEW_START,
2042        TEXT_ALIGNMENT_VIEW_END
2043    })
2044    @Retention(RetentionPolicy.SOURCE)
2045    public @interface TextAlignment {}
2046
2047    /**
2048     * Default text alignment. The text alignment of this View is inherited from its parent.
2049     * Use with {@link #setTextAlignment(int)}
2050     */
2051    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2052
2053    /**
2054     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2055     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2056     *
2057     * Use with {@link #setTextAlignment(int)}
2058     */
2059    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2060
2061    /**
2062     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2063     *
2064     * Use with {@link #setTextAlignment(int)}
2065     */
2066    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2067
2068    /**
2069     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2070     *
2071     * Use with {@link #setTextAlignment(int)}
2072     */
2073    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2074
2075    /**
2076     * Center the paragraph, e.g. ALIGN_CENTER.
2077     *
2078     * Use with {@link #setTextAlignment(int)}
2079     */
2080    public static final int TEXT_ALIGNMENT_CENTER = 4;
2081
2082    /**
2083     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2084     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2085     *
2086     * Use with {@link #setTextAlignment(int)}
2087     */
2088    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2089
2090    /**
2091     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2092     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2093     *
2094     * Use with {@link #setTextAlignment(int)}
2095     */
2096    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2097
2098    /**
2099     * Default text alignment is inherited
2100     */
2101    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2102
2103    /**
2104     * Default resolved text alignment
2105     * @hide
2106     */
2107    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2108
2109    /**
2110      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2111      * @hide
2112      */
2113    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2114
2115    /**
2116      * Mask for use with private flags indicating bits used for text alignment.
2117      * @hide
2118      */
2119    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2120
2121    /**
2122     * Array of text direction flags for mapping attribute "textAlignment" to correct
2123     * flag value.
2124     * @hide
2125     */
2126    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2127            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2128            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2129            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2130            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2131            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2132            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2133            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2134    };
2135
2136    /**
2137     * Indicates whether the view text alignment has been resolved.
2138     * @hide
2139     */
2140    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2141
2142    /**
2143     * Bit shift to get the resolved text alignment.
2144     * @hide
2145     */
2146    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2147
2148    /**
2149     * Mask for use with private flags indicating bits used for text alignment.
2150     * @hide
2151     */
2152    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2153            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2154
2155    /**
2156     * Indicates whether if the view text alignment has been resolved to gravity
2157     */
2158    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2159            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2160
2161    // Accessiblity constants for mPrivateFlags2
2162
2163    /**
2164     * Shift for the bits in {@link #mPrivateFlags2} related to the
2165     * "importantForAccessibility" attribute.
2166     */
2167    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2168
2169    /**
2170     * Automatically determine whether a view is important for accessibility.
2171     */
2172    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2173
2174    /**
2175     * The view is important for accessibility.
2176     */
2177    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2178
2179    /**
2180     * The view is not important for accessibility.
2181     */
2182    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2183
2184    /**
2185     * The view is not important for accessibility, nor are any of its
2186     * descendant views.
2187     */
2188    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2189
2190    /**
2191     * The default whether the view is important for accessibility.
2192     */
2193    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2194
2195    /**
2196     * Mask for obtainig the bits which specify how to determine
2197     * whether a view is important for accessibility.
2198     */
2199    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2200        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2201        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2202        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2203
2204    /**
2205     * Shift for the bits in {@link #mPrivateFlags2} related to the
2206     * "accessibilityLiveRegion" attribute.
2207     */
2208    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2209
2210    /**
2211     * Live region mode specifying that accessibility services should not
2212     * automatically announce changes to this view. This is the default live
2213     * region mode for most views.
2214     * <p>
2215     * Use with {@link #setAccessibilityLiveRegion(int)}.
2216     */
2217    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2218
2219    /**
2220     * Live region mode specifying that accessibility services should announce
2221     * changes to this view.
2222     * <p>
2223     * Use with {@link #setAccessibilityLiveRegion(int)}.
2224     */
2225    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2226
2227    /**
2228     * Live region mode specifying that accessibility services should interrupt
2229     * ongoing speech to immediately announce changes to this view.
2230     * <p>
2231     * Use with {@link #setAccessibilityLiveRegion(int)}.
2232     */
2233    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2234
2235    /**
2236     * The default whether the view is important for accessibility.
2237     */
2238    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2239
2240    /**
2241     * Mask for obtaining the bits which specify a view's accessibility live
2242     * region mode.
2243     */
2244    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2245            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2246            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2247
2248    /**
2249     * Flag indicating whether a view has accessibility focus.
2250     */
2251    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2252
2253    /**
2254     * Flag whether the accessibility state of the subtree rooted at this view changed.
2255     */
2256    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2257
2258    /**
2259     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2260     * is used to check whether later changes to the view's transform should invalidate the
2261     * view to force the quickReject test to run again.
2262     */
2263    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2264
2265    /**
2266     * Flag indicating that start/end padding has been resolved into left/right padding
2267     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2268     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2269     * during measurement. In some special cases this is required such as when an adapter-based
2270     * view measures prospective children without attaching them to a window.
2271     */
2272    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2273
2274    /**
2275     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2276     */
2277    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2278
2279    /**
2280     * Indicates that the view is tracking some sort of transient state
2281     * that the app should not need to be aware of, but that the framework
2282     * should take special care to preserve.
2283     */
2284    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2285
2286    /**
2287     * Group of bits indicating that RTL properties resolution is done.
2288     */
2289    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2290            PFLAG2_TEXT_DIRECTION_RESOLVED |
2291            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2292            PFLAG2_PADDING_RESOLVED |
2293            PFLAG2_DRAWABLE_RESOLVED;
2294
2295    // There are a couple of flags left in mPrivateFlags2
2296
2297    /* End of masks for mPrivateFlags2 */
2298
2299    /**
2300     * Masks for mPrivateFlags3, as generated by dumpFlags():
2301     *
2302     * |-------|-------|-------|-------|
2303     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2304     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2305     *                               1   PFLAG3_IS_LAID_OUT
2306     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2307     *                             1     PFLAG3_CALLED_SUPER
2308     * |-------|-------|-------|-------|
2309     */
2310
2311    /**
2312     * Flag indicating that view has a transform animation set on it. This is used to track whether
2313     * an animation is cleared between successive frames, in order to tell the associated
2314     * DisplayList to clear its animation matrix.
2315     */
2316    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2317
2318    /**
2319     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2320     * animation is cleared between successive frames, in order to tell the associated
2321     * DisplayList to restore its alpha value.
2322     */
2323    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2324
2325    /**
2326     * Flag indicating that the view has been through at least one layout since it
2327     * was last attached to a window.
2328     */
2329    static final int PFLAG3_IS_LAID_OUT = 0x4;
2330
2331    /**
2332     * Flag indicating that a call to measure() was skipped and should be done
2333     * instead when layout() is invoked.
2334     */
2335    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2336
2337    /**
2338     * Flag indicating that an overridden method correctly called down to
2339     * the superclass implementation as required by the API spec.
2340     */
2341    static final int PFLAG3_CALLED_SUPER = 0x10;
2342
2343    /**
2344     * Flag indicating that we're in the process of applying window insets.
2345     */
2346    static final int PFLAG3_APPLYING_INSETS = 0x20;
2347
2348    /**
2349     * Flag indicating that we're in the process of fitting system windows using the old method.
2350     */
2351    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2352
2353    /**
2354     * Flag indicating that nested scrolling is enabled for this view.
2355     * The view will optionally cooperate with views up its parent chain to allow for
2356     * integrated nested scrolling along the same axis.
2357     */
2358    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2359
2360    /* End of masks for mPrivateFlags3 */
2361
2362    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2363
2364    /**
2365     * Always allow a user to over-scroll this view, provided it is a
2366     * view that can scroll.
2367     *
2368     * @see #getOverScrollMode()
2369     * @see #setOverScrollMode(int)
2370     */
2371    public static final int OVER_SCROLL_ALWAYS = 0;
2372
2373    /**
2374     * Allow a user to over-scroll this view only if the content is large
2375     * enough to meaningfully scroll, provided it is a view that can scroll.
2376     *
2377     * @see #getOverScrollMode()
2378     * @see #setOverScrollMode(int)
2379     */
2380    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2381
2382    /**
2383     * Never allow a user to over-scroll this view.
2384     *
2385     * @see #getOverScrollMode()
2386     * @see #setOverScrollMode(int)
2387     */
2388    public static final int OVER_SCROLL_NEVER = 2;
2389
2390    /**
2391     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2392     * requested the system UI (status bar) to be visible (the default).
2393     *
2394     * @see #setSystemUiVisibility(int)
2395     */
2396    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2397
2398    /**
2399     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2400     * system UI to enter an unobtrusive "low profile" mode.
2401     *
2402     * <p>This is for use in games, book readers, video players, or any other
2403     * "immersive" application where the usual system chrome is deemed too distracting.
2404     *
2405     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2406     *
2407     * @see #setSystemUiVisibility(int)
2408     */
2409    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2410
2411    /**
2412     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2413     * system navigation be temporarily hidden.
2414     *
2415     * <p>This is an even less obtrusive state than that called for by
2416     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2417     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2418     * those to disappear. This is useful (in conjunction with the
2419     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2420     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2421     * window flags) for displaying content using every last pixel on the display.
2422     *
2423     * <p>There is a limitation: because navigation controls are so important, the least user
2424     * interaction will cause them to reappear immediately.  When this happens, both
2425     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2426     * so that both elements reappear at the same time.
2427     *
2428     * @see #setSystemUiVisibility(int)
2429     */
2430    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2431
2432    /**
2433     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2434     * into the normal fullscreen mode so that its content can take over the screen
2435     * while still allowing the user to interact with the application.
2436     *
2437     * <p>This has the same visual effect as
2438     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2439     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2440     * meaning that non-critical screen decorations (such as the status bar) will be
2441     * hidden while the user is in the View's window, focusing the experience on
2442     * that content.  Unlike the window flag, if you are using ActionBar in
2443     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2444     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2445     * hide the action bar.
2446     *
2447     * <p>This approach to going fullscreen is best used over the window flag when
2448     * it is a transient state -- that is, the application does this at certain
2449     * points in its user interaction where it wants to allow the user to focus
2450     * on content, but not as a continuous state.  For situations where the application
2451     * would like to simply stay full screen the entire time (such as a game that
2452     * wants to take over the screen), the
2453     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2454     * is usually a better approach.  The state set here will be removed by the system
2455     * in various situations (such as the user moving to another application) like
2456     * the other system UI states.
2457     *
2458     * <p>When using this flag, the application should provide some easy facility
2459     * for the user to go out of it.  A common example would be in an e-book
2460     * reader, where tapping on the screen brings back whatever screen and UI
2461     * decorations that had been hidden while the user was immersed in reading
2462     * the book.
2463     *
2464     * @see #setSystemUiVisibility(int)
2465     */
2466    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2467
2468    /**
2469     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2470     * flags, we would like a stable view of the content insets given to
2471     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2472     * will always represent the worst case that the application can expect
2473     * as a continuous state.  In the stock Android UI this is the space for
2474     * the system bar, nav bar, and status bar, but not more transient elements
2475     * such as an input method.
2476     *
2477     * The stable layout your UI sees is based on the system UI modes you can
2478     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2479     * then you will get a stable layout for changes of the
2480     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2481     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2482     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2483     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2484     * with a stable layout.  (Note that you should avoid using
2485     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2486     *
2487     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2488     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2489     * then a hidden status bar will be considered a "stable" state for purposes
2490     * here.  This allows your UI to continually hide the status bar, while still
2491     * using the system UI flags to hide the action bar while still retaining
2492     * a stable layout.  Note that changing the window fullscreen flag will never
2493     * provide a stable layout for a clean transition.
2494     *
2495     * <p>If you are using ActionBar in
2496     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2497     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2498     * insets it adds to those given to the application.
2499     */
2500    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2501
2502    /**
2503     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2504     * to be laid out as if it has requested
2505     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2506     * allows it to avoid artifacts when switching in and out of that mode, at
2507     * the expense that some of its user interface may be covered by screen
2508     * decorations when they are shown.  You can perform layout of your inner
2509     * UI elements to account for the navigation system UI through the
2510     * {@link #fitSystemWindows(Rect)} method.
2511     */
2512    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2513
2514    /**
2515     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2516     * to be laid out as if it has requested
2517     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2518     * allows it to avoid artifacts when switching in and out of that mode, at
2519     * the expense that some of its user interface may be covered by screen
2520     * decorations when they are shown.  You can perform layout of your inner
2521     * UI elements to account for non-fullscreen system UI through the
2522     * {@link #fitSystemWindows(Rect)} method.
2523     */
2524    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2525
2526    /**
2527     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2528     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2529     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2530     * user interaction.
2531     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2532     * has an effect when used in combination with that flag.</p>
2533     */
2534    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2535
2536    /**
2537     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2538     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2539     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2540     * experience while also hiding the system bars.  If this flag is not set,
2541     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2542     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2543     * if the user swipes from the top of the screen.
2544     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2545     * system gestures, such as swiping from the top of the screen.  These transient system bars
2546     * will overlay app’s content, may have some degree of transparency, and will automatically
2547     * hide after a short timeout.
2548     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2549     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2550     * with one or both of those flags.</p>
2551     */
2552    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2553
2554    /**
2555     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2556     * is compatible with light status bar backgrounds.
2557     *
2558     * <p>For this to take effect, the window must request
2559     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2560     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2561     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2562     *         FLAG_TRANSLUCENT_STATUS}.
2563     *
2564     * @see android.R.attr#windowHasLightStatusBar
2565     */
2566    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2567
2568    /**
2569     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2570     */
2571    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2572
2573    /**
2574     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2575     */
2576    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2577
2578    /**
2579     * @hide
2580     *
2581     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2582     * out of the public fields to keep the undefined bits out of the developer's way.
2583     *
2584     * Flag to make the status bar not expandable.  Unless you also
2585     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2586     */
2587    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2588
2589    /**
2590     * @hide
2591     *
2592     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2593     * out of the public fields to keep the undefined bits out of the developer's way.
2594     *
2595     * Flag to hide notification icons and scrolling ticker text.
2596     */
2597    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2598
2599    /**
2600     * @hide
2601     *
2602     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2603     * out of the public fields to keep the undefined bits out of the developer's way.
2604     *
2605     * Flag to disable incoming notification alerts.  This will not block
2606     * icons, but it will block sound, vibrating and other visual or aural notifications.
2607     */
2608    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2609
2610    /**
2611     * @hide
2612     *
2613     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2614     * out of the public fields to keep the undefined bits out of the developer's way.
2615     *
2616     * Flag to hide only the scrolling ticker.  Note that
2617     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2618     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2619     */
2620    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2621
2622    /**
2623     * @hide
2624     *
2625     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2626     * out of the public fields to keep the undefined bits out of the developer's way.
2627     *
2628     * Flag to hide the center system info area.
2629     */
2630    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2631
2632    /**
2633     * @hide
2634     *
2635     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2636     * out of the public fields to keep the undefined bits out of the developer's way.
2637     *
2638     * Flag to hide only the home button.  Don't use this
2639     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2640     */
2641    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2642
2643    /**
2644     * @hide
2645     *
2646     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2647     * out of the public fields to keep the undefined bits out of the developer's way.
2648     *
2649     * Flag to hide only the back button. Don't use this
2650     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2651     */
2652    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2653
2654    /**
2655     * @hide
2656     *
2657     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2658     * out of the public fields to keep the undefined bits out of the developer's way.
2659     *
2660     * Flag to hide only the clock.  You might use this if your activity has
2661     * its own clock making the status bar's clock redundant.
2662     */
2663    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2664
2665    /**
2666     * @hide
2667     *
2668     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2669     * out of the public fields to keep the undefined bits out of the developer's way.
2670     *
2671     * Flag to hide only the recent apps button. Don't use this
2672     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2673     */
2674    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2675
2676    /**
2677     * @hide
2678     *
2679     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2680     * out of the public fields to keep the undefined bits out of the developer's way.
2681     *
2682     * Flag to disable the global search gesture. Don't use this
2683     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2684     */
2685    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2686
2687    /**
2688     * @hide
2689     *
2690     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2691     * out of the public fields to keep the undefined bits out of the developer's way.
2692     *
2693     * Flag to specify that the status bar is displayed in transient mode.
2694     */
2695    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2696
2697    /**
2698     * @hide
2699     *
2700     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2701     * out of the public fields to keep the undefined bits out of the developer's way.
2702     *
2703     * Flag to specify that the navigation bar is displayed in transient mode.
2704     */
2705    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2706
2707    /**
2708     * @hide
2709     *
2710     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2711     * out of the public fields to keep the undefined bits out of the developer's way.
2712     *
2713     * Flag to specify that the hidden status bar would like to be shown.
2714     */
2715    public static final int STATUS_BAR_UNHIDE = 0x10000000;
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 hidden navigation bar would like to be shown.
2724     */
2725    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
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 status bar is displayed in translucent mode.
2734     */
2735    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
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 navigation bar is displayed in translucent mode.
2744     */
2745    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2746
2747    /**
2748     * @hide
2749     *
2750     * Whether Recents is visible or not.
2751     */
2752    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2753
2754    /**
2755     * @hide
2756     *
2757     * Makes system ui transparent.
2758     */
2759    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2760
2761    /**
2762     * @hide
2763     */
2764    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2765
2766    /**
2767     * These are the system UI flags that can be cleared by events outside
2768     * of an application.  Currently this is just the ability to tap on the
2769     * screen while hiding the navigation bar to have it return.
2770     * @hide
2771     */
2772    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2773            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2774            | SYSTEM_UI_FLAG_FULLSCREEN;
2775
2776    /**
2777     * Flags that can impact the layout in relation to system UI.
2778     */
2779    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2780            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2781            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2782
2783    /** @hide */
2784    @IntDef(flag = true,
2785            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2786    @Retention(RetentionPolicy.SOURCE)
2787    public @interface FindViewFlags {}
2788
2789    /**
2790     * Find views that render the specified text.
2791     *
2792     * @see #findViewsWithText(ArrayList, CharSequence, int)
2793     */
2794    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2795
2796    /**
2797     * Find find views that contain the specified content description.
2798     *
2799     * @see #findViewsWithText(ArrayList, CharSequence, int)
2800     */
2801    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2802
2803    /**
2804     * Find views that contain {@link AccessibilityNodeProvider}. Such
2805     * a View is a root of virtual view hierarchy and may contain the searched
2806     * text. If this flag is set Views with providers are automatically
2807     * added and it is a responsibility of the client to call the APIs of
2808     * the provider to determine whether the virtual tree rooted at this View
2809     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2810     * representing the virtual views with this text.
2811     *
2812     * @see #findViewsWithText(ArrayList, CharSequence, int)
2813     *
2814     * @hide
2815     */
2816    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2817
2818    /**
2819     * The undefined cursor position.
2820     *
2821     * @hide
2822     */
2823    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2824
2825    /**
2826     * Indicates that the screen has changed state and is now off.
2827     *
2828     * @see #onScreenStateChanged(int)
2829     */
2830    public static final int SCREEN_STATE_OFF = 0x0;
2831
2832    /**
2833     * Indicates that the screen has changed state and is now on.
2834     *
2835     * @see #onScreenStateChanged(int)
2836     */
2837    public static final int SCREEN_STATE_ON = 0x1;
2838
2839    /**
2840     * Indicates no axis of view scrolling.
2841     */
2842    public static final int SCROLL_AXIS_NONE = 0;
2843
2844    /**
2845     * Indicates scrolling along the horizontal axis.
2846     */
2847    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
2848
2849    /**
2850     * Indicates scrolling along the vertical axis.
2851     */
2852    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
2853
2854    /**
2855     * Controls the over-scroll mode for this view.
2856     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2857     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2858     * and {@link #OVER_SCROLL_NEVER}.
2859     */
2860    private int mOverScrollMode;
2861
2862    /**
2863     * The parent this view is attached to.
2864     * {@hide}
2865     *
2866     * @see #getParent()
2867     */
2868    protected ViewParent mParent;
2869
2870    /**
2871     * {@hide}
2872     */
2873    AttachInfo mAttachInfo;
2874
2875    /**
2876     * {@hide}
2877     */
2878    @ViewDebug.ExportedProperty(flagMapping = {
2879        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
2880                name = "FORCE_LAYOUT"),
2881        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
2882                name = "LAYOUT_REQUIRED"),
2883        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
2884            name = "DRAWING_CACHE_INVALID", outputIf = false),
2885        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2886        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2887        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2888        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
2889    }, formatToHexString = true)
2890    int mPrivateFlags;
2891    int mPrivateFlags2;
2892    int mPrivateFlags3;
2893
2894    /**
2895     * This view's request for the visibility of the status bar.
2896     * @hide
2897     */
2898    @ViewDebug.ExportedProperty(flagMapping = {
2899        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2900                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2901                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2902        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2903                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2904                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2905        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2906                                equals = SYSTEM_UI_FLAG_VISIBLE,
2907                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2908    }, formatToHexString = true)
2909    int mSystemUiVisibility;
2910
2911    /**
2912     * Reference count for transient state.
2913     * @see #setHasTransientState(boolean)
2914     */
2915    int mTransientStateCount = 0;
2916
2917    /**
2918     * Count of how many windows this view has been attached to.
2919     */
2920    int mWindowAttachCount;
2921
2922    /**
2923     * The layout parameters associated with this view and used by the parent
2924     * {@link android.view.ViewGroup} to determine how this view should be
2925     * laid out.
2926     * {@hide}
2927     */
2928    protected ViewGroup.LayoutParams mLayoutParams;
2929
2930    /**
2931     * The view flags hold various views states.
2932     * {@hide}
2933     */
2934    @ViewDebug.ExportedProperty(formatToHexString = true)
2935    int mViewFlags;
2936
2937    static class TransformationInfo {
2938        /**
2939         * The transform matrix for the View. This transform is calculated internally
2940         * based on the translation, rotation, and scale properties.
2941         *
2942         * Do *not* use this variable directly; instead call getMatrix(), which will
2943         * load the value from the View's RenderNode.
2944         */
2945        private final Matrix mMatrix = new Matrix();
2946
2947        /**
2948         * The inverse transform matrix for the View. This transform is calculated
2949         * internally based on the translation, rotation, and scale properties.
2950         *
2951         * Do *not* use this variable directly; instead call getInverseMatrix(),
2952         * which will load the value from the View's RenderNode.
2953         */
2954        private Matrix mInverseMatrix;
2955
2956        /**
2957         * The opacity of the View. This is a value from 0 to 1, where 0 means
2958         * completely transparent and 1 means completely opaque.
2959         */
2960        @ViewDebug.ExportedProperty
2961        float mAlpha = 1f;
2962
2963        /**
2964         * The opacity of the view as manipulated by the Fade transition. This is a hidden
2965         * property only used by transitions, which is composited with the other alpha
2966         * values to calculate the final visual alpha value.
2967         */
2968        float mTransitionAlpha = 1f;
2969    }
2970
2971    TransformationInfo mTransformationInfo;
2972
2973    /**
2974     * Current clip bounds. to which all drawing of this view are constrained.
2975     */
2976    Rect mClipBounds = null;
2977
2978    private boolean mLastIsOpaque;
2979
2980    /**
2981     * The distance in pixels from the left edge of this view's parent
2982     * to the left edge of this view.
2983     * {@hide}
2984     */
2985    @ViewDebug.ExportedProperty(category = "layout")
2986    protected int mLeft;
2987    /**
2988     * The distance in pixels from the left edge of this view's parent
2989     * to the right edge of this view.
2990     * {@hide}
2991     */
2992    @ViewDebug.ExportedProperty(category = "layout")
2993    protected int mRight;
2994    /**
2995     * The distance in pixels from the top edge of this view's parent
2996     * to the top edge of this view.
2997     * {@hide}
2998     */
2999    @ViewDebug.ExportedProperty(category = "layout")
3000    protected int mTop;
3001    /**
3002     * The distance in pixels from the top edge of this view's parent
3003     * to the bottom edge of this view.
3004     * {@hide}
3005     */
3006    @ViewDebug.ExportedProperty(category = "layout")
3007    protected int mBottom;
3008
3009    /**
3010     * The offset, in pixels, by which the content of this view is scrolled
3011     * horizontally.
3012     * {@hide}
3013     */
3014    @ViewDebug.ExportedProperty(category = "scrolling")
3015    protected int mScrollX;
3016    /**
3017     * The offset, in pixels, by which the content of this view is scrolled
3018     * vertically.
3019     * {@hide}
3020     */
3021    @ViewDebug.ExportedProperty(category = "scrolling")
3022    protected int mScrollY;
3023
3024    /**
3025     * The left padding in pixels, that is the distance in pixels between the
3026     * left edge of this view and the left edge of its content.
3027     * {@hide}
3028     */
3029    @ViewDebug.ExportedProperty(category = "padding")
3030    protected int mPaddingLeft = 0;
3031    /**
3032     * The right padding in pixels, that is the distance in pixels between the
3033     * right edge of this view and the right edge of its content.
3034     * {@hide}
3035     */
3036    @ViewDebug.ExportedProperty(category = "padding")
3037    protected int mPaddingRight = 0;
3038    /**
3039     * The top padding in pixels, that is the distance in pixels between the
3040     * top edge of this view and the top edge of its content.
3041     * {@hide}
3042     */
3043    @ViewDebug.ExportedProperty(category = "padding")
3044    protected int mPaddingTop;
3045    /**
3046     * The bottom padding in pixels, that is the distance in pixels between the
3047     * bottom edge of this view and the bottom edge of its content.
3048     * {@hide}
3049     */
3050    @ViewDebug.ExportedProperty(category = "padding")
3051    protected int mPaddingBottom;
3052
3053    /**
3054     * The layout insets in pixels, that is the distance in pixels between the
3055     * visible edges of this view its bounds.
3056     */
3057    private Insets mLayoutInsets;
3058
3059    /**
3060     * Briefly describes the view and is primarily used for accessibility support.
3061     */
3062    private CharSequence mContentDescription;
3063
3064    /**
3065     * Specifies the id of a view for which this view serves as a label for
3066     * accessibility purposes.
3067     */
3068    private int mLabelForId = View.NO_ID;
3069
3070    /**
3071     * Predicate for matching labeled view id with its label for
3072     * accessibility purposes.
3073     */
3074    private MatchLabelForPredicate mMatchLabelForPredicate;
3075
3076    /**
3077     * Specifies a view before which this one is visited in accessibility traversal.
3078     */
3079    private int mAccessibilityTraversalBeforeId = NO_ID;
3080
3081    /**
3082     * Specifies a view after which this one is visited in accessibility traversal.
3083     */
3084    private int mAccessibilityTraversalAfterId = NO_ID;
3085
3086    /**
3087     * Predicate for matching a view by its id.
3088     */
3089    private MatchIdPredicate mMatchIdPredicate;
3090
3091    /**
3092     * Cache the paddingRight set by the user to append to the scrollbar's size.
3093     *
3094     * @hide
3095     */
3096    @ViewDebug.ExportedProperty(category = "padding")
3097    protected int mUserPaddingRight;
3098
3099    /**
3100     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3101     *
3102     * @hide
3103     */
3104    @ViewDebug.ExportedProperty(category = "padding")
3105    protected int mUserPaddingBottom;
3106
3107    /**
3108     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3109     *
3110     * @hide
3111     */
3112    @ViewDebug.ExportedProperty(category = "padding")
3113    protected int mUserPaddingLeft;
3114
3115    /**
3116     * Cache the paddingStart set by the user to append to the scrollbar's size.
3117     *
3118     */
3119    @ViewDebug.ExportedProperty(category = "padding")
3120    int mUserPaddingStart;
3121
3122    /**
3123     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3124     *
3125     */
3126    @ViewDebug.ExportedProperty(category = "padding")
3127    int mUserPaddingEnd;
3128
3129    /**
3130     * Cache initial left padding.
3131     *
3132     * @hide
3133     */
3134    int mUserPaddingLeftInitial;
3135
3136    /**
3137     * Cache initial right padding.
3138     *
3139     * @hide
3140     */
3141    int mUserPaddingRightInitial;
3142
3143    /**
3144     * Default undefined padding
3145     */
3146    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3147
3148    /**
3149     * Cache if a left padding has been defined
3150     */
3151    private boolean mLeftPaddingDefined = false;
3152
3153    /**
3154     * Cache if a right padding has been defined
3155     */
3156    private boolean mRightPaddingDefined = false;
3157
3158    /**
3159     * @hide
3160     */
3161    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3162    /**
3163     * @hide
3164     */
3165    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3166
3167    private LongSparseLongArray mMeasureCache;
3168
3169    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3170    private Drawable mBackground;
3171    private TintInfo mBackgroundTint;
3172
3173    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3174    private ForegroundInfo mForegroundInfo;
3175
3176    /**
3177     * RenderNode used for backgrounds.
3178     * <p>
3179     * When non-null and valid, this is expected to contain an up-to-date copy
3180     * of the background drawable. It is cleared on temporary detach, and reset
3181     * on cleanup.
3182     */
3183    private RenderNode mBackgroundRenderNode;
3184
3185    private int mBackgroundResource;
3186    private boolean mBackgroundSizeChanged;
3187
3188    private String mTransitionName;
3189
3190    static class TintInfo {
3191        ColorStateList mTintList;
3192        PorterDuff.Mode mTintMode;
3193        boolean mHasTintMode;
3194        boolean mHasTintList;
3195    }
3196
3197    private static class ForegroundInfo {
3198        private Drawable mDrawable;
3199        private TintInfo mTintInfo;
3200        private int mGravity = Gravity.FILL;
3201        private boolean mInsidePadding = true;
3202        private boolean mBoundsChanged = true;
3203        private final Rect mSelfBounds = new Rect();
3204        private final Rect mOverlayBounds = new Rect();
3205    }
3206
3207    static class ListenerInfo {
3208        /**
3209         * Listener used to dispatch focus change events.
3210         * This field should be made private, so it is hidden from the SDK.
3211         * {@hide}
3212         */
3213        protected OnFocusChangeListener mOnFocusChangeListener;
3214
3215        /**
3216         * Listeners for layout change events.
3217         */
3218        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3219
3220        protected OnScrollChangeListener mOnScrollChangeListener;
3221
3222        /**
3223         * Listeners for attach events.
3224         */
3225        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3226
3227        /**
3228         * Listener used to dispatch click events.
3229         * This field should be made private, so it is hidden from the SDK.
3230         * {@hide}
3231         */
3232        public OnClickListener mOnClickListener;
3233
3234        /**
3235         * Listener used to dispatch long click events.
3236         * This field should be made private, so it is hidden from the SDK.
3237         * {@hide}
3238         */
3239        protected OnLongClickListener mOnLongClickListener;
3240
3241        /**
3242         * Listener used to build the context menu.
3243         * This field should be made private, so it is hidden from the SDK.
3244         * {@hide}
3245         */
3246        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3247
3248        private OnKeyListener mOnKeyListener;
3249
3250        private OnTouchListener mOnTouchListener;
3251
3252        private OnHoverListener mOnHoverListener;
3253
3254        private OnGenericMotionListener mOnGenericMotionListener;
3255
3256        private OnDragListener mOnDragListener;
3257
3258        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3259
3260        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3261    }
3262
3263    ListenerInfo mListenerInfo;
3264
3265    /**
3266     * The application environment this view lives in.
3267     * This field should be made private, so it is hidden from the SDK.
3268     * {@hide}
3269     */
3270    @ViewDebug.ExportedProperty(deepExport = true)
3271    protected Context mContext;
3272
3273    private final Resources mResources;
3274
3275    private ScrollabilityCache mScrollCache;
3276
3277    private int[] mDrawableState = null;
3278
3279    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3280
3281    /**
3282     * Animator that automatically runs based on state changes.
3283     */
3284    private StateListAnimator mStateListAnimator;
3285
3286    /**
3287     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3288     * the user may specify which view to go to next.
3289     */
3290    private int mNextFocusLeftId = View.NO_ID;
3291
3292    /**
3293     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3294     * the user may specify which view to go to next.
3295     */
3296    private int mNextFocusRightId = View.NO_ID;
3297
3298    /**
3299     * When this view has focus and the next focus is {@link #FOCUS_UP},
3300     * the user may specify which view to go to next.
3301     */
3302    private int mNextFocusUpId = View.NO_ID;
3303
3304    /**
3305     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3306     * the user may specify which view to go to next.
3307     */
3308    private int mNextFocusDownId = View.NO_ID;
3309
3310    /**
3311     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3312     * the user may specify which view to go to next.
3313     */
3314    int mNextFocusForwardId = View.NO_ID;
3315
3316    private CheckForLongPress mPendingCheckForLongPress;
3317    private CheckForTap mPendingCheckForTap = null;
3318    private PerformClick mPerformClick;
3319    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3320
3321    private UnsetPressedState mUnsetPressedState;
3322
3323    /**
3324     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3325     * up event while a long press is invoked as soon as the long press duration is reached, so
3326     * a long press could be performed before the tap is checked, in which case the tap's action
3327     * should not be invoked.
3328     */
3329    private boolean mHasPerformedLongPress;
3330
3331    /**
3332     * The minimum height of the view. We'll try our best to have the height
3333     * of this view to at least this amount.
3334     */
3335    @ViewDebug.ExportedProperty(category = "measurement")
3336    private int mMinHeight;
3337
3338    /**
3339     * The minimum width of the view. We'll try our best to have the width
3340     * of this view to at least this amount.
3341     */
3342    @ViewDebug.ExportedProperty(category = "measurement")
3343    private int mMinWidth;
3344
3345    /**
3346     * The delegate to handle touch events that are physically in this view
3347     * but should be handled by another view.
3348     */
3349    private TouchDelegate mTouchDelegate = null;
3350
3351    /**
3352     * Solid color to use as a background when creating the drawing cache. Enables
3353     * the cache to use 16 bit bitmaps instead of 32 bit.
3354     */
3355    private int mDrawingCacheBackgroundColor = 0;
3356
3357    /**
3358     * Special tree observer used when mAttachInfo is null.
3359     */
3360    private ViewTreeObserver mFloatingTreeObserver;
3361
3362    /**
3363     * Cache the touch slop from the context that created the view.
3364     */
3365    private int mTouchSlop;
3366
3367    /**
3368     * Object that handles automatic animation of view properties.
3369     */
3370    private ViewPropertyAnimator mAnimator = null;
3371
3372    /**
3373     * Flag indicating that a drag can cross window boundaries.  When
3374     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3375     * with this flag set, all visible applications will be able to participate
3376     * in the drag operation and receive the dragged content.
3377     *
3378     * @hide
3379     */
3380    public static final int DRAG_FLAG_GLOBAL = 1;
3381
3382    /**
3383     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3384     */
3385    private float mVerticalScrollFactor;
3386
3387    /**
3388     * Position of the vertical scroll bar.
3389     */
3390    private int mVerticalScrollbarPosition;
3391
3392    /**
3393     * Position the scroll bar at the default position as determined by the system.
3394     */
3395    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3396
3397    /**
3398     * Position the scroll bar along the left edge.
3399     */
3400    public static final int SCROLLBAR_POSITION_LEFT = 1;
3401
3402    /**
3403     * Position the scroll bar along the right edge.
3404     */
3405    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3406
3407    /**
3408     * Indicates that the view does not have a layer.
3409     *
3410     * @see #getLayerType()
3411     * @see #setLayerType(int, android.graphics.Paint)
3412     * @see #LAYER_TYPE_SOFTWARE
3413     * @see #LAYER_TYPE_HARDWARE
3414     */
3415    public static final int LAYER_TYPE_NONE = 0;
3416
3417    /**
3418     * <p>Indicates that the view has a software layer. A software layer is backed
3419     * by a bitmap and causes the view to be rendered using Android's software
3420     * rendering pipeline, even if hardware acceleration is enabled.</p>
3421     *
3422     * <p>Software layers have various usages:</p>
3423     * <p>When the application is not using hardware acceleration, a software layer
3424     * is useful to apply a specific color filter and/or blending mode and/or
3425     * translucency to a view and all its children.</p>
3426     * <p>When the application is using hardware acceleration, a software layer
3427     * is useful to render drawing primitives not supported by the hardware
3428     * accelerated pipeline. It can also be used to cache a complex view tree
3429     * into a texture and reduce the complexity of drawing operations. For instance,
3430     * when animating a complex view tree with a translation, a software layer can
3431     * be used to render the view tree only once.</p>
3432     * <p>Software layers should be avoided when the affected view tree updates
3433     * often. Every update will require to re-render the software layer, which can
3434     * potentially be slow (particularly when hardware acceleration is turned on
3435     * since the layer will have to be uploaded into a hardware texture after every
3436     * update.)</p>
3437     *
3438     * @see #getLayerType()
3439     * @see #setLayerType(int, android.graphics.Paint)
3440     * @see #LAYER_TYPE_NONE
3441     * @see #LAYER_TYPE_HARDWARE
3442     */
3443    public static final int LAYER_TYPE_SOFTWARE = 1;
3444
3445    /**
3446     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3447     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3448     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3449     * rendering pipeline, but only if hardware acceleration is turned on for the
3450     * view hierarchy. When hardware acceleration is turned off, hardware layers
3451     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3452     *
3453     * <p>A hardware layer is useful to apply a specific color filter and/or
3454     * blending mode and/or translucency to a view and all its children.</p>
3455     * <p>A hardware layer can be used to cache a complex view tree into a
3456     * texture and reduce the complexity of drawing operations. For instance,
3457     * when animating a complex view tree with a translation, a hardware layer can
3458     * be used to render the view tree only once.</p>
3459     * <p>A hardware layer can also be used to increase the rendering quality when
3460     * rotation transformations are applied on a view. It can also be used to
3461     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3462     *
3463     * @see #getLayerType()
3464     * @see #setLayerType(int, android.graphics.Paint)
3465     * @see #LAYER_TYPE_NONE
3466     * @see #LAYER_TYPE_SOFTWARE
3467     */
3468    public static final int LAYER_TYPE_HARDWARE = 2;
3469
3470    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3471            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3472            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3473            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3474    })
3475    int mLayerType = LAYER_TYPE_NONE;
3476    Paint mLayerPaint;
3477
3478    /**
3479     * Set to true when drawing cache is enabled and cannot be created.
3480     *
3481     * @hide
3482     */
3483    public boolean mCachingFailed;
3484    private Bitmap mDrawingCache;
3485    private Bitmap mUnscaledDrawingCache;
3486
3487    /**
3488     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3489     * <p>
3490     * When non-null and valid, this is expected to contain an up-to-date copy
3491     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3492     * cleanup.
3493     */
3494    final RenderNode mRenderNode;
3495
3496    /**
3497     * Set to true when the view is sending hover accessibility events because it
3498     * is the innermost hovered view.
3499     */
3500    private boolean mSendingHoverAccessibilityEvents;
3501
3502    /**
3503     * Delegate for injecting accessibility functionality.
3504     */
3505    AccessibilityDelegate mAccessibilityDelegate;
3506
3507    /**
3508     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3509     * and add/remove objects to/from the overlay directly through the Overlay methods.
3510     */
3511    ViewOverlay mOverlay;
3512
3513    /**
3514     * The currently active parent view for receiving delegated nested scrolling events.
3515     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3516     * by {@link #stopNestedScroll()} at the same point where we clear
3517     * requestDisallowInterceptTouchEvent.
3518     */
3519    private ViewParent mNestedScrollingParent;
3520
3521    /**
3522     * Consistency verifier for debugging purposes.
3523     * @hide
3524     */
3525    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3526            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3527                    new InputEventConsistencyVerifier(this, 0) : null;
3528
3529    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3530
3531    private int[] mTempNestedScrollConsumed;
3532
3533    /**
3534     * An overlay is going to draw this View instead of being drawn as part of this
3535     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3536     * when this view is invalidated.
3537     */
3538    GhostView mGhostView;
3539
3540    /**
3541     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3542     * @hide
3543     */
3544    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3545    public String[] mAttributes;
3546
3547    /**
3548     * Maps a Resource id to its name.
3549     */
3550    private static SparseArray<String> mAttributeMap;
3551
3552    /**
3553     * Simple constructor to use when creating a view from code.
3554     *
3555     * @param context The Context the view is running in, through which it can
3556     *        access the current theme, resources, etc.
3557     */
3558    public View(Context context) {
3559        mContext = context;
3560        mResources = context != null ? context.getResources() : null;
3561        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3562        // Set some flags defaults
3563        mPrivateFlags2 =
3564                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3565                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3566                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3567                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3568                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3569                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3570        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3571        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3572        mUserPaddingStart = UNDEFINED_PADDING;
3573        mUserPaddingEnd = UNDEFINED_PADDING;
3574        mRenderNode = RenderNode.create(getClass().getName(), this);
3575
3576        if (!sCompatibilityDone && context != null) {
3577            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3578
3579            // Older apps may need this compatibility hack for measurement.
3580            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3581
3582            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3583            // of whether a layout was requested on that View.
3584            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3585
3586            Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
3587
3588            sCompatibilityDone = true;
3589        }
3590    }
3591
3592    /**
3593     * Constructor that is called when inflating a view from XML. This is called
3594     * when a view is being constructed from an XML file, supplying attributes
3595     * that were specified in the XML file. This version uses a default style of
3596     * 0, so the only attribute values applied are those in the Context's Theme
3597     * and the given AttributeSet.
3598     *
3599     * <p>
3600     * The method onFinishInflate() will be called after all children have been
3601     * added.
3602     *
3603     * @param context The Context the view is running in, through which it can
3604     *        access the current theme, resources, etc.
3605     * @param attrs The attributes of the XML tag that is inflating the view.
3606     * @see #View(Context, AttributeSet, int)
3607     */
3608    public View(Context context, @Nullable AttributeSet attrs) {
3609        this(context, attrs, 0);
3610    }
3611
3612    /**
3613     * Perform inflation from XML and apply a class-specific base style from a
3614     * theme attribute. This constructor of View allows subclasses to use their
3615     * own base style when they are inflating. For example, a Button class's
3616     * constructor would call this version of the super class constructor and
3617     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3618     * allows the theme's button style to modify all of the base view attributes
3619     * (in particular its background) as well as the Button class's attributes.
3620     *
3621     * @param context The Context the view is running in, through which it can
3622     *        access the current theme, resources, etc.
3623     * @param attrs The attributes of the XML tag that is inflating the view.
3624     * @param defStyleAttr An attribute in the current theme that contains a
3625     *        reference to a style resource that supplies default values for
3626     *        the view. Can be 0 to not look for defaults.
3627     * @see #View(Context, AttributeSet)
3628     */
3629    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3630        this(context, attrs, defStyleAttr, 0);
3631    }
3632
3633    /**
3634     * Perform inflation from XML and apply a class-specific base style from a
3635     * theme attribute or style resource. This constructor of View allows
3636     * subclasses to use their own base style when they are inflating.
3637     * <p>
3638     * When determining the final value of a particular attribute, there are
3639     * four inputs that come into play:
3640     * <ol>
3641     * <li>Any attribute values in the given AttributeSet.
3642     * <li>The style resource specified in the AttributeSet (named "style").
3643     * <li>The default style specified by <var>defStyleAttr</var>.
3644     * <li>The default style specified by <var>defStyleRes</var>.
3645     * <li>The base values in this theme.
3646     * </ol>
3647     * <p>
3648     * Each of these inputs is considered in-order, with the first listed taking
3649     * precedence over the following ones. In other words, if in the
3650     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3651     * , then the button's text will <em>always</em> be black, regardless of
3652     * what is specified in any of the styles.
3653     *
3654     * @param context The Context the view is running in, through which it can
3655     *        access the current theme, resources, etc.
3656     * @param attrs The attributes of the XML tag that is inflating the view.
3657     * @param defStyleAttr An attribute in the current theme that contains a
3658     *        reference to a style resource that supplies default values for
3659     *        the view. Can be 0 to not look for defaults.
3660     * @param defStyleRes A resource identifier of a style resource that
3661     *        supplies default values for the view, used only if
3662     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3663     *        to not look for defaults.
3664     * @see #View(Context, AttributeSet, int)
3665     */
3666    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3667        this(context);
3668
3669        final TypedArray a = context.obtainStyledAttributes(
3670                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3671
3672        if (mDebugViewAttributes) {
3673            saveAttributeData(attrs, a);
3674        }
3675
3676        Drawable background = null;
3677
3678        int leftPadding = -1;
3679        int topPadding = -1;
3680        int rightPadding = -1;
3681        int bottomPadding = -1;
3682        int startPadding = UNDEFINED_PADDING;
3683        int endPadding = UNDEFINED_PADDING;
3684
3685        int padding = -1;
3686
3687        int viewFlagValues = 0;
3688        int viewFlagMasks = 0;
3689
3690        boolean setScrollContainer = false;
3691
3692        int x = 0;
3693        int y = 0;
3694
3695        float tx = 0;
3696        float ty = 0;
3697        float tz = 0;
3698        float elevation = 0;
3699        float rotation = 0;
3700        float rotationX = 0;
3701        float rotationY = 0;
3702        float sx = 1f;
3703        float sy = 1f;
3704        boolean transformSet = false;
3705
3706        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3707        int overScrollMode = mOverScrollMode;
3708        boolean initializeScrollbars = false;
3709
3710        boolean startPaddingDefined = false;
3711        boolean endPaddingDefined = false;
3712        boolean leftPaddingDefined = false;
3713        boolean rightPaddingDefined = false;
3714
3715        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3716
3717        final int N = a.getIndexCount();
3718        for (int i = 0; i < N; i++) {
3719            int attr = a.getIndex(i);
3720            switch (attr) {
3721                case com.android.internal.R.styleable.View_background:
3722                    background = a.getDrawable(attr);
3723                    break;
3724                case com.android.internal.R.styleable.View_padding:
3725                    padding = a.getDimensionPixelSize(attr, -1);
3726                    mUserPaddingLeftInitial = padding;
3727                    mUserPaddingRightInitial = padding;
3728                    leftPaddingDefined = true;
3729                    rightPaddingDefined = true;
3730                    break;
3731                 case com.android.internal.R.styleable.View_paddingLeft:
3732                    leftPadding = a.getDimensionPixelSize(attr, -1);
3733                    mUserPaddingLeftInitial = leftPadding;
3734                    leftPaddingDefined = true;
3735                    break;
3736                case com.android.internal.R.styleable.View_paddingTop:
3737                    topPadding = a.getDimensionPixelSize(attr, -1);
3738                    break;
3739                case com.android.internal.R.styleable.View_paddingRight:
3740                    rightPadding = a.getDimensionPixelSize(attr, -1);
3741                    mUserPaddingRightInitial = rightPadding;
3742                    rightPaddingDefined = true;
3743                    break;
3744                case com.android.internal.R.styleable.View_paddingBottom:
3745                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3746                    break;
3747                case com.android.internal.R.styleable.View_paddingStart:
3748                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3749                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3750                    break;
3751                case com.android.internal.R.styleable.View_paddingEnd:
3752                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3753                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3754                    break;
3755                case com.android.internal.R.styleable.View_scrollX:
3756                    x = a.getDimensionPixelOffset(attr, 0);
3757                    break;
3758                case com.android.internal.R.styleable.View_scrollY:
3759                    y = a.getDimensionPixelOffset(attr, 0);
3760                    break;
3761                case com.android.internal.R.styleable.View_alpha:
3762                    setAlpha(a.getFloat(attr, 1f));
3763                    break;
3764                case com.android.internal.R.styleable.View_transformPivotX:
3765                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3766                    break;
3767                case com.android.internal.R.styleable.View_transformPivotY:
3768                    setPivotY(a.getDimensionPixelOffset(attr, 0));
3769                    break;
3770                case com.android.internal.R.styleable.View_translationX:
3771                    tx = a.getDimensionPixelOffset(attr, 0);
3772                    transformSet = true;
3773                    break;
3774                case com.android.internal.R.styleable.View_translationY:
3775                    ty = a.getDimensionPixelOffset(attr, 0);
3776                    transformSet = true;
3777                    break;
3778                case com.android.internal.R.styleable.View_translationZ:
3779                    tz = a.getDimensionPixelOffset(attr, 0);
3780                    transformSet = true;
3781                    break;
3782                case com.android.internal.R.styleable.View_elevation:
3783                    elevation = a.getDimensionPixelOffset(attr, 0);
3784                    transformSet = true;
3785                    break;
3786                case com.android.internal.R.styleable.View_rotation:
3787                    rotation = a.getFloat(attr, 0);
3788                    transformSet = true;
3789                    break;
3790                case com.android.internal.R.styleable.View_rotationX:
3791                    rotationX = a.getFloat(attr, 0);
3792                    transformSet = true;
3793                    break;
3794                case com.android.internal.R.styleable.View_rotationY:
3795                    rotationY = a.getFloat(attr, 0);
3796                    transformSet = true;
3797                    break;
3798                case com.android.internal.R.styleable.View_scaleX:
3799                    sx = a.getFloat(attr, 1f);
3800                    transformSet = true;
3801                    break;
3802                case com.android.internal.R.styleable.View_scaleY:
3803                    sy = a.getFloat(attr, 1f);
3804                    transformSet = true;
3805                    break;
3806                case com.android.internal.R.styleable.View_id:
3807                    mID = a.getResourceId(attr, NO_ID);
3808                    break;
3809                case com.android.internal.R.styleable.View_tag:
3810                    mTag = a.getText(attr);
3811                    break;
3812                case com.android.internal.R.styleable.View_fitsSystemWindows:
3813                    if (a.getBoolean(attr, false)) {
3814                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
3815                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3816                    }
3817                    break;
3818                case com.android.internal.R.styleable.View_focusable:
3819                    if (a.getBoolean(attr, false)) {
3820                        viewFlagValues |= FOCUSABLE;
3821                        viewFlagMasks |= FOCUSABLE_MASK;
3822                    }
3823                    break;
3824                case com.android.internal.R.styleable.View_focusableInTouchMode:
3825                    if (a.getBoolean(attr, false)) {
3826                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3827                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3828                    }
3829                    break;
3830                case com.android.internal.R.styleable.View_clickable:
3831                    if (a.getBoolean(attr, false)) {
3832                        viewFlagValues |= CLICKABLE;
3833                        viewFlagMasks |= CLICKABLE;
3834                    }
3835                    break;
3836                case com.android.internal.R.styleable.View_longClickable:
3837                    if (a.getBoolean(attr, false)) {
3838                        viewFlagValues |= LONG_CLICKABLE;
3839                        viewFlagMasks |= LONG_CLICKABLE;
3840                    }
3841                    break;
3842                case com.android.internal.R.styleable.View_saveEnabled:
3843                    if (!a.getBoolean(attr, true)) {
3844                        viewFlagValues |= SAVE_DISABLED;
3845                        viewFlagMasks |= SAVE_DISABLED_MASK;
3846                    }
3847                    break;
3848                case com.android.internal.R.styleable.View_duplicateParentState:
3849                    if (a.getBoolean(attr, false)) {
3850                        viewFlagValues |= DUPLICATE_PARENT_STATE;
3851                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
3852                    }
3853                    break;
3854                case com.android.internal.R.styleable.View_visibility:
3855                    final int visibility = a.getInt(attr, 0);
3856                    if (visibility != 0) {
3857                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
3858                        viewFlagMasks |= VISIBILITY_MASK;
3859                    }
3860                    break;
3861                case com.android.internal.R.styleable.View_layoutDirection:
3862                    // Clear any layout direction flags (included resolved bits) already set
3863                    mPrivateFlags2 &=
3864                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
3865                    // Set the layout direction flags depending on the value of the attribute
3866                    final int layoutDirection = a.getInt(attr, -1);
3867                    final int value = (layoutDirection != -1) ?
3868                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
3869                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
3870                    break;
3871                case com.android.internal.R.styleable.View_drawingCacheQuality:
3872                    final int cacheQuality = a.getInt(attr, 0);
3873                    if (cacheQuality != 0) {
3874                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3875                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3876                    }
3877                    break;
3878                case com.android.internal.R.styleable.View_contentDescription:
3879                    setContentDescription(a.getString(attr));
3880                    break;
3881                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
3882                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
3883                    break;
3884                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
3885                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
3886                    break;
3887                case com.android.internal.R.styleable.View_labelFor:
3888                    setLabelFor(a.getResourceId(attr, NO_ID));
3889                    break;
3890                case com.android.internal.R.styleable.View_soundEffectsEnabled:
3891                    if (!a.getBoolean(attr, true)) {
3892                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3893                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3894                    }
3895                    break;
3896                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3897                    if (!a.getBoolean(attr, true)) {
3898                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3899                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3900                    }
3901                    break;
3902                case R.styleable.View_scrollbars:
3903                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3904                    if (scrollbars != SCROLLBARS_NONE) {
3905                        viewFlagValues |= scrollbars;
3906                        viewFlagMasks |= SCROLLBARS_MASK;
3907                        initializeScrollbars = true;
3908                    }
3909                    break;
3910                //noinspection deprecation
3911                case R.styleable.View_fadingEdge:
3912                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
3913                        // Ignore the attribute starting with ICS
3914                        break;
3915                    }
3916                    // With builds < ICS, fall through and apply fading edges
3917                case R.styleable.View_requiresFadingEdge:
3918                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3919                    if (fadingEdge != FADING_EDGE_NONE) {
3920                        viewFlagValues |= fadingEdge;
3921                        viewFlagMasks |= FADING_EDGE_MASK;
3922                        initializeFadingEdgeInternal(a);
3923                    }
3924                    break;
3925                case R.styleable.View_scrollbarStyle:
3926                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3927                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3928                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3929                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3930                    }
3931                    break;
3932                case R.styleable.View_isScrollContainer:
3933                    setScrollContainer = true;
3934                    if (a.getBoolean(attr, false)) {
3935                        setScrollContainer(true);
3936                    }
3937                    break;
3938                case com.android.internal.R.styleable.View_keepScreenOn:
3939                    if (a.getBoolean(attr, false)) {
3940                        viewFlagValues |= KEEP_SCREEN_ON;
3941                        viewFlagMasks |= KEEP_SCREEN_ON;
3942                    }
3943                    break;
3944                case R.styleable.View_filterTouchesWhenObscured:
3945                    if (a.getBoolean(attr, false)) {
3946                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3947                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3948                    }
3949                    break;
3950                case R.styleable.View_nextFocusLeft:
3951                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3952                    break;
3953                case R.styleable.View_nextFocusRight:
3954                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3955                    break;
3956                case R.styleable.View_nextFocusUp:
3957                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3958                    break;
3959                case R.styleable.View_nextFocusDown:
3960                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3961                    break;
3962                case R.styleable.View_nextFocusForward:
3963                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3964                    break;
3965                case R.styleable.View_minWidth:
3966                    mMinWidth = a.getDimensionPixelSize(attr, 0);
3967                    break;
3968                case R.styleable.View_minHeight:
3969                    mMinHeight = a.getDimensionPixelSize(attr, 0);
3970                    break;
3971                case R.styleable.View_onClick:
3972                    if (context.isRestricted()) {
3973                        throw new IllegalStateException("The android:onClick attribute cannot "
3974                                + "be used within a restricted context");
3975                    }
3976
3977                    final String handlerName = a.getString(attr);
3978                    if (handlerName != null) {
3979                        setOnClickListener(new OnClickListener() {
3980                            private Method mHandler;
3981
3982                            public void onClick(View v) {
3983                                if (mHandler == null) {
3984                                    try {
3985                                        mHandler = getContext().getClass().getMethod(handlerName,
3986                                                View.class);
3987                                    } catch (NoSuchMethodException e) {
3988                                        int id = getId();
3989                                        String idText = id == NO_ID ? "" : " with id '"
3990                                                + getContext().getResources().getResourceEntryName(
3991                                                    id) + "'";
3992                                        throw new IllegalStateException("Could not find a method " +
3993                                                handlerName + "(View) in the activity "
3994                                                + getContext().getClass() + " for onClick handler"
3995                                                + " on view " + View.this.getClass() + idText, e);
3996                                    }
3997                                }
3998
3999                                try {
4000                                    mHandler.invoke(getContext(), View.this);
4001                                } catch (IllegalAccessException e) {
4002                                    throw new IllegalStateException("Could not execute non "
4003                                            + "public method of the activity", e);
4004                                } catch (InvocationTargetException e) {
4005                                    throw new IllegalStateException("Could not execute "
4006                                            + "method of the activity", e);
4007                                }
4008                            }
4009                        });
4010                    }
4011                    break;
4012                case R.styleable.View_overScrollMode:
4013                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4014                    break;
4015                case R.styleable.View_verticalScrollbarPosition:
4016                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4017                    break;
4018                case R.styleable.View_layerType:
4019                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4020                    break;
4021                case R.styleable.View_textDirection:
4022                    // Clear any text direction flag already set
4023                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4024                    // Set the text direction flags depending on the value of the attribute
4025                    final int textDirection = a.getInt(attr, -1);
4026                    if (textDirection != -1) {
4027                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4028                    }
4029                    break;
4030                case R.styleable.View_textAlignment:
4031                    // Clear any text alignment flag already set
4032                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4033                    // Set the text alignment flag depending on the value of the attribute
4034                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4035                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4036                    break;
4037                case R.styleable.View_importantForAccessibility:
4038                    setImportantForAccessibility(a.getInt(attr,
4039                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4040                    break;
4041                case R.styleable.View_accessibilityLiveRegion:
4042                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4043                    break;
4044                case R.styleable.View_transitionName:
4045                    setTransitionName(a.getString(attr));
4046                    break;
4047                case R.styleable.View_nestedScrollingEnabled:
4048                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4049                    break;
4050                case R.styleable.View_stateListAnimator:
4051                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4052                            a.getResourceId(attr, 0)));
4053                    break;
4054                case R.styleable.View_backgroundTint:
4055                    // This will get applied later during setBackground().
4056                    if (mBackgroundTint == null) {
4057                        mBackgroundTint = new TintInfo();
4058                    }
4059                    mBackgroundTint.mTintList = a.getColorStateList(
4060                            R.styleable.View_backgroundTint);
4061                    mBackgroundTint.mHasTintList = true;
4062                    break;
4063                case R.styleable.View_backgroundTintMode:
4064                    // This will get applied later during setBackground().
4065                    if (mBackgroundTint == null) {
4066                        mBackgroundTint = new TintInfo();
4067                    }
4068                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4069                            R.styleable.View_backgroundTintMode, -1), null);
4070                    mBackgroundTint.mHasTintMode = true;
4071                    break;
4072                case R.styleable.View_outlineProvider:
4073                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4074                            PROVIDER_BACKGROUND));
4075                    break;
4076                case R.styleable.View_foreground:
4077                    setForeground(a.getDrawable(attr));
4078                    break;
4079                case R.styleable.View_foregroundGravity:
4080                    setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4081                    break;
4082                case R.styleable.View_foregroundTintMode:
4083                    setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4084                    break;
4085                case R.styleable.View_foregroundTint:
4086                    setForegroundTintList(a.getColorStateList(attr));
4087                    break;
4088                case R.styleable.View_foregroundInsidePadding:
4089                    if (mForegroundInfo == null) {
4090                        mForegroundInfo = new ForegroundInfo();
4091                    }
4092                    mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4093                            mForegroundInfo.mInsidePadding);
4094                    break;
4095            }
4096        }
4097
4098        setOverScrollMode(overScrollMode);
4099
4100        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4101        // the resolved layout direction). Those cached values will be used later during padding
4102        // resolution.
4103        mUserPaddingStart = startPadding;
4104        mUserPaddingEnd = endPadding;
4105
4106        if (background != null) {
4107            setBackground(background);
4108        }
4109
4110        // setBackground above will record that padding is currently provided by the background.
4111        // If we have padding specified via xml, record that here instead and use it.
4112        mLeftPaddingDefined = leftPaddingDefined;
4113        mRightPaddingDefined = rightPaddingDefined;
4114
4115        if (padding >= 0) {
4116            leftPadding = padding;
4117            topPadding = padding;
4118            rightPadding = padding;
4119            bottomPadding = padding;
4120            mUserPaddingLeftInitial = padding;
4121            mUserPaddingRightInitial = padding;
4122        }
4123
4124        if (isRtlCompatibilityMode()) {
4125            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4126            // left / right padding are used if defined (meaning here nothing to do). If they are not
4127            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4128            // start / end and resolve them as left / right (layout direction is not taken into account).
4129            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4130            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4131            // defined.
4132            if (!mLeftPaddingDefined && startPaddingDefined) {
4133                leftPadding = startPadding;
4134            }
4135            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4136            if (!mRightPaddingDefined && endPaddingDefined) {
4137                rightPadding = endPadding;
4138            }
4139            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4140        } else {
4141            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4142            // values defined. Otherwise, left /right values are used.
4143            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4144            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4145            // defined.
4146            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4147
4148            if (mLeftPaddingDefined && !hasRelativePadding) {
4149                mUserPaddingLeftInitial = leftPadding;
4150            }
4151            if (mRightPaddingDefined && !hasRelativePadding) {
4152                mUserPaddingRightInitial = rightPadding;
4153            }
4154        }
4155
4156        internalSetPadding(
4157                mUserPaddingLeftInitial,
4158                topPadding >= 0 ? topPadding : mPaddingTop,
4159                mUserPaddingRightInitial,
4160                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4161
4162        if (viewFlagMasks != 0) {
4163            setFlags(viewFlagValues, viewFlagMasks);
4164        }
4165
4166        if (initializeScrollbars) {
4167            initializeScrollbarsInternal(a);
4168        }
4169
4170        a.recycle();
4171
4172        // Needs to be called after mViewFlags is set
4173        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4174            recomputePadding();
4175        }
4176
4177        if (x != 0 || y != 0) {
4178            scrollTo(x, y);
4179        }
4180
4181        if (transformSet) {
4182            setTranslationX(tx);
4183            setTranslationY(ty);
4184            setTranslationZ(tz);
4185            setElevation(elevation);
4186            setRotation(rotation);
4187            setRotationX(rotationX);
4188            setRotationY(rotationY);
4189            setScaleX(sx);
4190            setScaleY(sy);
4191        }
4192
4193        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4194            setScrollContainer(true);
4195        }
4196
4197        computeOpaqueFlags();
4198    }
4199
4200    /**
4201     * Non-public constructor for use in testing
4202     */
4203    View() {
4204        mResources = null;
4205        mRenderNode = RenderNode.create(getClass().getName(), this);
4206    }
4207
4208    private static SparseArray<String> getAttributeMap() {
4209        if (mAttributeMap == null) {
4210            mAttributeMap = new SparseArray<String>();
4211        }
4212        return mAttributeMap;
4213    }
4214
4215    private void saveAttributeData(AttributeSet attrs, TypedArray a) {
4216        int length = ((attrs == null ? 0 : attrs.getAttributeCount()) + a.getIndexCount()) * 2;
4217        mAttributes = new String[length];
4218
4219        int i = 0;
4220        if (attrs != null) {
4221            for (i = 0; i < attrs.getAttributeCount(); i += 2) {
4222                mAttributes[i] = attrs.getAttributeName(i);
4223                mAttributes[i + 1] = attrs.getAttributeValue(i);
4224            }
4225
4226        }
4227
4228        SparseArray<String> attributeMap = getAttributeMap();
4229        for (int j = 0; j < a.length(); ++j) {
4230            if (a.hasValue(j)) {
4231                try {
4232                    int resourceId = a.getResourceId(j, 0);
4233                    if (resourceId == 0) {
4234                        continue;
4235                    }
4236
4237                    String resourceName = attributeMap.get(resourceId);
4238                    if (resourceName == null) {
4239                        resourceName = a.getResources().getResourceName(resourceId);
4240                        attributeMap.put(resourceId, resourceName);
4241                    }
4242
4243                    mAttributes[i] = resourceName;
4244                    mAttributes[i + 1] = a.getText(j).toString();
4245                    i += 2;
4246                } catch (Resources.NotFoundException e) {
4247                    // if we can't get the resource name, we just ignore it
4248                }
4249            }
4250        }
4251    }
4252
4253    public String toString() {
4254        StringBuilder out = new StringBuilder(128);
4255        out.append(getClass().getName());
4256        out.append('{');
4257        out.append(Integer.toHexString(System.identityHashCode(this)));
4258        out.append(' ');
4259        switch (mViewFlags&VISIBILITY_MASK) {
4260            case VISIBLE: out.append('V'); break;
4261            case INVISIBLE: out.append('I'); break;
4262            case GONE: out.append('G'); break;
4263            default: out.append('.'); break;
4264        }
4265        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4266        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4267        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4268        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4269        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4270        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4271        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4272        out.append(' ');
4273        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4274        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4275        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4276        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4277            out.append('p');
4278        } else {
4279            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4280        }
4281        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4282        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4283        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4284        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4285        out.append(' ');
4286        out.append(mLeft);
4287        out.append(',');
4288        out.append(mTop);
4289        out.append('-');
4290        out.append(mRight);
4291        out.append(',');
4292        out.append(mBottom);
4293        final int id = getId();
4294        if (id != NO_ID) {
4295            out.append(" #");
4296            out.append(Integer.toHexString(id));
4297            final Resources r = mResources;
4298            if (Resources.resourceHasPackage(id) && r != null) {
4299                try {
4300                    String pkgname;
4301                    switch (id&0xff000000) {
4302                        case 0x7f000000:
4303                            pkgname="app";
4304                            break;
4305                        case 0x01000000:
4306                            pkgname="android";
4307                            break;
4308                        default:
4309                            pkgname = r.getResourcePackageName(id);
4310                            break;
4311                    }
4312                    String typename = r.getResourceTypeName(id);
4313                    String entryname = r.getResourceEntryName(id);
4314                    out.append(" ");
4315                    out.append(pkgname);
4316                    out.append(":");
4317                    out.append(typename);
4318                    out.append("/");
4319                    out.append(entryname);
4320                } catch (Resources.NotFoundException e) {
4321                }
4322            }
4323        }
4324        out.append("}");
4325        return out.toString();
4326    }
4327
4328    /**
4329     * <p>
4330     * Initializes the fading edges from a given set of styled attributes. This
4331     * method should be called by subclasses that need fading edges and when an
4332     * instance of these subclasses is created programmatically rather than
4333     * being inflated from XML. This method is automatically called when the XML
4334     * is inflated.
4335     * </p>
4336     *
4337     * @param a the styled attributes set to initialize the fading edges from
4338     *
4339     * @removed
4340     */
4341    protected void initializeFadingEdge(TypedArray a) {
4342        // This method probably shouldn't have been included in the SDK to begin with.
4343        // It relies on 'a' having been initialized using an attribute filter array that is
4344        // not publicly available to the SDK. The old method has been renamed
4345        // to initializeFadingEdgeInternal and hidden for framework use only;
4346        // this one initializes using defaults to make it safe to call for apps.
4347
4348        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4349
4350        initializeFadingEdgeInternal(arr);
4351
4352        arr.recycle();
4353    }
4354
4355    /**
4356     * <p>
4357     * Initializes the fading edges from a given set of styled attributes. This
4358     * method should be called by subclasses that need fading edges and when an
4359     * instance of these subclasses is created programmatically rather than
4360     * being inflated from XML. This method is automatically called when the XML
4361     * is inflated.
4362     * </p>
4363     *
4364     * @param a the styled attributes set to initialize the fading edges from
4365     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4366     */
4367    protected void initializeFadingEdgeInternal(TypedArray a) {
4368        initScrollCache();
4369
4370        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4371                R.styleable.View_fadingEdgeLength,
4372                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4373    }
4374
4375    /**
4376     * Returns the size of the vertical faded edges used to indicate that more
4377     * content in this view is visible.
4378     *
4379     * @return The size in pixels of the vertical faded edge or 0 if vertical
4380     *         faded edges are not enabled for this view.
4381     * @attr ref android.R.styleable#View_fadingEdgeLength
4382     */
4383    public int getVerticalFadingEdgeLength() {
4384        if (isVerticalFadingEdgeEnabled()) {
4385            ScrollabilityCache cache = mScrollCache;
4386            if (cache != null) {
4387                return cache.fadingEdgeLength;
4388            }
4389        }
4390        return 0;
4391    }
4392
4393    /**
4394     * Set the size of the faded edge used to indicate that more content in this
4395     * view is available.  Will not change whether the fading edge is enabled; use
4396     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4397     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4398     * for the vertical or horizontal fading edges.
4399     *
4400     * @param length The size in pixels of the faded edge used to indicate that more
4401     *        content in this view is visible.
4402     */
4403    public void setFadingEdgeLength(int length) {
4404        initScrollCache();
4405        mScrollCache.fadingEdgeLength = length;
4406    }
4407
4408    /**
4409     * Returns the size of the horizontal faded edges used to indicate that more
4410     * content in this view is visible.
4411     *
4412     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4413     *         faded edges are not enabled for this view.
4414     * @attr ref android.R.styleable#View_fadingEdgeLength
4415     */
4416    public int getHorizontalFadingEdgeLength() {
4417        if (isHorizontalFadingEdgeEnabled()) {
4418            ScrollabilityCache cache = mScrollCache;
4419            if (cache != null) {
4420                return cache.fadingEdgeLength;
4421            }
4422        }
4423        return 0;
4424    }
4425
4426    /**
4427     * Returns the width of the vertical scrollbar.
4428     *
4429     * @return The width in pixels of the vertical scrollbar or 0 if there
4430     *         is no vertical scrollbar.
4431     */
4432    public int getVerticalScrollbarWidth() {
4433        ScrollabilityCache cache = mScrollCache;
4434        if (cache != null) {
4435            ScrollBarDrawable scrollBar = cache.scrollBar;
4436            if (scrollBar != null) {
4437                int size = scrollBar.getSize(true);
4438                if (size <= 0) {
4439                    size = cache.scrollBarSize;
4440                }
4441                return size;
4442            }
4443            return 0;
4444        }
4445        return 0;
4446    }
4447
4448    /**
4449     * Returns the height of the horizontal scrollbar.
4450     *
4451     * @return The height in pixels of the horizontal scrollbar or 0 if
4452     *         there is no horizontal scrollbar.
4453     */
4454    protected int getHorizontalScrollbarHeight() {
4455        ScrollabilityCache cache = mScrollCache;
4456        if (cache != null) {
4457            ScrollBarDrawable scrollBar = cache.scrollBar;
4458            if (scrollBar != null) {
4459                int size = scrollBar.getSize(false);
4460                if (size <= 0) {
4461                    size = cache.scrollBarSize;
4462                }
4463                return size;
4464            }
4465            return 0;
4466        }
4467        return 0;
4468    }
4469
4470    /**
4471     * <p>
4472     * Initializes the scrollbars from a given set of styled attributes. This
4473     * method should be called by subclasses that need scrollbars and when an
4474     * instance of these subclasses is created programmatically rather than
4475     * being inflated from XML. This method is automatically called when the XML
4476     * is inflated.
4477     * </p>
4478     *
4479     * @param a the styled attributes set to initialize the scrollbars from
4480     *
4481     * @removed
4482     */
4483    protected void initializeScrollbars(TypedArray a) {
4484        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4485        // using the View filter array which is not available to the SDK. As such, internal
4486        // framework usage now uses initializeScrollbarsInternal and we grab a default
4487        // TypedArray with the right filter instead here.
4488        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4489
4490        initializeScrollbarsInternal(arr);
4491
4492        // We ignored the method parameter. Recycle the one we actually did use.
4493        arr.recycle();
4494    }
4495
4496    /**
4497     * <p>
4498     * Initializes the scrollbars from a given set of styled attributes. This
4499     * method should be called by subclasses that need scrollbars and when an
4500     * instance of these subclasses is created programmatically rather than
4501     * being inflated from XML. This method is automatically called when the XML
4502     * is inflated.
4503     * </p>
4504     *
4505     * @param a the styled attributes set to initialize the scrollbars from
4506     * @hide
4507     */
4508    protected void initializeScrollbarsInternal(TypedArray a) {
4509        initScrollCache();
4510
4511        final ScrollabilityCache scrollabilityCache = mScrollCache;
4512
4513        if (scrollabilityCache.scrollBar == null) {
4514            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4515            scrollabilityCache.scrollBar.setCallback(this);
4516            scrollabilityCache.scrollBar.setState(getDrawableState());
4517        }
4518
4519        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4520
4521        if (!fadeScrollbars) {
4522            scrollabilityCache.state = ScrollabilityCache.ON;
4523        }
4524        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4525
4526
4527        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4528                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4529                        .getScrollBarFadeDuration());
4530        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4531                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4532                ViewConfiguration.getScrollDefaultDelay());
4533
4534
4535        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4536                com.android.internal.R.styleable.View_scrollbarSize,
4537                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4538
4539        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4540        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4541
4542        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4543        if (thumb != null) {
4544            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4545        }
4546
4547        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4548                false);
4549        if (alwaysDraw) {
4550            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4551        }
4552
4553        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4554        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4555
4556        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4557        if (thumb != null) {
4558            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4559        }
4560
4561        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4562                false);
4563        if (alwaysDraw) {
4564            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4565        }
4566
4567        // Apply layout direction to the new Drawables if needed
4568        final int layoutDirection = getLayoutDirection();
4569        if (track != null) {
4570            track.setLayoutDirection(layoutDirection);
4571        }
4572        if (thumb != null) {
4573            thumb.setLayoutDirection(layoutDirection);
4574        }
4575
4576        // Re-apply user/background padding so that scrollbar(s) get added
4577        resolvePadding();
4578    }
4579
4580    /**
4581     * <p>
4582     * Initalizes the scrollability cache if necessary.
4583     * </p>
4584     */
4585    private void initScrollCache() {
4586        if (mScrollCache == null) {
4587            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4588        }
4589    }
4590
4591    private ScrollabilityCache getScrollCache() {
4592        initScrollCache();
4593        return mScrollCache;
4594    }
4595
4596    /**
4597     * Set the position of the vertical scroll bar. Should be one of
4598     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4599     * {@link #SCROLLBAR_POSITION_RIGHT}.
4600     *
4601     * @param position Where the vertical scroll bar should be positioned.
4602     */
4603    public void setVerticalScrollbarPosition(int position) {
4604        if (mVerticalScrollbarPosition != position) {
4605            mVerticalScrollbarPosition = position;
4606            computeOpaqueFlags();
4607            resolvePadding();
4608        }
4609    }
4610
4611    /**
4612     * @return The position where the vertical scroll bar will show, if applicable.
4613     * @see #setVerticalScrollbarPosition(int)
4614     */
4615    public int getVerticalScrollbarPosition() {
4616        return mVerticalScrollbarPosition;
4617    }
4618
4619    ListenerInfo getListenerInfo() {
4620        if (mListenerInfo != null) {
4621            return mListenerInfo;
4622        }
4623        mListenerInfo = new ListenerInfo();
4624        return mListenerInfo;
4625    }
4626
4627    /**
4628     * Register a callback to be invoked when the scroll X or Y positions of
4629     * this view change.
4630     * <p>
4631     * <b>Note:</b> Some views handle scrolling independently from View and may
4632     * have their own separate listeners for scroll-type events. For example,
4633     * {@link android.widget.ListView ListView} allows clients to register an
4634     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
4635     * to listen for changes in list scroll position.
4636     *
4637     * @param l The listener to notify when the scroll X or Y position changes.
4638     * @see android.view.View#getScrollX()
4639     * @see android.view.View#getScrollY()
4640     */
4641    public void setOnScrollChangeListener(OnScrollChangeListener l) {
4642        getListenerInfo().mOnScrollChangeListener = l;
4643    }
4644
4645    /**
4646     * Register a callback to be invoked when focus of this view changed.
4647     *
4648     * @param l The callback that will run.
4649     */
4650    public void setOnFocusChangeListener(OnFocusChangeListener l) {
4651        getListenerInfo().mOnFocusChangeListener = l;
4652    }
4653
4654    /**
4655     * Add a listener that will be called when the bounds of the view change due to
4656     * layout processing.
4657     *
4658     * @param listener The listener that will be called when layout bounds change.
4659     */
4660    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
4661        ListenerInfo li = getListenerInfo();
4662        if (li.mOnLayoutChangeListeners == null) {
4663            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
4664        }
4665        if (!li.mOnLayoutChangeListeners.contains(listener)) {
4666            li.mOnLayoutChangeListeners.add(listener);
4667        }
4668    }
4669
4670    /**
4671     * Remove a listener for layout changes.
4672     *
4673     * @param listener The listener for layout bounds change.
4674     */
4675    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
4676        ListenerInfo li = mListenerInfo;
4677        if (li == null || li.mOnLayoutChangeListeners == null) {
4678            return;
4679        }
4680        li.mOnLayoutChangeListeners.remove(listener);
4681    }
4682
4683    /**
4684     * Add a listener for attach state changes.
4685     *
4686     * This listener will be called whenever this view is attached or detached
4687     * from a window. Remove the listener using
4688     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
4689     *
4690     * @param listener Listener to attach
4691     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
4692     */
4693    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4694        ListenerInfo li = getListenerInfo();
4695        if (li.mOnAttachStateChangeListeners == null) {
4696            li.mOnAttachStateChangeListeners
4697                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
4698        }
4699        li.mOnAttachStateChangeListeners.add(listener);
4700    }
4701
4702    /**
4703     * Remove a listener for attach state changes. The listener will receive no further
4704     * notification of window attach/detach events.
4705     *
4706     * @param listener Listener to remove
4707     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
4708     */
4709    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
4710        ListenerInfo li = mListenerInfo;
4711        if (li == null || li.mOnAttachStateChangeListeners == null) {
4712            return;
4713        }
4714        li.mOnAttachStateChangeListeners.remove(listener);
4715    }
4716
4717    /**
4718     * Returns the focus-change callback registered for this view.
4719     *
4720     * @return The callback, or null if one is not registered.
4721     */
4722    public OnFocusChangeListener getOnFocusChangeListener() {
4723        ListenerInfo li = mListenerInfo;
4724        return li != null ? li.mOnFocusChangeListener : null;
4725    }
4726
4727    /**
4728     * Register a callback to be invoked when this view is clicked. If this view is not
4729     * clickable, it becomes clickable.
4730     *
4731     * @param l The callback that will run
4732     *
4733     * @see #setClickable(boolean)
4734     */
4735    public void setOnClickListener(@Nullable OnClickListener l) {
4736        if (!isClickable()) {
4737            setClickable(true);
4738        }
4739        getListenerInfo().mOnClickListener = l;
4740    }
4741
4742    /**
4743     * Return whether this view has an attached OnClickListener.  Returns
4744     * true if there is a listener, false if there is none.
4745     */
4746    public boolean hasOnClickListeners() {
4747        ListenerInfo li = mListenerInfo;
4748        return (li != null && li.mOnClickListener != null);
4749    }
4750
4751    /**
4752     * Register a callback to be invoked when this view is clicked and held. If this view is not
4753     * long clickable, it becomes long clickable.
4754     *
4755     * @param l The callback that will run
4756     *
4757     * @see #setLongClickable(boolean)
4758     */
4759    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
4760        if (!isLongClickable()) {
4761            setLongClickable(true);
4762        }
4763        getListenerInfo().mOnLongClickListener = l;
4764    }
4765
4766    /**
4767     * Register a callback to be invoked when the context menu for this view is
4768     * being built. If this view is not long clickable, it becomes long clickable.
4769     *
4770     * @param l The callback that will run
4771     *
4772     */
4773    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4774        if (!isLongClickable()) {
4775            setLongClickable(true);
4776        }
4777        getListenerInfo().mOnCreateContextMenuListener = l;
4778    }
4779
4780    /**
4781     * Call this view's OnClickListener, if it is defined.  Performs all normal
4782     * actions associated with clicking: reporting accessibility event, playing
4783     * a sound, etc.
4784     *
4785     * @return True there was an assigned OnClickListener that was called, false
4786     *         otherwise is returned.
4787     */
4788    public boolean performClick() {
4789        final boolean result;
4790        final ListenerInfo li = mListenerInfo;
4791        if (li != null && li.mOnClickListener != null) {
4792            playSoundEffect(SoundEffectConstants.CLICK);
4793            li.mOnClickListener.onClick(this);
4794            result = true;
4795        } else {
4796            result = false;
4797        }
4798
4799        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4800        return result;
4801    }
4802
4803    /**
4804     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
4805     * this only calls the listener, and does not do any associated clicking
4806     * actions like reporting an accessibility event.
4807     *
4808     * @return True there was an assigned OnClickListener that was called, false
4809     *         otherwise is returned.
4810     */
4811    public boolean callOnClick() {
4812        ListenerInfo li = mListenerInfo;
4813        if (li != null && li.mOnClickListener != null) {
4814            li.mOnClickListener.onClick(this);
4815            return true;
4816        }
4817        return false;
4818    }
4819
4820    /**
4821     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4822     * OnLongClickListener did not consume the event.
4823     *
4824     * @return True if one of the above receivers consumed the event, false otherwise.
4825     */
4826    public boolean performLongClick() {
4827        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4828
4829        boolean handled = false;
4830        ListenerInfo li = mListenerInfo;
4831        if (li != null && li.mOnLongClickListener != null) {
4832            handled = li.mOnLongClickListener.onLongClick(View.this);
4833        }
4834        if (!handled) {
4835            handled = showContextMenu();
4836        }
4837        if (handled) {
4838            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4839        }
4840        return handled;
4841    }
4842
4843    /**
4844     * Performs button-related actions during a touch down event.
4845     *
4846     * @param event The event.
4847     * @return True if the down was consumed.
4848     *
4849     * @hide
4850     */
4851    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4852        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
4853            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4854            showContextMenu(event.getX(), event.getY(), event.getMetaState());
4855            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
4856            return true;
4857        }
4858        return false;
4859    }
4860
4861    /**
4862     * Bring up the context menu for this view.
4863     *
4864     * @return Whether a context menu was displayed.
4865     */
4866    public boolean showContextMenu() {
4867        return getParent().showContextMenuForChild(this);
4868    }
4869
4870    /**
4871     * Bring up the context menu for this view, referring to the item under the specified point.
4872     *
4873     * @param x The referenced x coordinate.
4874     * @param y The referenced y coordinate.
4875     * @param metaState The keyboard modifiers that were pressed.
4876     * @return Whether a context menu was displayed.
4877     *
4878     * @hide
4879     */
4880    public boolean showContextMenu(float x, float y, int metaState) {
4881        return showContextMenu();
4882    }
4883
4884    /**
4885     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
4886     *
4887     * @param callback Callback that will control the lifecycle of the action mode
4888     * @return The new action mode if it is started, null otherwise
4889     *
4890     * @see ActionMode
4891     * @see #startActionMode(android.view.ActionMode.Callback, int)
4892     */
4893    public ActionMode startActionMode(ActionMode.Callback callback) {
4894        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
4895    }
4896
4897    /**
4898     * Start an action mode with the given type.
4899     *
4900     * @param callback Callback that will control the lifecycle of the action mode
4901     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
4902     * @return The new action mode if it is started, null otherwise
4903     *
4904     * @see ActionMode
4905     */
4906    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
4907        ViewParent parent = getParent();
4908        if (parent == null) return null;
4909        try {
4910            return parent.startActionModeForChild(this, callback, type);
4911        } catch (AbstractMethodError ame) {
4912            // Older implementations of custom views might not implement this.
4913            return parent.startActionModeForChild(this, callback);
4914        }
4915    }
4916
4917    /**
4918     * Register a callback to be invoked when a hardware key is pressed in this view.
4919     * Key presses in software input methods will generally not trigger the methods of
4920     * this listener.
4921     * @param l the key listener to attach to this view
4922     */
4923    public void setOnKeyListener(OnKeyListener l) {
4924        getListenerInfo().mOnKeyListener = l;
4925    }
4926
4927    /**
4928     * Register a callback to be invoked when a touch event is sent to this view.
4929     * @param l the touch listener to attach to this view
4930     */
4931    public void setOnTouchListener(OnTouchListener l) {
4932        getListenerInfo().mOnTouchListener = l;
4933    }
4934
4935    /**
4936     * Register a callback to be invoked when a generic motion event is sent to this view.
4937     * @param l the generic motion listener to attach to this view
4938     */
4939    public void setOnGenericMotionListener(OnGenericMotionListener l) {
4940        getListenerInfo().mOnGenericMotionListener = l;
4941    }
4942
4943    /**
4944     * Register a callback to be invoked when a hover event is sent to this view.
4945     * @param l the hover listener to attach to this view
4946     */
4947    public void setOnHoverListener(OnHoverListener l) {
4948        getListenerInfo().mOnHoverListener = l;
4949    }
4950
4951    /**
4952     * Register a drag event listener callback object for this View. The parameter is
4953     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4954     * View, the system calls the
4955     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4956     * @param l An implementation of {@link android.view.View.OnDragListener}.
4957     */
4958    public void setOnDragListener(OnDragListener l) {
4959        getListenerInfo().mOnDragListener = l;
4960    }
4961
4962    /**
4963     * Give this view focus. This will cause
4964     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
4965     *
4966     * Note: this does not check whether this {@link View} should get focus, it just
4967     * gives it focus no matter what.  It should only be called internally by framework
4968     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4969     *
4970     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4971     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
4972     *        focus moved when requestFocus() is called. It may not always
4973     *        apply, in which case use the default View.FOCUS_DOWN.
4974     * @param previouslyFocusedRect The rectangle of the view that had focus
4975     *        prior in this View's coordinate system.
4976     */
4977    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
4978        if (DBG) {
4979            System.out.println(this + " requestFocus()");
4980        }
4981
4982        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4983            mPrivateFlags |= PFLAG_FOCUSED;
4984
4985            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
4986
4987            if (mParent != null) {
4988                mParent.requestChildFocus(this, this);
4989            }
4990
4991            if (mAttachInfo != null) {
4992                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
4993            }
4994
4995            onFocusChanged(true, direction, previouslyFocusedRect);
4996            refreshDrawableState();
4997        }
4998    }
4999
5000    /**
5001     * Populates <code>outRect</code> with the hotspot bounds. By default,
5002     * the hotspot bounds are identical to the screen bounds.
5003     *
5004     * @param outRect rect to populate with hotspot bounds
5005     * @hide Only for internal use by views and widgets.
5006     */
5007    public void getHotspotBounds(Rect outRect) {
5008        final Drawable background = getBackground();
5009        if (background != null) {
5010            background.getHotspotBounds(outRect);
5011        } else {
5012            getBoundsOnScreen(outRect);
5013        }
5014    }
5015
5016    /**
5017     * Request that a rectangle of this view be visible on the screen,
5018     * scrolling if necessary just enough.
5019     *
5020     * <p>A View should call this if it maintains some notion of which part
5021     * of its content is interesting.  For example, a text editing view
5022     * should call this when its cursor moves.
5023     *
5024     * @param rectangle The rectangle.
5025     * @return Whether any parent scrolled.
5026     */
5027    public boolean requestRectangleOnScreen(Rect rectangle) {
5028        return requestRectangleOnScreen(rectangle, false);
5029    }
5030
5031    /**
5032     * Request that a rectangle of this view be visible on the screen,
5033     * scrolling if necessary just enough.
5034     *
5035     * <p>A View should call this if it maintains some notion of which part
5036     * of its content is interesting.  For example, a text editing view
5037     * should call this when its cursor moves.
5038     *
5039     * <p>When <code>immediate</code> is set to true, scrolling will not be
5040     * animated.
5041     *
5042     * @param rectangle The rectangle.
5043     * @param immediate True to forbid animated scrolling, false otherwise
5044     * @return Whether any parent scrolled.
5045     */
5046    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5047        if (mParent == null) {
5048            return false;
5049        }
5050
5051        View child = this;
5052
5053        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5054        position.set(rectangle);
5055
5056        ViewParent parent = mParent;
5057        boolean scrolled = false;
5058        while (parent != null) {
5059            rectangle.set((int) position.left, (int) position.top,
5060                    (int) position.right, (int) position.bottom);
5061
5062            scrolled |= parent.requestChildRectangleOnScreen(child,
5063                    rectangle, immediate);
5064
5065            if (!child.hasIdentityMatrix()) {
5066                child.getMatrix().mapRect(position);
5067            }
5068
5069            position.offset(child.mLeft, child.mTop);
5070
5071            if (!(parent instanceof View)) {
5072                break;
5073            }
5074
5075            View parentView = (View) parent;
5076
5077            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5078
5079            child = parentView;
5080            parent = child.getParent();
5081        }
5082
5083        return scrolled;
5084    }
5085
5086    /**
5087     * Called when this view wants to give up focus. If focus is cleared
5088     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5089     * <p>
5090     * <strong>Note:</strong> When a View clears focus the framework is trying
5091     * to give focus to the first focusable View from the top. Hence, if this
5092     * View is the first from the top that can take focus, then all callbacks
5093     * related to clearing focus will be invoked after which the framework will
5094     * give focus to this view.
5095     * </p>
5096     */
5097    public void clearFocus() {
5098        if (DBG) {
5099            System.out.println(this + " clearFocus()");
5100        }
5101
5102        clearFocusInternal(null, true, true);
5103    }
5104
5105    /**
5106     * Clears focus from the view, optionally propagating the change up through
5107     * the parent hierarchy and requesting that the root view place new focus.
5108     *
5109     * @param propagate whether to propagate the change up through the parent
5110     *            hierarchy
5111     * @param refocus when propagate is true, specifies whether to request the
5112     *            root view place new focus
5113     */
5114    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5115        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5116            mPrivateFlags &= ~PFLAG_FOCUSED;
5117
5118            if (propagate && mParent != null) {
5119                mParent.clearChildFocus(this);
5120            }
5121
5122            onFocusChanged(false, 0, null);
5123            refreshDrawableState();
5124
5125            if (propagate && (!refocus || !rootViewRequestFocus())) {
5126                notifyGlobalFocusCleared(this);
5127            }
5128        }
5129    }
5130
5131    void notifyGlobalFocusCleared(View oldFocus) {
5132        if (oldFocus != null && mAttachInfo != null) {
5133            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5134        }
5135    }
5136
5137    boolean rootViewRequestFocus() {
5138        final View root = getRootView();
5139        return root != null && root.requestFocus();
5140    }
5141
5142    /**
5143     * Called internally by the view system when a new view is getting focus.
5144     * This is what clears the old focus.
5145     * <p>
5146     * <b>NOTE:</b> The parent view's focused child must be updated manually
5147     * after calling this method. Otherwise, the view hierarchy may be left in
5148     * an inconstent state.
5149     */
5150    void unFocus(View focused) {
5151        if (DBG) {
5152            System.out.println(this + " unFocus()");
5153        }
5154
5155        clearFocusInternal(focused, false, false);
5156    }
5157
5158    /**
5159     * Returns true if this view has focus itself, or is the ancestor of the
5160     * view that has focus.
5161     *
5162     * @return True if this view has or contains focus, false otherwise.
5163     */
5164    @ViewDebug.ExportedProperty(category = "focus")
5165    public boolean hasFocus() {
5166        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5167    }
5168
5169    /**
5170     * Returns true if this view is focusable or if it contains a reachable View
5171     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5172     * is a View whose parents do not block descendants focus.
5173     *
5174     * Only {@link #VISIBLE} views are considered focusable.
5175     *
5176     * @return True if the view is focusable or if the view contains a focusable
5177     *         View, false otherwise.
5178     *
5179     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5180     * @see ViewGroup#getTouchscreenBlocksFocus()
5181     */
5182    public boolean hasFocusable() {
5183        if (!isFocusableInTouchMode()) {
5184            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5185                final ViewGroup g = (ViewGroup) p;
5186                if (g.shouldBlockFocusForTouchscreen()) {
5187                    return false;
5188                }
5189            }
5190        }
5191        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5192    }
5193
5194    /**
5195     * Called by the view system when the focus state of this view changes.
5196     * When the focus change event is caused by directional navigation, direction
5197     * and previouslyFocusedRect provide insight into where the focus is coming from.
5198     * When overriding, be sure to call up through to the super class so that
5199     * the standard focus handling will occur.
5200     *
5201     * @param gainFocus True if the View has focus; false otherwise.
5202     * @param direction The direction focus has moved when requestFocus()
5203     *                  is called to give this view focus. Values are
5204     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5205     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5206     *                  It may not always apply, in which case use the default.
5207     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5208     *        system, of the previously focused view.  If applicable, this will be
5209     *        passed in as finer grained information about where the focus is coming
5210     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5211     */
5212    @CallSuper
5213    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5214            @Nullable Rect previouslyFocusedRect) {
5215        if (gainFocus) {
5216            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5217        } else {
5218            notifyViewAccessibilityStateChangedIfNeeded(
5219                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5220        }
5221
5222        InputMethodManager imm = InputMethodManager.peekInstance();
5223        if (!gainFocus) {
5224            if (isPressed()) {
5225                setPressed(false);
5226            }
5227            if (imm != null && mAttachInfo != null
5228                    && mAttachInfo.mHasWindowFocus) {
5229                imm.focusOut(this);
5230            }
5231            onFocusLost();
5232        } else if (imm != null && mAttachInfo != null
5233                && mAttachInfo.mHasWindowFocus) {
5234            imm.focusIn(this);
5235        }
5236
5237        invalidate(true);
5238        ListenerInfo li = mListenerInfo;
5239        if (li != null && li.mOnFocusChangeListener != null) {
5240            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5241        }
5242
5243        if (mAttachInfo != null) {
5244            mAttachInfo.mKeyDispatchState.reset(this);
5245        }
5246    }
5247
5248    /**
5249     * Sends an accessibility event of the given type. If accessibility is
5250     * not enabled this method has no effect. The default implementation calls
5251     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5252     * to populate information about the event source (this View), then calls
5253     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5254     * populate the text content of the event source including its descendants,
5255     * and last calls
5256     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5257     * on its parent to request sending of the event to interested parties.
5258     * <p>
5259     * If an {@link AccessibilityDelegate} has been specified via calling
5260     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5261     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5262     * responsible for handling this call.
5263     * </p>
5264     *
5265     * @param eventType The type of the event to send, as defined by several types from
5266     * {@link android.view.accessibility.AccessibilityEvent}, such as
5267     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5268     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5269     *
5270     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5271     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5272     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5273     * @see AccessibilityDelegate
5274     */
5275    public void sendAccessibilityEvent(int eventType) {
5276        if (mAccessibilityDelegate != null) {
5277            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5278        } else {
5279            sendAccessibilityEventInternal(eventType);
5280        }
5281    }
5282
5283    /**
5284     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5285     * {@link AccessibilityEvent} to make an announcement which is related to some
5286     * sort of a context change for which none of the events representing UI transitions
5287     * is a good fit. For example, announcing a new page in a book. If accessibility
5288     * is not enabled this method does nothing.
5289     *
5290     * @param text The announcement text.
5291     */
5292    public void announceForAccessibility(CharSequence text) {
5293        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5294            AccessibilityEvent event = AccessibilityEvent.obtain(
5295                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5296            onInitializeAccessibilityEvent(event);
5297            event.getText().add(text);
5298            event.setContentDescription(null);
5299            mParent.requestSendAccessibilityEvent(this, event);
5300        }
5301    }
5302
5303    /**
5304     * @see #sendAccessibilityEvent(int)
5305     *
5306     * Note: Called from the default {@link AccessibilityDelegate}.
5307     *
5308     * @hide
5309     */
5310    public void sendAccessibilityEventInternal(int eventType) {
5311        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5312            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5313        }
5314    }
5315
5316    /**
5317     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5318     * takes as an argument an empty {@link AccessibilityEvent} and does not
5319     * perform a check whether accessibility is enabled.
5320     * <p>
5321     * If an {@link AccessibilityDelegate} has been specified via calling
5322     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5323     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5324     * is responsible for handling this call.
5325     * </p>
5326     *
5327     * @param event The event to send.
5328     *
5329     * @see #sendAccessibilityEvent(int)
5330     */
5331    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5332        if (mAccessibilityDelegate != null) {
5333            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5334        } else {
5335            sendAccessibilityEventUncheckedInternal(event);
5336        }
5337    }
5338
5339    /**
5340     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5341     *
5342     * Note: Called from the default {@link AccessibilityDelegate}.
5343     *
5344     * @hide
5345     */
5346    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5347        if (!isShown()) {
5348            return;
5349        }
5350        onInitializeAccessibilityEvent(event);
5351        // Only a subset of accessibility events populates text content.
5352        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5353            dispatchPopulateAccessibilityEvent(event);
5354        }
5355        // In the beginning we called #isShown(), so we know that getParent() is not null.
5356        getParent().requestSendAccessibilityEvent(this, event);
5357    }
5358
5359    /**
5360     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5361     * to its children for adding their text content to the event. Note that the
5362     * event text is populated in a separate dispatch path since we add to the
5363     * event not only the text of the source but also the text of all its descendants.
5364     * A typical implementation will call
5365     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5366     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5367     * on each child. Override this method if custom population of the event text
5368     * content is required.
5369     * <p>
5370     * If an {@link AccessibilityDelegate} has been specified via calling
5371     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5372     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5373     * is responsible for handling this call.
5374     * </p>
5375     * <p>
5376     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5377     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5378     * </p>
5379     *
5380     * @param event The event.
5381     *
5382     * @return True if the event population was completed.
5383     */
5384    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5385        if (mAccessibilityDelegate != null) {
5386            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5387        } else {
5388            return dispatchPopulateAccessibilityEventInternal(event);
5389        }
5390    }
5391
5392    /**
5393     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5394     *
5395     * Note: Called from the default {@link AccessibilityDelegate}.
5396     *
5397     * @hide
5398     */
5399    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5400        onPopulateAccessibilityEvent(event);
5401        return false;
5402    }
5403
5404    /**
5405     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5406     * giving a chance to this View to populate the accessibility event with its
5407     * text content. While this method is free to modify event
5408     * attributes other than text content, doing so should normally be performed in
5409     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5410     * <p>
5411     * Example: Adding formatted date string to an accessibility event in addition
5412     *          to the text added by the super implementation:
5413     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5414     *     super.onPopulateAccessibilityEvent(event);
5415     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5416     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5417     *         mCurrentDate.getTimeInMillis(), flags);
5418     *     event.getText().add(selectedDateUtterance);
5419     * }</pre>
5420     * <p>
5421     * If an {@link AccessibilityDelegate} has been specified via calling
5422     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5423     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5424     * is responsible for handling this call.
5425     * </p>
5426     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5427     * information to the event, in case the default implementation has basic information to add.
5428     * </p>
5429     *
5430     * @param event The accessibility event which to populate.
5431     *
5432     * @see #sendAccessibilityEvent(int)
5433     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5434     */
5435    @CallSuper
5436    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5437        if (mAccessibilityDelegate != null) {
5438            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5439        } else {
5440            onPopulateAccessibilityEventInternal(event);
5441        }
5442    }
5443
5444    /**
5445     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5446     *
5447     * Note: Called from the default {@link AccessibilityDelegate}.
5448     *
5449     * @hide
5450     */
5451    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5452    }
5453
5454    /**
5455     * Initializes an {@link AccessibilityEvent} with information about
5456     * this View which is the event source. In other words, the source of
5457     * an accessibility event is the view whose state change triggered firing
5458     * the event.
5459     * <p>
5460     * Example: Setting the password property of an event in addition
5461     *          to properties set by the super implementation:
5462     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5463     *     super.onInitializeAccessibilityEvent(event);
5464     *     event.setPassword(true);
5465     * }</pre>
5466     * <p>
5467     * If an {@link AccessibilityDelegate} has been specified via calling
5468     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5469     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5470     * is responsible for handling this call.
5471     * </p>
5472     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5473     * information to the event, in case the default implementation has basic information to add.
5474     * </p>
5475     * @param event The event to initialize.
5476     *
5477     * @see #sendAccessibilityEvent(int)
5478     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5479     */
5480    @CallSuper
5481    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5482        if (mAccessibilityDelegate != null) {
5483            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5484        } else {
5485            onInitializeAccessibilityEventInternal(event);
5486        }
5487    }
5488
5489    /**
5490     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5491     *
5492     * Note: Called from the default {@link AccessibilityDelegate}.
5493     *
5494     * @hide
5495     */
5496    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5497        event.setSource(this);
5498        event.setClassName(getAccessibilityClassName());
5499        event.setPackageName(getContext().getPackageName());
5500        event.setEnabled(isEnabled());
5501        event.setContentDescription(mContentDescription);
5502
5503        switch (event.getEventType()) {
5504            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5505                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5506                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5507                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5508                event.setItemCount(focusablesTempList.size());
5509                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5510                if (mAttachInfo != null) {
5511                    focusablesTempList.clear();
5512                }
5513            } break;
5514            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5515                CharSequence text = getIterableTextForAccessibility();
5516                if (text != null && text.length() > 0) {
5517                    event.setFromIndex(getAccessibilitySelectionStart());
5518                    event.setToIndex(getAccessibilitySelectionEnd());
5519                    event.setItemCount(text.length());
5520                }
5521            } break;
5522        }
5523    }
5524
5525    /**
5526     * Returns an {@link AccessibilityNodeInfo} representing this view from the
5527     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
5528     * This method is responsible for obtaining an accessibility node info from a
5529     * pool of reusable instances and calling
5530     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
5531     * initialize the former.
5532     * <p>
5533     * Note: The client is responsible for recycling the obtained instance by calling
5534     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
5535     * </p>
5536     *
5537     * @return A populated {@link AccessibilityNodeInfo}.
5538     *
5539     * @see AccessibilityNodeInfo
5540     */
5541    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
5542        if (mAccessibilityDelegate != null) {
5543            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
5544        } else {
5545            return createAccessibilityNodeInfoInternal();
5546        }
5547    }
5548
5549    /**
5550     * @see #createAccessibilityNodeInfo()
5551     *
5552     * @hide
5553     */
5554    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
5555        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5556        if (provider != null) {
5557            return provider.createAccessibilityNodeInfo(View.NO_ID);
5558        } else {
5559            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
5560            onInitializeAccessibilityNodeInfo(info);
5561            return info;
5562        }
5563    }
5564
5565    /**
5566     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
5567     * The base implementation sets:
5568     * <ul>
5569     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
5570     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
5571     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
5572     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
5573     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
5574     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
5575     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
5576     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
5577     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
5578     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
5579     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
5580     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
5581     * </ul>
5582     * <p>
5583     * Subclasses should override this method, call the super implementation,
5584     * and set additional attributes.
5585     * </p>
5586     * <p>
5587     * If an {@link AccessibilityDelegate} has been specified via calling
5588     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5589     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
5590     * is responsible for handling this call.
5591     * </p>
5592     *
5593     * @param info The instance to initialize.
5594     */
5595    @CallSuper
5596    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
5597        if (mAccessibilityDelegate != null) {
5598            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
5599        } else {
5600            onInitializeAccessibilityNodeInfoInternal(info);
5601        }
5602    }
5603
5604    /**
5605     * Gets the location of this view in screen coordinates.
5606     *
5607     * @param outRect The output location
5608     * @hide
5609     */
5610    public void getBoundsOnScreen(Rect outRect) {
5611        getBoundsOnScreen(outRect, false);
5612    }
5613
5614    /**
5615     * Gets the location of this view in screen coordinates.
5616     *
5617     * @param outRect The output location
5618     * @param clipToParent Whether to clip child bounds to the parent ones.
5619     * @hide
5620     */
5621    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
5622        if (mAttachInfo == null) {
5623            return;
5624        }
5625
5626        RectF position = mAttachInfo.mTmpTransformRect;
5627        position.set(0, 0, mRight - mLeft, mBottom - mTop);
5628
5629        if (!hasIdentityMatrix()) {
5630            getMatrix().mapRect(position);
5631        }
5632
5633        position.offset(mLeft, mTop);
5634
5635        ViewParent parent = mParent;
5636        while (parent instanceof View) {
5637            View parentView = (View) parent;
5638
5639            position.offset(-parentView.mScrollX, -parentView.mScrollY);
5640
5641            if (clipToParent) {
5642                position.left = Math.max(position.left, 0);
5643                position.top = Math.max(position.top, 0);
5644                position.right = Math.min(position.right, parentView.getWidth());
5645                position.bottom = Math.min(position.bottom, parentView.getHeight());
5646            }
5647
5648            if (!parentView.hasIdentityMatrix()) {
5649                parentView.getMatrix().mapRect(position);
5650            }
5651
5652            position.offset(parentView.mLeft, parentView.mTop);
5653
5654            parent = parentView.mParent;
5655        }
5656
5657        if (parent instanceof ViewRootImpl) {
5658            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
5659            position.offset(0, -viewRootImpl.mCurScrollY);
5660        }
5661
5662        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
5663
5664        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
5665                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
5666    }
5667
5668    /**
5669     * Return the class name of this object to be used for accessibility purposes.
5670     * Subclasses should only override this if they are implementing something that
5671     * should be seen as a completely new class of view when used by accessibility,
5672     * unrelated to the class it is deriving from.  This is used to fill in
5673     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
5674     */
5675    public CharSequence getAccessibilityClassName() {
5676        return View.class.getName();
5677    }
5678
5679    /**
5680     * Called when assist structure is being retrieved from a view as part of
5681     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
5682     * @param structure Fill in with structured view data.  The default implementation
5683     * fills in all data that can be inferred from the view itself.
5684     */
5685    public void onProvideAssistStructure(ViewAssistStructure structure) {
5686        final int id = mID;
5687        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
5688                && (id&0x0000ffff) != 0) {
5689            String pkg, type, entry;
5690            try {
5691                final Resources res = getResources();
5692                entry = res.getResourceEntryName(id);
5693                type = res.getResourceTypeName(id);
5694                pkg = res.getResourcePackageName(id);
5695            } catch (Resources.NotFoundException e) {
5696                entry = type = pkg = null;
5697            }
5698            structure.setId(id, pkg, type, entry);
5699        } else {
5700            structure.setId(id, null, null, null);
5701        }
5702        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight-mLeft, mBottom-mTop);
5703        structure.setVisibility(getVisibility());
5704        structure.setEnabled(isEnabled());
5705        if (isClickable()) {
5706            structure.setClickable(true);
5707        }
5708        if (isFocusable()) {
5709            structure.setFocusable(true);
5710        }
5711        if (isFocused()) {
5712            structure.setFocused(true);
5713        }
5714        if (isAccessibilityFocused()) {
5715            structure.setAccessibilityFocused(true);
5716        }
5717        if (isSelected()) {
5718            structure.setSelected(true);
5719        }
5720        if (isActivated()) {
5721            structure.setActivated(true);
5722        }
5723        if (isLongClickable()) {
5724            structure.setLongClickable(true);
5725        }
5726        if (this instanceof Checkable) {
5727            structure.setCheckable(true);
5728            if (((Checkable)this).isChecked()) {
5729                structure.setChecked(true);
5730            }
5731        }
5732        structure.setClassName(getAccessibilityClassName().toString());
5733        structure.setContentDescription(getContentDescription());
5734    }
5735
5736    /**
5737     * Called when assist structure is being retrieved from a view as part of
5738     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
5739     * generate additional virtual structure under this view.  The defaullt implementation
5740     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
5741     * view's virtual accessibility nodes, if any.  You can override this for a more
5742     * optimal implementation providing this data.
5743     */
5744    public void onProvideVirtualAssistStructure(ViewAssistStructure structure) {
5745        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
5746        if (provider != null) {
5747            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
5748            Log.i("View", "Provider of " + this + ": children=" + info.getChildCount());
5749            structure.setChildCount(1);
5750            ViewAssistStructure root = structure.newChild(0);
5751            populateVirtualAssistStructure(root, provider, info);
5752            info.recycle();
5753        }
5754    }
5755
5756    private void populateVirtualAssistStructure(ViewAssistStructure structure,
5757            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
5758        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
5759                null, null, null);
5760        Rect rect = structure.getTempRect();
5761        info.getBoundsInParent(rect);
5762        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
5763        structure.setVisibility(VISIBLE);
5764        structure.setEnabled(info.isEnabled());
5765        if (info.isClickable()) {
5766            structure.setClickable(true);
5767        }
5768        if (info.isFocusable()) {
5769            structure.setFocusable(true);
5770        }
5771        if (info.isFocused()) {
5772            structure.setFocused(true);
5773        }
5774        if (info.isAccessibilityFocused()) {
5775            structure.setAccessibilityFocused(true);
5776        }
5777        if (info.isSelected()) {
5778            structure.setSelected(true);
5779        }
5780        if (info.isLongClickable()) {
5781            structure.setLongClickable(true);
5782        }
5783        if (info.isCheckable()) {
5784            structure.setCheckable(true);
5785            if (info.isChecked()) {
5786                structure.setChecked(true);
5787            }
5788        }
5789        CharSequence cname = info.getClassName();
5790        structure.setClassName(cname != null ? cname.toString() : null);
5791        structure.setContentDescription(info.getContentDescription());
5792        Log.i("View", "vassist " + cname + " @ " + rect.toShortString()
5793                + " text=" + info.getText() + " cd=" + info.getContentDescription());
5794        if (info.getText() != null || info.getError() != null) {
5795            structure.setText(info.getText(), info.getTextSelectionStart(),
5796                    info.getTextSelectionEnd());
5797        }
5798        final int NCHILDREN = info.getChildCount();
5799        if (NCHILDREN > 0) {
5800            structure.setChildCount(NCHILDREN);
5801            for (int i=0; i<NCHILDREN; i++) {
5802                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
5803                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
5804                ViewAssistStructure child = structure.newChild(i);
5805                populateVirtualAssistStructure(child, provider, cinfo);
5806                cinfo.recycle();
5807            }
5808        }
5809    }
5810
5811    /**
5812     * Dispatch creation of {@link ViewAssistStructure} down the hierarchy.  The default
5813     * implementation calls {@link #onProvideAssistStructure} and
5814     * {@link #onProvideVirtualAssistStructure}.
5815     */
5816    public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
5817        onProvideAssistStructure(structure);
5818        onProvideVirtualAssistStructure(structure);
5819    }
5820
5821    /**
5822     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
5823     *
5824     * Note: Called from the default {@link AccessibilityDelegate}.
5825     *
5826     * @hide
5827     */
5828    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
5829        Rect bounds = mAttachInfo.mTmpInvalRect;
5830
5831        getDrawingRect(bounds);
5832        info.setBoundsInParent(bounds);
5833
5834        getBoundsOnScreen(bounds, true);
5835        info.setBoundsInScreen(bounds);
5836
5837        ViewParent parent = getParentForAccessibility();
5838        if (parent instanceof View) {
5839            info.setParent((View) parent);
5840        }
5841
5842        if (mID != View.NO_ID) {
5843            View rootView = getRootView();
5844            if (rootView == null) {
5845                rootView = this;
5846            }
5847
5848            View label = rootView.findLabelForView(this, mID);
5849            if (label != null) {
5850                info.setLabeledBy(label);
5851            }
5852
5853            if ((mAttachInfo.mAccessibilityFetchFlags
5854                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
5855                    && Resources.resourceHasPackage(mID)) {
5856                try {
5857                    String viewId = getResources().getResourceName(mID);
5858                    info.setViewIdResourceName(viewId);
5859                } catch (Resources.NotFoundException nfe) {
5860                    /* ignore */
5861                }
5862            }
5863        }
5864
5865        if (mLabelForId != View.NO_ID) {
5866            View rootView = getRootView();
5867            if (rootView == null) {
5868                rootView = this;
5869            }
5870            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
5871            if (labeled != null) {
5872                info.setLabelFor(labeled);
5873            }
5874        }
5875
5876        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
5877            View rootView = getRootView();
5878            if (rootView == null) {
5879                rootView = this;
5880            }
5881            View next = rootView.findViewInsideOutShouldExist(this,
5882                    mAccessibilityTraversalBeforeId);
5883            if (next != null) {
5884                info.setTraversalBefore(next);
5885            }
5886        }
5887
5888        if (mAccessibilityTraversalAfterId != View.NO_ID) {
5889            View rootView = getRootView();
5890            if (rootView == null) {
5891                rootView = this;
5892            }
5893            View next = rootView.findViewInsideOutShouldExist(this,
5894                    mAccessibilityTraversalAfterId);
5895            if (next != null) {
5896                info.setTraversalAfter(next);
5897            }
5898        }
5899
5900        info.setVisibleToUser(isVisibleToUser());
5901
5902        info.setPackageName(mContext.getPackageName());
5903        info.setClassName(getAccessibilityClassName());
5904        info.setContentDescription(getContentDescription());
5905
5906        info.setEnabled(isEnabled());
5907        info.setClickable(isClickable());
5908        info.setFocusable(isFocusable());
5909        info.setFocused(isFocused());
5910        info.setAccessibilityFocused(isAccessibilityFocused());
5911        info.setSelected(isSelected());
5912        info.setLongClickable(isLongClickable());
5913        info.setLiveRegion(getAccessibilityLiveRegion());
5914
5915        // TODO: These make sense only if we are in an AdapterView but all
5916        // views can be selected. Maybe from accessibility perspective
5917        // we should report as selectable view in an AdapterView.
5918        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
5919        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
5920
5921        if (isFocusable()) {
5922            if (isFocused()) {
5923                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
5924            } else {
5925                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
5926            }
5927        }
5928
5929        if (!isAccessibilityFocused()) {
5930            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
5931        } else {
5932            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
5933        }
5934
5935        if (isClickable() && isEnabled()) {
5936            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
5937        }
5938
5939        if (isLongClickable() && isEnabled()) {
5940            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
5941        }
5942
5943        CharSequence text = getIterableTextForAccessibility();
5944        if (text != null && text.length() > 0) {
5945            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
5946
5947            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
5948            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
5949            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
5950            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
5951                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
5952                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
5953        }
5954
5955        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
5956    }
5957
5958    private View findLabelForView(View view, int labeledId) {
5959        if (mMatchLabelForPredicate == null) {
5960            mMatchLabelForPredicate = new MatchLabelForPredicate();
5961        }
5962        mMatchLabelForPredicate.mLabeledId = labeledId;
5963        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
5964    }
5965
5966    /**
5967     * Computes whether this view is visible to the user. Such a view is
5968     * attached, visible, all its predecessors are visible, it is not clipped
5969     * entirely by its predecessors, and has an alpha greater than zero.
5970     *
5971     * @return Whether the view is visible on the screen.
5972     *
5973     * @hide
5974     */
5975    protected boolean isVisibleToUser() {
5976        return isVisibleToUser(null);
5977    }
5978
5979    /**
5980     * Computes whether the given portion of this view is visible to the user.
5981     * Such a view is attached, visible, all its predecessors are visible,
5982     * has an alpha greater than zero, and the specified portion is not
5983     * clipped entirely by its predecessors.
5984     *
5985     * @param boundInView the portion of the view to test; coordinates should be relative; may be
5986     *                    <code>null</code>, and the entire view will be tested in this case.
5987     *                    When <code>true</code> is returned by the function, the actual visible
5988     *                    region will be stored in this parameter; that is, if boundInView is fully
5989     *                    contained within the view, no modification will be made, otherwise regions
5990     *                    outside of the visible area of the view will be clipped.
5991     *
5992     * @return Whether the specified portion of the view is visible on the screen.
5993     *
5994     * @hide
5995     */
5996    protected boolean isVisibleToUser(Rect boundInView) {
5997        if (mAttachInfo != null) {
5998            // Attached to invisible window means this view is not visible.
5999            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6000                return false;
6001            }
6002            // An invisible predecessor or one with alpha zero means
6003            // that this view is not visible to the user.
6004            Object current = this;
6005            while (current instanceof View) {
6006                View view = (View) current;
6007                // We have attach info so this view is attached and there is no
6008                // need to check whether we reach to ViewRootImpl on the way up.
6009                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6010                        view.getVisibility() != VISIBLE) {
6011                    return false;
6012                }
6013                current = view.mParent;
6014            }
6015            // Check if the view is entirely covered by its predecessors.
6016            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6017            Point offset = mAttachInfo.mPoint;
6018            if (!getGlobalVisibleRect(visibleRect, offset)) {
6019                return false;
6020            }
6021            // Check if the visible portion intersects the rectangle of interest.
6022            if (boundInView != null) {
6023                visibleRect.offset(-offset.x, -offset.y);
6024                return boundInView.intersect(visibleRect);
6025            }
6026            return true;
6027        }
6028        return false;
6029    }
6030
6031    /**
6032     * Returns the delegate for implementing accessibility support via
6033     * composition. For more details see {@link AccessibilityDelegate}.
6034     *
6035     * @return The delegate, or null if none set.
6036     *
6037     * @hide
6038     */
6039    public AccessibilityDelegate getAccessibilityDelegate() {
6040        return mAccessibilityDelegate;
6041    }
6042
6043    /**
6044     * Sets a delegate for implementing accessibility support via composition as
6045     * opposed to inheritance. The delegate's primary use is for implementing
6046     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6047     *
6048     * @param delegate The delegate instance.
6049     *
6050     * @see AccessibilityDelegate
6051     */
6052    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6053        mAccessibilityDelegate = delegate;
6054    }
6055
6056    /**
6057     * Gets the provider for managing a virtual view hierarchy rooted at this View
6058     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6059     * that explore the window content.
6060     * <p>
6061     * If this method returns an instance, this instance is responsible for managing
6062     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6063     * View including the one representing the View itself. Similarly the returned
6064     * instance is responsible for performing accessibility actions on any virtual
6065     * view or the root view itself.
6066     * </p>
6067     * <p>
6068     * If an {@link AccessibilityDelegate} has been specified via calling
6069     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6070     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6071     * is responsible for handling this call.
6072     * </p>
6073     *
6074     * @return The provider.
6075     *
6076     * @see AccessibilityNodeProvider
6077     */
6078    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6079        if (mAccessibilityDelegate != null) {
6080            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6081        } else {
6082            return null;
6083        }
6084    }
6085
6086    /**
6087     * Gets the unique identifier of this view on the screen for accessibility purposes.
6088     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6089     *
6090     * @return The view accessibility id.
6091     *
6092     * @hide
6093     */
6094    public int getAccessibilityViewId() {
6095        if (mAccessibilityViewId == NO_ID) {
6096            mAccessibilityViewId = sNextAccessibilityViewId++;
6097        }
6098        return mAccessibilityViewId;
6099    }
6100
6101    /**
6102     * Gets the unique identifier of the window in which this View reseides.
6103     *
6104     * @return The window accessibility id.
6105     *
6106     * @hide
6107     */
6108    public int getAccessibilityWindowId() {
6109        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6110                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6111    }
6112
6113    /**
6114     * Gets the {@link View} description. It briefly describes the view and is
6115     * primarily used for accessibility support. Set this property to enable
6116     * better accessibility support for your application. This is especially
6117     * true for views that do not have textual representation (For example,
6118     * ImageButton).
6119     *
6120     * @return The content description.
6121     *
6122     * @attr ref android.R.styleable#View_contentDescription
6123     */
6124    @ViewDebug.ExportedProperty(category = "accessibility")
6125    public CharSequence getContentDescription() {
6126        return mContentDescription;
6127    }
6128
6129    /**
6130     * Sets the {@link View} description. It briefly describes the view and is
6131     * primarily used for accessibility support. Set this property to enable
6132     * better accessibility support for your application. This is especially
6133     * true for views that do not have textual representation (For example,
6134     * ImageButton).
6135     *
6136     * @param contentDescription The content description.
6137     *
6138     * @attr ref android.R.styleable#View_contentDescription
6139     */
6140    @RemotableViewMethod
6141    public void setContentDescription(CharSequence contentDescription) {
6142        if (mContentDescription == null) {
6143            if (contentDescription == null) {
6144                return;
6145            }
6146        } else if (mContentDescription.equals(contentDescription)) {
6147            return;
6148        }
6149        mContentDescription = contentDescription;
6150        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6151        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6152            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6153            notifySubtreeAccessibilityStateChangedIfNeeded();
6154        } else {
6155            notifyViewAccessibilityStateChangedIfNeeded(
6156                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6157        }
6158    }
6159
6160    /**
6161     * Sets the id of a view before which this one is visited in accessibility traversal.
6162     * A screen-reader must visit the content of this view before the content of the one
6163     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6164     * will traverse the entire content of B before traversing the entire content of A,
6165     * regardles of what traversal strategy it is using.
6166     * <p>
6167     * Views that do not have specified before/after relationships are traversed in order
6168     * determined by the screen-reader.
6169     * </p>
6170     * <p>
6171     * Setting that this view is before a view that is not important for accessibility
6172     * or if this view is not important for accessibility will have no effect as the
6173     * screen-reader is not aware of unimportant views.
6174     * </p>
6175     *
6176     * @param beforeId The id of a view this one precedes in accessibility traversal.
6177     *
6178     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6179     *
6180     * @see #setImportantForAccessibility(int)
6181     */
6182    @RemotableViewMethod
6183    public void setAccessibilityTraversalBefore(int beforeId) {
6184        if (mAccessibilityTraversalBeforeId == beforeId) {
6185            return;
6186        }
6187        mAccessibilityTraversalBeforeId = beforeId;
6188        notifyViewAccessibilityStateChangedIfNeeded(
6189                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6190    }
6191
6192    /**
6193     * Gets the id of a view before which this one is visited in accessibility traversal.
6194     *
6195     * @return The id of a view this one precedes in accessibility traversal if
6196     *         specified, otherwise {@link #NO_ID}.
6197     *
6198     * @see #setAccessibilityTraversalBefore(int)
6199     */
6200    public int getAccessibilityTraversalBefore() {
6201        return mAccessibilityTraversalBeforeId;
6202    }
6203
6204    /**
6205     * Sets the id of a view after which this one is visited in accessibility traversal.
6206     * A screen-reader must visit the content of the other view before the content of this
6207     * one. For example, if view B is set to be after view A, then a screen-reader
6208     * will traverse the entire content of A before traversing the entire content of B,
6209     * regardles of what traversal strategy it is using.
6210     * <p>
6211     * Views that do not have specified before/after relationships are traversed in order
6212     * determined by the screen-reader.
6213     * </p>
6214     * <p>
6215     * Setting that this view is after a view that is not important for accessibility
6216     * or if this view is not important for accessibility will have no effect as the
6217     * screen-reader is not aware of unimportant views.
6218     * </p>
6219     *
6220     * @param afterId The id of a view this one succedees in accessibility traversal.
6221     *
6222     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6223     *
6224     * @see #setImportantForAccessibility(int)
6225     */
6226    @RemotableViewMethod
6227    public void setAccessibilityTraversalAfter(int afterId) {
6228        if (mAccessibilityTraversalAfterId == afterId) {
6229            return;
6230        }
6231        mAccessibilityTraversalAfterId = afterId;
6232        notifyViewAccessibilityStateChangedIfNeeded(
6233                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6234    }
6235
6236    /**
6237     * Gets the id of a view after which this one is visited in accessibility traversal.
6238     *
6239     * @return The id of a view this one succeedes in accessibility traversal if
6240     *         specified, otherwise {@link #NO_ID}.
6241     *
6242     * @see #setAccessibilityTraversalAfter(int)
6243     */
6244    public int getAccessibilityTraversalAfter() {
6245        return mAccessibilityTraversalAfterId;
6246    }
6247
6248    /**
6249     * Gets the id of a view for which this view serves as a label for
6250     * accessibility purposes.
6251     *
6252     * @return The labeled view id.
6253     */
6254    @ViewDebug.ExportedProperty(category = "accessibility")
6255    public int getLabelFor() {
6256        return mLabelForId;
6257    }
6258
6259    /**
6260     * Sets the id of a view for which this view serves as a label for
6261     * accessibility purposes.
6262     *
6263     * @param id The labeled view id.
6264     */
6265    @RemotableViewMethod
6266    public void setLabelFor(@IdRes int id) {
6267        if (mLabelForId == id) {
6268            return;
6269        }
6270        mLabelForId = id;
6271        if (mLabelForId != View.NO_ID
6272                && mID == View.NO_ID) {
6273            mID = generateViewId();
6274        }
6275        notifyViewAccessibilityStateChangedIfNeeded(
6276                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6277    }
6278
6279    /**
6280     * Invoked whenever this view loses focus, either by losing window focus or by losing
6281     * focus within its window. This method can be used to clear any state tied to the
6282     * focus. For instance, if a button is held pressed with the trackball and the window
6283     * loses focus, this method can be used to cancel the press.
6284     *
6285     * Subclasses of View overriding this method should always call super.onFocusLost().
6286     *
6287     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6288     * @see #onWindowFocusChanged(boolean)
6289     *
6290     * @hide pending API council approval
6291     */
6292    @CallSuper
6293    protected void onFocusLost() {
6294        resetPressedState();
6295    }
6296
6297    private void resetPressedState() {
6298        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6299            return;
6300        }
6301
6302        if (isPressed()) {
6303            setPressed(false);
6304
6305            if (!mHasPerformedLongPress) {
6306                removeLongPressCallback();
6307            }
6308        }
6309    }
6310
6311    /**
6312     * Returns true if this view has focus
6313     *
6314     * @return True if this view has focus, false otherwise.
6315     */
6316    @ViewDebug.ExportedProperty(category = "focus")
6317    public boolean isFocused() {
6318        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6319    }
6320
6321    /**
6322     * Find the view in the hierarchy rooted at this view that currently has
6323     * focus.
6324     *
6325     * @return The view that currently has focus, or null if no focused view can
6326     *         be found.
6327     */
6328    public View findFocus() {
6329        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6330    }
6331
6332    /**
6333     * Indicates whether this view is one of the set of scrollable containers in
6334     * its window.
6335     *
6336     * @return whether this view is one of the set of scrollable containers in
6337     * its window
6338     *
6339     * @attr ref android.R.styleable#View_isScrollContainer
6340     */
6341    public boolean isScrollContainer() {
6342        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6343    }
6344
6345    /**
6346     * Change whether this view is one of the set of scrollable containers in
6347     * its window.  This will be used to determine whether the window can
6348     * resize or must pan when a soft input area is open -- scrollable
6349     * containers allow the window to use resize mode since the container
6350     * will appropriately shrink.
6351     *
6352     * @attr ref android.R.styleable#View_isScrollContainer
6353     */
6354    public void setScrollContainer(boolean isScrollContainer) {
6355        if (isScrollContainer) {
6356            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6357                mAttachInfo.mScrollContainers.add(this);
6358                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6359            }
6360            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6361        } else {
6362            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6363                mAttachInfo.mScrollContainers.remove(this);
6364            }
6365            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6366        }
6367    }
6368
6369    /**
6370     * Returns the quality of the drawing cache.
6371     *
6372     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6373     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6374     *
6375     * @see #setDrawingCacheQuality(int)
6376     * @see #setDrawingCacheEnabled(boolean)
6377     * @see #isDrawingCacheEnabled()
6378     *
6379     * @attr ref android.R.styleable#View_drawingCacheQuality
6380     */
6381    @DrawingCacheQuality
6382    public int getDrawingCacheQuality() {
6383        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6384    }
6385
6386    /**
6387     * Set the drawing cache quality of this view. This value is used only when the
6388     * drawing cache is enabled
6389     *
6390     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6391     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6392     *
6393     * @see #getDrawingCacheQuality()
6394     * @see #setDrawingCacheEnabled(boolean)
6395     * @see #isDrawingCacheEnabled()
6396     *
6397     * @attr ref android.R.styleable#View_drawingCacheQuality
6398     */
6399    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6400        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6401    }
6402
6403    /**
6404     * Returns whether the screen should remain on, corresponding to the current
6405     * value of {@link #KEEP_SCREEN_ON}.
6406     *
6407     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6408     *
6409     * @see #setKeepScreenOn(boolean)
6410     *
6411     * @attr ref android.R.styleable#View_keepScreenOn
6412     */
6413    public boolean getKeepScreenOn() {
6414        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6415    }
6416
6417    /**
6418     * Controls whether the screen should remain on, modifying the
6419     * value of {@link #KEEP_SCREEN_ON}.
6420     *
6421     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6422     *
6423     * @see #getKeepScreenOn()
6424     *
6425     * @attr ref android.R.styleable#View_keepScreenOn
6426     */
6427    public void setKeepScreenOn(boolean keepScreenOn) {
6428        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6429    }
6430
6431    /**
6432     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6433     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6434     *
6435     * @attr ref android.R.styleable#View_nextFocusLeft
6436     */
6437    public int getNextFocusLeftId() {
6438        return mNextFocusLeftId;
6439    }
6440
6441    /**
6442     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6443     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6444     * decide automatically.
6445     *
6446     * @attr ref android.R.styleable#View_nextFocusLeft
6447     */
6448    public void setNextFocusLeftId(int nextFocusLeftId) {
6449        mNextFocusLeftId = nextFocusLeftId;
6450    }
6451
6452    /**
6453     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6454     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6455     *
6456     * @attr ref android.R.styleable#View_nextFocusRight
6457     */
6458    public int getNextFocusRightId() {
6459        return mNextFocusRightId;
6460    }
6461
6462    /**
6463     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6464     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6465     * decide automatically.
6466     *
6467     * @attr ref android.R.styleable#View_nextFocusRight
6468     */
6469    public void setNextFocusRightId(int nextFocusRightId) {
6470        mNextFocusRightId = nextFocusRightId;
6471    }
6472
6473    /**
6474     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6475     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6476     *
6477     * @attr ref android.R.styleable#View_nextFocusUp
6478     */
6479    public int getNextFocusUpId() {
6480        return mNextFocusUpId;
6481    }
6482
6483    /**
6484     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6485     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6486     * decide automatically.
6487     *
6488     * @attr ref android.R.styleable#View_nextFocusUp
6489     */
6490    public void setNextFocusUpId(int nextFocusUpId) {
6491        mNextFocusUpId = nextFocusUpId;
6492    }
6493
6494    /**
6495     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6496     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6497     *
6498     * @attr ref android.R.styleable#View_nextFocusDown
6499     */
6500    public int getNextFocusDownId() {
6501        return mNextFocusDownId;
6502    }
6503
6504    /**
6505     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
6506     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
6507     * decide automatically.
6508     *
6509     * @attr ref android.R.styleable#View_nextFocusDown
6510     */
6511    public void setNextFocusDownId(int nextFocusDownId) {
6512        mNextFocusDownId = nextFocusDownId;
6513    }
6514
6515    /**
6516     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6517     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6518     *
6519     * @attr ref android.R.styleable#View_nextFocusForward
6520     */
6521    public int getNextFocusForwardId() {
6522        return mNextFocusForwardId;
6523    }
6524
6525    /**
6526     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
6527     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
6528     * decide automatically.
6529     *
6530     * @attr ref android.R.styleable#View_nextFocusForward
6531     */
6532    public void setNextFocusForwardId(int nextFocusForwardId) {
6533        mNextFocusForwardId = nextFocusForwardId;
6534    }
6535
6536    /**
6537     * Returns the visibility of this view and all of its ancestors
6538     *
6539     * @return True if this view and all of its ancestors are {@link #VISIBLE}
6540     */
6541    public boolean isShown() {
6542        View current = this;
6543        //noinspection ConstantConditions
6544        do {
6545            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6546                return false;
6547            }
6548            ViewParent parent = current.mParent;
6549            if (parent == null) {
6550                return false; // We are not attached to the view root
6551            }
6552            if (!(parent instanceof View)) {
6553                return true;
6554            }
6555            current = (View) parent;
6556        } while (current != null);
6557
6558        return false;
6559    }
6560
6561    /**
6562     * Called by the view hierarchy when the content insets for a window have
6563     * changed, to allow it to adjust its content to fit within those windows.
6564     * The content insets tell you the space that the status bar, input method,
6565     * and other system windows infringe on the application's window.
6566     *
6567     * <p>You do not normally need to deal with this function, since the default
6568     * window decoration given to applications takes care of applying it to the
6569     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
6570     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
6571     * and your content can be placed under those system elements.  You can then
6572     * use this method within your view hierarchy if you have parts of your UI
6573     * which you would like to ensure are not being covered.
6574     *
6575     * <p>The default implementation of this method simply applies the content
6576     * insets to the view's padding, consuming that content (modifying the
6577     * insets to be 0), and returning true.  This behavior is off by default, but can
6578     * be enabled through {@link #setFitsSystemWindows(boolean)}.
6579     *
6580     * <p>This function's traversal down the hierarchy is depth-first.  The same content
6581     * insets object is propagated down the hierarchy, so any changes made to it will
6582     * be seen by all following views (including potentially ones above in
6583     * the hierarchy since this is a depth-first traversal).  The first view
6584     * that returns true will abort the entire traversal.
6585     *
6586     * <p>The default implementation works well for a situation where it is
6587     * used with a container that covers the entire window, allowing it to
6588     * apply the appropriate insets to its content on all edges.  If you need
6589     * a more complicated layout (such as two different views fitting system
6590     * windows, one on the top of the window, and one on the bottom),
6591     * you can override the method and handle the insets however you would like.
6592     * Note that the insets provided by the framework are always relative to the
6593     * far edges of the window, not accounting for the location of the called view
6594     * within that window.  (In fact when this method is called you do not yet know
6595     * where the layout will place the view, as it is done before layout happens.)
6596     *
6597     * <p>Note: unlike many View methods, there is no dispatch phase to this
6598     * call.  If you are overriding it in a ViewGroup and want to allow the
6599     * call to continue to your children, you must be sure to call the super
6600     * implementation.
6601     *
6602     * <p>Here is a sample layout that makes use of fitting system windows
6603     * to have controls for a video view placed inside of the window decorations
6604     * that it hides and shows.  This can be used with code like the second
6605     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
6606     *
6607     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
6608     *
6609     * @param insets Current content insets of the window.  Prior to
6610     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
6611     * the insets or else you and Android will be unhappy.
6612     *
6613     * @return {@code true} if this view applied the insets and it should not
6614     * continue propagating further down the hierarchy, {@code false} otherwise.
6615     * @see #getFitsSystemWindows()
6616     * @see #setFitsSystemWindows(boolean)
6617     * @see #setSystemUiVisibility(int)
6618     *
6619     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
6620     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
6621     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
6622     * to implement handling their own insets.
6623     */
6624    protected boolean fitSystemWindows(Rect insets) {
6625        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
6626            if (insets == null) {
6627                // Null insets by definition have already been consumed.
6628                // This call cannot apply insets since there are none to apply,
6629                // so return false.
6630                return false;
6631            }
6632            // If we're not in the process of dispatching the newer apply insets call,
6633            // that means we're not in the compatibility path. Dispatch into the newer
6634            // apply insets path and take things from there.
6635            try {
6636                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
6637                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
6638            } finally {
6639                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
6640            }
6641        } else {
6642            // We're being called from the newer apply insets path.
6643            // Perform the standard fallback behavior.
6644            return fitSystemWindowsInt(insets);
6645        }
6646    }
6647
6648    private boolean fitSystemWindowsInt(Rect insets) {
6649        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
6650            mUserPaddingStart = UNDEFINED_PADDING;
6651            mUserPaddingEnd = UNDEFINED_PADDING;
6652            Rect localInsets = sThreadLocal.get();
6653            if (localInsets == null) {
6654                localInsets = new Rect();
6655                sThreadLocal.set(localInsets);
6656            }
6657            boolean res = computeFitSystemWindows(insets, localInsets);
6658            mUserPaddingLeftInitial = localInsets.left;
6659            mUserPaddingRightInitial = localInsets.right;
6660            internalSetPadding(localInsets.left, localInsets.top,
6661                    localInsets.right, localInsets.bottom);
6662            return res;
6663        }
6664        return false;
6665    }
6666
6667    /**
6668     * Called when the view should apply {@link WindowInsets} according to its internal policy.
6669     *
6670     * <p>This method should be overridden by views that wish to apply a policy different from or
6671     * in addition to the default behavior. Clients that wish to force a view subtree
6672     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
6673     *
6674     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
6675     * it will be called during dispatch instead of this method. The listener may optionally
6676     * call this method from its own implementation if it wishes to apply the view's default
6677     * insets policy in addition to its own.</p>
6678     *
6679     * <p>Implementations of this method should either return the insets parameter unchanged
6680     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
6681     * that this view applied itself. This allows new inset types added in future platform
6682     * versions to pass through existing implementations unchanged without being erroneously
6683     * consumed.</p>
6684     *
6685     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
6686     * property is set then the view will consume the system window insets and apply them
6687     * as padding for the view.</p>
6688     *
6689     * @param insets Insets to apply
6690     * @return The supplied insets with any applied insets consumed
6691     */
6692    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
6693        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
6694            // We weren't called from within a direct call to fitSystemWindows,
6695            // call into it as a fallback in case we're in a class that overrides it
6696            // and has logic to perform.
6697            if (fitSystemWindows(insets.getSystemWindowInsets())) {
6698                return insets.consumeSystemWindowInsets();
6699            }
6700        } else {
6701            // We were called from within a direct call to fitSystemWindows.
6702            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
6703                return insets.consumeSystemWindowInsets();
6704            }
6705        }
6706        return insets;
6707    }
6708
6709    /**
6710     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
6711     * window insets to this view. The listener's
6712     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
6713     * method will be called instead of the view's
6714     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
6715     *
6716     * @param listener Listener to set
6717     *
6718     * @see #onApplyWindowInsets(WindowInsets)
6719     */
6720    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
6721        getListenerInfo().mOnApplyWindowInsetsListener = listener;
6722    }
6723
6724    /**
6725     * Request to apply the given window insets to this view or another view in its subtree.
6726     *
6727     * <p>This method should be called by clients wishing to apply insets corresponding to areas
6728     * obscured by window decorations or overlays. This can include the status and navigation bars,
6729     * action bars, input methods and more. New inset categories may be added in the future.
6730     * The method returns the insets provided minus any that were applied by this view or its
6731     * children.</p>
6732     *
6733     * <p>Clients wishing to provide custom behavior should override the
6734     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
6735     * {@link OnApplyWindowInsetsListener} via the
6736     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
6737     * method.</p>
6738     *
6739     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
6740     * </p>
6741     *
6742     * @param insets Insets to apply
6743     * @return The provided insets minus the insets that were consumed
6744     */
6745    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
6746        try {
6747            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
6748            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
6749                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
6750            } else {
6751                return onApplyWindowInsets(insets);
6752            }
6753        } finally {
6754            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
6755        }
6756    }
6757
6758    /**
6759     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
6760     * only available if the view is attached.
6761     *
6762     * @return WindowInsets from the top of the view hierarchy or null if View is detached
6763     */
6764    public WindowInsets getRootWindowInsets() {
6765        if (mAttachInfo != null) {
6766            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
6767        }
6768        return null;
6769    }
6770
6771    /**
6772     * @hide Compute the insets that should be consumed by this view and the ones
6773     * that should propagate to those under it.
6774     */
6775    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
6776        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6777                || mAttachInfo == null
6778                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
6779                        && !mAttachInfo.mOverscanRequested)) {
6780            outLocalInsets.set(inoutInsets);
6781            inoutInsets.set(0, 0, 0, 0);
6782            return true;
6783        } else {
6784            // The application wants to take care of fitting system window for
6785            // the content...  however we still need to take care of any overscan here.
6786            final Rect overscan = mAttachInfo.mOverscanInsets;
6787            outLocalInsets.set(overscan);
6788            inoutInsets.left -= overscan.left;
6789            inoutInsets.top -= overscan.top;
6790            inoutInsets.right -= overscan.right;
6791            inoutInsets.bottom -= overscan.bottom;
6792            return false;
6793        }
6794    }
6795
6796    /**
6797     * Compute insets that should be consumed by this view and the ones that should propagate
6798     * to those under it.
6799     *
6800     * @param in Insets currently being processed by this View, likely received as a parameter
6801     *           to {@link #onApplyWindowInsets(WindowInsets)}.
6802     * @param outLocalInsets A Rect that will receive the insets that should be consumed
6803     *                       by this view
6804     * @return Insets that should be passed along to views under this one
6805     */
6806    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
6807        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
6808                || mAttachInfo == null
6809                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
6810            outLocalInsets.set(in.getSystemWindowInsets());
6811            return in.consumeSystemWindowInsets();
6812        } else {
6813            outLocalInsets.set(0, 0, 0, 0);
6814            return in;
6815        }
6816    }
6817
6818    /**
6819     * Sets whether or not this view should account for system screen decorations
6820     * such as the status bar and inset its content; that is, controlling whether
6821     * the default implementation of {@link #fitSystemWindows(Rect)} will be
6822     * executed.  See that method for more details.
6823     *
6824     * <p>Note that if you are providing your own implementation of
6825     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
6826     * flag to true -- your implementation will be overriding the default
6827     * implementation that checks this flag.
6828     *
6829     * @param fitSystemWindows If true, then the default implementation of
6830     * {@link #fitSystemWindows(Rect)} will be executed.
6831     *
6832     * @attr ref android.R.styleable#View_fitsSystemWindows
6833     * @see #getFitsSystemWindows()
6834     * @see #fitSystemWindows(Rect)
6835     * @see #setSystemUiVisibility(int)
6836     */
6837    public void setFitsSystemWindows(boolean fitSystemWindows) {
6838        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
6839    }
6840
6841    /**
6842     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
6843     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
6844     * will be executed.
6845     *
6846     * @return {@code true} if the default implementation of
6847     * {@link #fitSystemWindows(Rect)} will be executed.
6848     *
6849     * @attr ref android.R.styleable#View_fitsSystemWindows
6850     * @see #setFitsSystemWindows(boolean)
6851     * @see #fitSystemWindows(Rect)
6852     * @see #setSystemUiVisibility(int)
6853     */
6854    @ViewDebug.ExportedProperty
6855    public boolean getFitsSystemWindows() {
6856        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
6857    }
6858
6859    /** @hide */
6860    public boolean fitsSystemWindows() {
6861        return getFitsSystemWindows();
6862    }
6863
6864    /**
6865     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
6866     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
6867     */
6868    public void requestFitSystemWindows() {
6869        if (mParent != null) {
6870            mParent.requestFitSystemWindows();
6871        }
6872    }
6873
6874    /**
6875     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
6876     */
6877    public void requestApplyInsets() {
6878        requestFitSystemWindows();
6879    }
6880
6881    /**
6882     * For use by PhoneWindow to make its own system window fitting optional.
6883     * @hide
6884     */
6885    public void makeOptionalFitsSystemWindows() {
6886        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
6887    }
6888
6889    /**
6890     * Returns the visibility status for this view.
6891     *
6892     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6893     * @attr ref android.R.styleable#View_visibility
6894     */
6895    @ViewDebug.ExportedProperty(mapping = {
6896        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
6897        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
6898        @ViewDebug.IntToString(from = GONE,      to = "GONE")
6899    })
6900    @Visibility
6901    public int getVisibility() {
6902        return mViewFlags & VISIBILITY_MASK;
6903    }
6904
6905    /**
6906     * Set the enabled state of this view.
6907     *
6908     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
6909     * @attr ref android.R.styleable#View_visibility
6910     */
6911    @RemotableViewMethod
6912    public void setVisibility(@Visibility int visibility) {
6913        setFlags(visibility, VISIBILITY_MASK);
6914    }
6915
6916    /**
6917     * Returns the enabled status for this view. The interpretation of the
6918     * enabled state varies by subclass.
6919     *
6920     * @return True if this view is enabled, false otherwise.
6921     */
6922    @ViewDebug.ExportedProperty
6923    public boolean isEnabled() {
6924        return (mViewFlags & ENABLED_MASK) == ENABLED;
6925    }
6926
6927    /**
6928     * Set the enabled state of this view. The interpretation of the enabled
6929     * state varies by subclass.
6930     *
6931     * @param enabled True if this view is enabled, false otherwise.
6932     */
6933    @RemotableViewMethod
6934    public void setEnabled(boolean enabled) {
6935        if (enabled == isEnabled()) return;
6936
6937        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
6938
6939        /*
6940         * The View most likely has to change its appearance, so refresh
6941         * the drawable state.
6942         */
6943        refreshDrawableState();
6944
6945        // Invalidate too, since the default behavior for views is to be
6946        // be drawn at 50% alpha rather than to change the drawable.
6947        invalidate(true);
6948
6949        if (!enabled) {
6950            cancelPendingInputEvents();
6951        }
6952    }
6953
6954    /**
6955     * Set whether this view can receive the focus.
6956     *
6957     * Setting this to false will also ensure that this view is not focusable
6958     * in touch mode.
6959     *
6960     * @param focusable If true, this view can receive the focus.
6961     *
6962     * @see #setFocusableInTouchMode(boolean)
6963     * @attr ref android.R.styleable#View_focusable
6964     */
6965    public void setFocusable(boolean focusable) {
6966        if (!focusable) {
6967            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
6968        }
6969        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
6970    }
6971
6972    /**
6973     * Set whether this view can receive focus while in touch mode.
6974     *
6975     * Setting this to true will also ensure that this view is focusable.
6976     *
6977     * @param focusableInTouchMode If true, this view can receive the focus while
6978     *   in touch mode.
6979     *
6980     * @see #setFocusable(boolean)
6981     * @attr ref android.R.styleable#View_focusableInTouchMode
6982     */
6983    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
6984        // Focusable in touch mode should always be set before the focusable flag
6985        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
6986        // which, in touch mode, will not successfully request focus on this view
6987        // because the focusable in touch mode flag is not set
6988        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
6989        if (focusableInTouchMode) {
6990            setFlags(FOCUSABLE, FOCUSABLE_MASK);
6991        }
6992    }
6993
6994    /**
6995     * Set whether this view should have sound effects enabled for events such as
6996     * clicking and touching.
6997     *
6998     * <p>You may wish to disable sound effects for a view if you already play sounds,
6999     * for instance, a dial key that plays dtmf tones.
7000     *
7001     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7002     * @see #isSoundEffectsEnabled()
7003     * @see #playSoundEffect(int)
7004     * @attr ref android.R.styleable#View_soundEffectsEnabled
7005     */
7006    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7007        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7008    }
7009
7010    /**
7011     * @return whether this view should have sound effects enabled for events such as
7012     *     clicking and touching.
7013     *
7014     * @see #setSoundEffectsEnabled(boolean)
7015     * @see #playSoundEffect(int)
7016     * @attr ref android.R.styleable#View_soundEffectsEnabled
7017     */
7018    @ViewDebug.ExportedProperty
7019    public boolean isSoundEffectsEnabled() {
7020        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7021    }
7022
7023    /**
7024     * Set whether this view should have haptic feedback for events such as
7025     * long presses.
7026     *
7027     * <p>You may wish to disable haptic feedback if your view already controls
7028     * its own haptic feedback.
7029     *
7030     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7031     * @see #isHapticFeedbackEnabled()
7032     * @see #performHapticFeedback(int)
7033     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7034     */
7035    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7036        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7037    }
7038
7039    /**
7040     * @return whether this view should have haptic feedback enabled for events
7041     * long presses.
7042     *
7043     * @see #setHapticFeedbackEnabled(boolean)
7044     * @see #performHapticFeedback(int)
7045     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7046     */
7047    @ViewDebug.ExportedProperty
7048    public boolean isHapticFeedbackEnabled() {
7049        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7050    }
7051
7052    /**
7053     * Returns the layout direction for this view.
7054     *
7055     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7056     *   {@link #LAYOUT_DIRECTION_RTL},
7057     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7058     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7059     *
7060     * @attr ref android.R.styleable#View_layoutDirection
7061     *
7062     * @hide
7063     */
7064    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7065        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7066        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7067        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7068        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7069    })
7070    @LayoutDir
7071    public int getRawLayoutDirection() {
7072        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7073    }
7074
7075    /**
7076     * Set the layout direction for this view. This will propagate a reset of layout direction
7077     * resolution to the view's children and resolve layout direction for this view.
7078     *
7079     * @param layoutDirection the layout direction to set. Should be one of:
7080     *
7081     * {@link #LAYOUT_DIRECTION_LTR},
7082     * {@link #LAYOUT_DIRECTION_RTL},
7083     * {@link #LAYOUT_DIRECTION_INHERIT},
7084     * {@link #LAYOUT_DIRECTION_LOCALE}.
7085     *
7086     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7087     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7088     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7089     *
7090     * @attr ref android.R.styleable#View_layoutDirection
7091     */
7092    @RemotableViewMethod
7093    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7094        if (getRawLayoutDirection() != layoutDirection) {
7095            // Reset the current layout direction and the resolved one
7096            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7097            resetRtlProperties();
7098            // Set the new layout direction (filtered)
7099            mPrivateFlags2 |=
7100                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7101            // We need to resolve all RTL properties as they all depend on layout direction
7102            resolveRtlPropertiesIfNeeded();
7103            requestLayout();
7104            invalidate(true);
7105        }
7106    }
7107
7108    /**
7109     * Returns the resolved layout direction for this view.
7110     *
7111     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7112     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7113     *
7114     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7115     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7116     *
7117     * @attr ref android.R.styleable#View_layoutDirection
7118     */
7119    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7120        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7121        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7122    })
7123    @ResolvedLayoutDir
7124    public int getLayoutDirection() {
7125        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7126        if (targetSdkVersion < JELLY_BEAN_MR1) {
7127            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7128            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7129        }
7130        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7131                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7132    }
7133
7134    /**
7135     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7136     * layout attribute and/or the inherited value from the parent
7137     *
7138     * @return true if the layout is right-to-left.
7139     *
7140     * @hide
7141     */
7142    @ViewDebug.ExportedProperty(category = "layout")
7143    public boolean isLayoutRtl() {
7144        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7145    }
7146
7147    /**
7148     * Indicates whether the view is currently tracking transient state that the
7149     * app should not need to concern itself with saving and restoring, but that
7150     * the framework should take special note to preserve when possible.
7151     *
7152     * <p>A view with transient state cannot be trivially rebound from an external
7153     * data source, such as an adapter binding item views in a list. This may be
7154     * because the view is performing an animation, tracking user selection
7155     * of content, or similar.</p>
7156     *
7157     * @return true if the view has transient state
7158     */
7159    @ViewDebug.ExportedProperty(category = "layout")
7160    public boolean hasTransientState() {
7161        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7162    }
7163
7164    /**
7165     * Set whether this view is currently tracking transient state that the
7166     * framework should attempt to preserve when possible. This flag is reference counted,
7167     * so every call to setHasTransientState(true) should be paired with a later call
7168     * to setHasTransientState(false).
7169     *
7170     * <p>A view with transient state cannot be trivially rebound from an external
7171     * data source, such as an adapter binding item views in a list. This may be
7172     * because the view is performing an animation, tracking user selection
7173     * of content, or similar.</p>
7174     *
7175     * @param hasTransientState true if this view has transient state
7176     */
7177    public void setHasTransientState(boolean hasTransientState) {
7178        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7179                mTransientStateCount - 1;
7180        if (mTransientStateCount < 0) {
7181            mTransientStateCount = 0;
7182            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7183                    "unmatched pair of setHasTransientState calls");
7184        } else if ((hasTransientState && mTransientStateCount == 1) ||
7185                (!hasTransientState && mTransientStateCount == 0)) {
7186            // update flag if we've just incremented up from 0 or decremented down to 0
7187            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7188                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7189            if (mParent != null) {
7190                try {
7191                    mParent.childHasTransientStateChanged(this, hasTransientState);
7192                } catch (AbstractMethodError e) {
7193                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7194                            " does not fully implement ViewParent", e);
7195                }
7196            }
7197        }
7198    }
7199
7200    /**
7201     * Returns true if this view is currently attached to a window.
7202     */
7203    public boolean isAttachedToWindow() {
7204        return mAttachInfo != null;
7205    }
7206
7207    /**
7208     * Returns true if this view has been through at least one layout since it
7209     * was last attached to or detached from a window.
7210     */
7211    public boolean isLaidOut() {
7212        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7213    }
7214
7215    /**
7216     * If this view doesn't do any drawing on its own, set this flag to
7217     * allow further optimizations. By default, this flag is not set on
7218     * View, but could be set on some View subclasses such as ViewGroup.
7219     *
7220     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7221     * you should clear this flag.
7222     *
7223     * @param willNotDraw whether or not this View draw on its own
7224     */
7225    public void setWillNotDraw(boolean willNotDraw) {
7226        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7227    }
7228
7229    /**
7230     * Returns whether or not this View draws on its own.
7231     *
7232     * @return true if this view has nothing to draw, false otherwise
7233     */
7234    @ViewDebug.ExportedProperty(category = "drawing")
7235    public boolean willNotDraw() {
7236        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7237    }
7238
7239    /**
7240     * When a View's drawing cache is enabled, drawing is redirected to an
7241     * offscreen bitmap. Some views, like an ImageView, must be able to
7242     * bypass this mechanism if they already draw a single bitmap, to avoid
7243     * unnecessary usage of the memory.
7244     *
7245     * @param willNotCacheDrawing true if this view does not cache its
7246     *        drawing, false otherwise
7247     */
7248    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7249        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7250    }
7251
7252    /**
7253     * Returns whether or not this View can cache its drawing or not.
7254     *
7255     * @return true if this view does not cache its drawing, false otherwise
7256     */
7257    @ViewDebug.ExportedProperty(category = "drawing")
7258    public boolean willNotCacheDrawing() {
7259        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7260    }
7261
7262    /**
7263     * Indicates whether this view reacts to click events or not.
7264     *
7265     * @return true if the view is clickable, false otherwise
7266     *
7267     * @see #setClickable(boolean)
7268     * @attr ref android.R.styleable#View_clickable
7269     */
7270    @ViewDebug.ExportedProperty
7271    public boolean isClickable() {
7272        return (mViewFlags & CLICKABLE) == CLICKABLE;
7273    }
7274
7275    /**
7276     * Enables or disables click events for this view. When a view
7277     * is clickable it will change its state to "pressed" on every click.
7278     * Subclasses should set the view clickable to visually react to
7279     * user's clicks.
7280     *
7281     * @param clickable true to make the view clickable, false otherwise
7282     *
7283     * @see #isClickable()
7284     * @attr ref android.R.styleable#View_clickable
7285     */
7286    public void setClickable(boolean clickable) {
7287        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7288    }
7289
7290    /**
7291     * Indicates whether this view reacts to long click events or not.
7292     *
7293     * @return true if the view is long clickable, false otherwise
7294     *
7295     * @see #setLongClickable(boolean)
7296     * @attr ref android.R.styleable#View_longClickable
7297     */
7298    public boolean isLongClickable() {
7299        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7300    }
7301
7302    /**
7303     * Enables or disables long click events for this view. When a view is long
7304     * clickable it reacts to the user holding down the button for a longer
7305     * duration than a tap. This event can either launch the listener or a
7306     * context menu.
7307     *
7308     * @param longClickable true to make the view long clickable, false otherwise
7309     * @see #isLongClickable()
7310     * @attr ref android.R.styleable#View_longClickable
7311     */
7312    public void setLongClickable(boolean longClickable) {
7313        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7314    }
7315
7316    /**
7317     * Sets the pressed state for this view and provides a touch coordinate for
7318     * animation hinting.
7319     *
7320     * @param pressed Pass true to set the View's internal state to "pressed",
7321     *            or false to reverts the View's internal state from a
7322     *            previously set "pressed" state.
7323     * @param x The x coordinate of the touch that caused the press
7324     * @param y The y coordinate of the touch that caused the press
7325     */
7326    private void setPressed(boolean pressed, float x, float y) {
7327        if (pressed) {
7328            drawableHotspotChanged(x, y);
7329        }
7330
7331        setPressed(pressed);
7332    }
7333
7334    /**
7335     * Sets the pressed state for this view.
7336     *
7337     * @see #isClickable()
7338     * @see #setClickable(boolean)
7339     *
7340     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7341     *        the View's internal state from a previously set "pressed" state.
7342     */
7343    public void setPressed(boolean pressed) {
7344        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7345
7346        if (pressed) {
7347            mPrivateFlags |= PFLAG_PRESSED;
7348        } else {
7349            mPrivateFlags &= ~PFLAG_PRESSED;
7350        }
7351
7352        if (needsRefresh) {
7353            refreshDrawableState();
7354        }
7355        dispatchSetPressed(pressed);
7356    }
7357
7358    /**
7359     * Dispatch setPressed to all of this View's children.
7360     *
7361     * @see #setPressed(boolean)
7362     *
7363     * @param pressed The new pressed state
7364     */
7365    protected void dispatchSetPressed(boolean pressed) {
7366    }
7367
7368    /**
7369     * Indicates whether the view is currently in pressed state. Unless
7370     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7371     * the pressed state.
7372     *
7373     * @see #setPressed(boolean)
7374     * @see #isClickable()
7375     * @see #setClickable(boolean)
7376     *
7377     * @return true if the view is currently pressed, false otherwise
7378     */
7379    @ViewDebug.ExportedProperty
7380    public boolean isPressed() {
7381        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7382    }
7383
7384    /**
7385     * Indicates whether this view will save its state (that is,
7386     * whether its {@link #onSaveInstanceState} method will be called).
7387     *
7388     * @return Returns true if the view state saving is enabled, else false.
7389     *
7390     * @see #setSaveEnabled(boolean)
7391     * @attr ref android.R.styleable#View_saveEnabled
7392     */
7393    public boolean isSaveEnabled() {
7394        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7395    }
7396
7397    /**
7398     * Controls whether the saving of this view's state is
7399     * enabled (that is, whether its {@link #onSaveInstanceState} method
7400     * will be called).  Note that even if freezing is enabled, the
7401     * view still must have an id assigned to it (via {@link #setId(int)})
7402     * for its state to be saved.  This flag can only disable the
7403     * saving of this view; any child views may still have their state saved.
7404     *
7405     * @param enabled Set to false to <em>disable</em> state saving, or true
7406     * (the default) to allow it.
7407     *
7408     * @see #isSaveEnabled()
7409     * @see #setId(int)
7410     * @see #onSaveInstanceState()
7411     * @attr ref android.R.styleable#View_saveEnabled
7412     */
7413    public void setSaveEnabled(boolean enabled) {
7414        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7415    }
7416
7417    /**
7418     * Gets whether the framework should discard touches when the view's
7419     * window is obscured by another visible window.
7420     * Refer to the {@link View} security documentation for more details.
7421     *
7422     * @return True if touch filtering is enabled.
7423     *
7424     * @see #setFilterTouchesWhenObscured(boolean)
7425     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7426     */
7427    @ViewDebug.ExportedProperty
7428    public boolean getFilterTouchesWhenObscured() {
7429        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
7430    }
7431
7432    /**
7433     * Sets whether the framework should discard touches when the view's
7434     * window is obscured by another visible window.
7435     * Refer to the {@link View} security documentation for more details.
7436     *
7437     * @param enabled True if touch filtering should be enabled.
7438     *
7439     * @see #getFilterTouchesWhenObscured
7440     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
7441     */
7442    public void setFilterTouchesWhenObscured(boolean enabled) {
7443        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
7444                FILTER_TOUCHES_WHEN_OBSCURED);
7445    }
7446
7447    /**
7448     * Indicates whether the entire hierarchy under this view will save its
7449     * state when a state saving traversal occurs from its parent.  The default
7450     * is true; if false, these views will not be saved unless
7451     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7452     *
7453     * @return Returns true if the view state saving from parent is enabled, else false.
7454     *
7455     * @see #setSaveFromParentEnabled(boolean)
7456     */
7457    public boolean isSaveFromParentEnabled() {
7458        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
7459    }
7460
7461    /**
7462     * Controls whether the entire hierarchy under this view will save its
7463     * state when a state saving traversal occurs from its parent.  The default
7464     * is true; if false, these views will not be saved unless
7465     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
7466     *
7467     * @param enabled Set to false to <em>disable</em> state saving, or true
7468     * (the default) to allow it.
7469     *
7470     * @see #isSaveFromParentEnabled()
7471     * @see #setId(int)
7472     * @see #onSaveInstanceState()
7473     */
7474    public void setSaveFromParentEnabled(boolean enabled) {
7475        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
7476    }
7477
7478
7479    /**
7480     * Returns whether this View is able to take focus.
7481     *
7482     * @return True if this view can take focus, or false otherwise.
7483     * @attr ref android.R.styleable#View_focusable
7484     */
7485    @ViewDebug.ExportedProperty(category = "focus")
7486    public final boolean isFocusable() {
7487        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
7488    }
7489
7490    /**
7491     * When a view is focusable, it may not want to take focus when in touch mode.
7492     * For example, a button would like focus when the user is navigating via a D-pad
7493     * so that the user can click on it, but once the user starts touching the screen,
7494     * the button shouldn't take focus
7495     * @return Whether the view is focusable in touch mode.
7496     * @attr ref android.R.styleable#View_focusableInTouchMode
7497     */
7498    @ViewDebug.ExportedProperty
7499    public final boolean isFocusableInTouchMode() {
7500        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
7501    }
7502
7503    /**
7504     * Find the nearest view in the specified direction that can take focus.
7505     * This does not actually give focus to that view.
7506     *
7507     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7508     *
7509     * @return The nearest focusable in the specified direction, or null if none
7510     *         can be found.
7511     */
7512    public View focusSearch(@FocusRealDirection int direction) {
7513        if (mParent != null) {
7514            return mParent.focusSearch(this, direction);
7515        } else {
7516            return null;
7517        }
7518    }
7519
7520    /**
7521     * This method is the last chance for the focused view and its ancestors to
7522     * respond to an arrow key. This is called when the focused view did not
7523     * consume the key internally, nor could the view system find a new view in
7524     * the requested direction to give focus to.
7525     *
7526     * @param focused The currently focused view.
7527     * @param direction The direction focus wants to move. One of FOCUS_UP,
7528     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
7529     * @return True if the this view consumed this unhandled move.
7530     */
7531    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
7532        return false;
7533    }
7534
7535    /**
7536     * If a user manually specified the next view id for a particular direction,
7537     * use the root to look up the view.
7538     * @param root The root view of the hierarchy containing this view.
7539     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
7540     * or FOCUS_BACKWARD.
7541     * @return The user specified next view, or null if there is none.
7542     */
7543    View findUserSetNextFocus(View root, @FocusDirection int direction) {
7544        switch (direction) {
7545            case FOCUS_LEFT:
7546                if (mNextFocusLeftId == View.NO_ID) return null;
7547                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
7548            case FOCUS_RIGHT:
7549                if (mNextFocusRightId == View.NO_ID) return null;
7550                return findViewInsideOutShouldExist(root, mNextFocusRightId);
7551            case FOCUS_UP:
7552                if (mNextFocusUpId == View.NO_ID) return null;
7553                return findViewInsideOutShouldExist(root, mNextFocusUpId);
7554            case FOCUS_DOWN:
7555                if (mNextFocusDownId == View.NO_ID) return null;
7556                return findViewInsideOutShouldExist(root, mNextFocusDownId);
7557            case FOCUS_FORWARD:
7558                if (mNextFocusForwardId == View.NO_ID) return null;
7559                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
7560            case FOCUS_BACKWARD: {
7561                if (mID == View.NO_ID) return null;
7562                final int id = mID;
7563                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
7564                    @Override
7565                    public boolean apply(View t) {
7566                        return t.mNextFocusForwardId == id;
7567                    }
7568                });
7569            }
7570        }
7571        return null;
7572    }
7573
7574    private View findViewInsideOutShouldExist(View root, int id) {
7575        if (mMatchIdPredicate == null) {
7576            mMatchIdPredicate = new MatchIdPredicate();
7577        }
7578        mMatchIdPredicate.mId = id;
7579        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
7580        if (result == null) {
7581            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
7582        }
7583        return result;
7584    }
7585
7586    /**
7587     * Find and return all focusable views that are descendants of this view,
7588     * possibly including this view if it is focusable itself.
7589     *
7590     * @param direction The direction of the focus
7591     * @return A list of focusable views
7592     */
7593    public ArrayList<View> getFocusables(@FocusDirection int direction) {
7594        ArrayList<View> result = new ArrayList<View>(24);
7595        addFocusables(result, direction);
7596        return result;
7597    }
7598
7599    /**
7600     * Add any focusable views that are descendants of this view (possibly
7601     * including this view if it is focusable itself) to views.  If we are in touch mode,
7602     * only add views that are also focusable in touch mode.
7603     *
7604     * @param views Focusable views found so far
7605     * @param direction The direction of the focus
7606     */
7607    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
7608        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
7609    }
7610
7611    /**
7612     * Adds any focusable views that are descendants of this view (possibly
7613     * including this view if it is focusable itself) to views. This method
7614     * adds all focusable views regardless if we are in touch mode or
7615     * only views focusable in touch mode if we are in touch mode or
7616     * only views that can take accessibility focus if accessibility is enabled
7617     * depending on the focusable mode parameter.
7618     *
7619     * @param views Focusable views found so far or null if all we are interested is
7620     *        the number of focusables.
7621     * @param direction The direction of the focus.
7622     * @param focusableMode The type of focusables to be added.
7623     *
7624     * @see #FOCUSABLES_ALL
7625     * @see #FOCUSABLES_TOUCH_MODE
7626     */
7627    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
7628            @FocusableMode int focusableMode) {
7629        if (views == null) {
7630            return;
7631        }
7632        if (!isFocusable()) {
7633            return;
7634        }
7635        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
7636                && isInTouchMode() && !isFocusableInTouchMode()) {
7637            return;
7638        }
7639        views.add(this);
7640    }
7641
7642    /**
7643     * Finds the Views that contain given text. The containment is case insensitive.
7644     * The search is performed by either the text that the View renders or the content
7645     * description that describes the view for accessibility purposes and the view does
7646     * not render or both. Clients can specify how the search is to be performed via
7647     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
7648     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
7649     *
7650     * @param outViews The output list of matching Views.
7651     * @param searched The text to match against.
7652     *
7653     * @see #FIND_VIEWS_WITH_TEXT
7654     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
7655     * @see #setContentDescription(CharSequence)
7656     */
7657    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
7658            @FindViewFlags int flags) {
7659        if (getAccessibilityNodeProvider() != null) {
7660            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
7661                outViews.add(this);
7662            }
7663        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
7664                && (searched != null && searched.length() > 0)
7665                && (mContentDescription != null && mContentDescription.length() > 0)) {
7666            String searchedLowerCase = searched.toString().toLowerCase();
7667            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
7668            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
7669                outViews.add(this);
7670            }
7671        }
7672    }
7673
7674    /**
7675     * Find and return all touchable views that are descendants of this view,
7676     * possibly including this view if it is touchable itself.
7677     *
7678     * @return A list of touchable views
7679     */
7680    public ArrayList<View> getTouchables() {
7681        ArrayList<View> result = new ArrayList<View>();
7682        addTouchables(result);
7683        return result;
7684    }
7685
7686    /**
7687     * Add any touchable views that are descendants of this view (possibly
7688     * including this view if it is touchable itself) to views.
7689     *
7690     * @param views Touchable views found so far
7691     */
7692    public void addTouchables(ArrayList<View> views) {
7693        final int viewFlags = mViewFlags;
7694
7695        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
7696                && (viewFlags & ENABLED_MASK) == ENABLED) {
7697            views.add(this);
7698        }
7699    }
7700
7701    /**
7702     * Returns whether this View is accessibility focused.
7703     *
7704     * @return True if this View is accessibility focused.
7705     */
7706    public boolean isAccessibilityFocused() {
7707        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
7708    }
7709
7710    /**
7711     * Call this to try to give accessibility focus to this view.
7712     *
7713     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
7714     * returns false or the view is no visible or the view already has accessibility
7715     * focus.
7716     *
7717     * See also {@link #focusSearch(int)}, which is what you call to say that you
7718     * have focus, and you want your parent to look for the next one.
7719     *
7720     * @return Whether this view actually took accessibility focus.
7721     *
7722     * @hide
7723     */
7724    public boolean requestAccessibilityFocus() {
7725        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
7726        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
7727            return false;
7728        }
7729        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7730            return false;
7731        }
7732        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
7733            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
7734            ViewRootImpl viewRootImpl = getViewRootImpl();
7735            if (viewRootImpl != null) {
7736                viewRootImpl.setAccessibilityFocus(this, null);
7737            }
7738            invalidate();
7739            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
7740            return true;
7741        }
7742        return false;
7743    }
7744
7745    /**
7746     * Call this to try to clear accessibility focus of this view.
7747     *
7748     * See also {@link #focusSearch(int)}, which is what you call to say that you
7749     * have focus, and you want your parent to look for the next one.
7750     *
7751     * @hide
7752     */
7753    public void clearAccessibilityFocus() {
7754        clearAccessibilityFocusNoCallbacks();
7755        // Clear the global reference of accessibility focus if this
7756        // view or any of its descendants had accessibility focus.
7757        ViewRootImpl viewRootImpl = getViewRootImpl();
7758        if (viewRootImpl != null) {
7759            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
7760            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
7761                viewRootImpl.setAccessibilityFocus(null, null);
7762            }
7763        }
7764    }
7765
7766    private void sendAccessibilityHoverEvent(int eventType) {
7767        // Since we are not delivering to a client accessibility events from not
7768        // important views (unless the clinet request that) we need to fire the
7769        // event from the deepest view exposed to the client. As a consequence if
7770        // the user crosses a not exposed view the client will see enter and exit
7771        // of the exposed predecessor followed by and enter and exit of that same
7772        // predecessor when entering and exiting the not exposed descendant. This
7773        // is fine since the client has a clear idea which view is hovered at the
7774        // price of a couple more events being sent. This is a simple and
7775        // working solution.
7776        View source = this;
7777        while (true) {
7778            if (source.includeForAccessibility()) {
7779                source.sendAccessibilityEvent(eventType);
7780                return;
7781            }
7782            ViewParent parent = source.getParent();
7783            if (parent instanceof View) {
7784                source = (View) parent;
7785            } else {
7786                return;
7787            }
7788        }
7789    }
7790
7791    /**
7792     * Clears accessibility focus without calling any callback methods
7793     * normally invoked in {@link #clearAccessibilityFocus()}. This method
7794     * is used for clearing accessibility focus when giving this focus to
7795     * another view.
7796     */
7797    void clearAccessibilityFocusNoCallbacks() {
7798        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
7799            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
7800            invalidate();
7801            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
7802        }
7803    }
7804
7805    /**
7806     * Call this to try to give focus to a specific view or to one of its
7807     * descendants.
7808     *
7809     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7810     * false), or if it is focusable and it is not focusable in touch mode
7811     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7812     *
7813     * See also {@link #focusSearch(int)}, which is what you call to say that you
7814     * have focus, and you want your parent to look for the next one.
7815     *
7816     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
7817     * {@link #FOCUS_DOWN} and <code>null</code>.
7818     *
7819     * @return Whether this view or one of its descendants actually took focus.
7820     */
7821    public final boolean requestFocus() {
7822        return requestFocus(View.FOCUS_DOWN);
7823    }
7824
7825    /**
7826     * Call this to try to give focus to a specific view or to one of its
7827     * descendants and give it a hint about what direction focus is heading.
7828     *
7829     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7830     * false), or if it is focusable and it is not focusable in touch mode
7831     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7832     *
7833     * See also {@link #focusSearch(int)}, which is what you call to say that you
7834     * have focus, and you want your parent to look for the next one.
7835     *
7836     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
7837     * <code>null</code> set for the previously focused rectangle.
7838     *
7839     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7840     * @return Whether this view or one of its descendants actually took focus.
7841     */
7842    public final boolean requestFocus(int direction) {
7843        return requestFocus(direction, null);
7844    }
7845
7846    /**
7847     * Call this to try to give focus to a specific view or to one of its descendants
7848     * and give it hints about the direction and a specific rectangle that the focus
7849     * is coming from.  The rectangle can help give larger views a finer grained hint
7850     * about where focus is coming from, and therefore, where to show selection, or
7851     * forward focus change internally.
7852     *
7853     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
7854     * false), or if it is focusable and it is not focusable in touch mode
7855     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
7856     *
7857     * A View will not take focus if it is not visible.
7858     *
7859     * A View will not take focus if one of its parents has
7860     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
7861     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
7862     *
7863     * See also {@link #focusSearch(int)}, which is what you call to say that you
7864     * have focus, and you want your parent to look for the next one.
7865     *
7866     * You may wish to override this method if your custom {@link View} has an internal
7867     * {@link View} that it wishes to forward the request to.
7868     *
7869     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
7870     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
7871     *        to give a finer grained hint about where focus is coming from.  May be null
7872     *        if there is no hint.
7873     * @return Whether this view or one of its descendants actually took focus.
7874     */
7875    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
7876        return requestFocusNoSearch(direction, previouslyFocusedRect);
7877    }
7878
7879    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
7880        // need to be focusable
7881        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
7882                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7883            return false;
7884        }
7885
7886        // need to be focusable in touch mode if in touch mode
7887        if (isInTouchMode() &&
7888            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
7889               return false;
7890        }
7891
7892        // need to not have any parents blocking us
7893        if (hasAncestorThatBlocksDescendantFocus()) {
7894            return false;
7895        }
7896
7897        handleFocusGainInternal(direction, previouslyFocusedRect);
7898        return true;
7899    }
7900
7901    /**
7902     * Call this to try to give focus to a specific view or to one of its descendants. This is a
7903     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
7904     * touch mode to request focus when they are touched.
7905     *
7906     * @return Whether this view or one of its descendants actually took focus.
7907     *
7908     * @see #isInTouchMode()
7909     *
7910     */
7911    public final boolean requestFocusFromTouch() {
7912        // Leave touch mode if we need to
7913        if (isInTouchMode()) {
7914            ViewRootImpl viewRoot = getViewRootImpl();
7915            if (viewRoot != null) {
7916                viewRoot.ensureTouchMode(false);
7917            }
7918        }
7919        return requestFocus(View.FOCUS_DOWN);
7920    }
7921
7922    /**
7923     * @return Whether any ancestor of this view blocks descendant focus.
7924     */
7925    private boolean hasAncestorThatBlocksDescendantFocus() {
7926        final boolean focusableInTouchMode = isFocusableInTouchMode();
7927        ViewParent ancestor = mParent;
7928        while (ancestor instanceof ViewGroup) {
7929            final ViewGroup vgAncestor = (ViewGroup) ancestor;
7930            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
7931                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
7932                return true;
7933            } else {
7934                ancestor = vgAncestor.getParent();
7935            }
7936        }
7937        return false;
7938    }
7939
7940    /**
7941     * Gets the mode for determining whether this View is important for accessibility
7942     * which is if it fires accessibility events and if it is reported to
7943     * accessibility services that query the screen.
7944     *
7945     * @return The mode for determining whether a View is important for accessibility.
7946     *
7947     * @attr ref android.R.styleable#View_importantForAccessibility
7948     *
7949     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
7950     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
7951     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
7952     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
7953     */
7954    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
7955            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
7956            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
7957            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
7958            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
7959                    to = "noHideDescendants")
7960        })
7961    public int getImportantForAccessibility() {
7962        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
7963                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
7964    }
7965
7966    /**
7967     * Sets the live region mode for this view. This indicates to accessibility
7968     * services whether they should automatically notify the user about changes
7969     * to the view's content description or text, or to the content descriptions
7970     * or text of the view's children (where applicable).
7971     * <p>
7972     * For example, in a login screen with a TextView that displays an "incorrect
7973     * password" notification, that view should be marked as a live region with
7974     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7975     * <p>
7976     * To disable change notifications for this view, use
7977     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
7978     * mode for most views.
7979     * <p>
7980     * To indicate that the user should be notified of changes, use
7981     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
7982     * <p>
7983     * If the view's changes should interrupt ongoing speech and notify the user
7984     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
7985     *
7986     * @param mode The live region mode for this view, one of:
7987     *        <ul>
7988     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
7989     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
7990     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
7991     *        </ul>
7992     * @attr ref android.R.styleable#View_accessibilityLiveRegion
7993     */
7994    public void setAccessibilityLiveRegion(int mode) {
7995        if (mode != getAccessibilityLiveRegion()) {
7996            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7997            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
7998                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
7999            notifyViewAccessibilityStateChangedIfNeeded(
8000                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8001        }
8002    }
8003
8004    /**
8005     * Gets the live region mode for this View.
8006     *
8007     * @return The live region mode for the view.
8008     *
8009     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8010     *
8011     * @see #setAccessibilityLiveRegion(int)
8012     */
8013    public int getAccessibilityLiveRegion() {
8014        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8015                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8016    }
8017
8018    /**
8019     * Sets how to determine whether this view is important for accessibility
8020     * which is if it fires accessibility events and if it is reported to
8021     * accessibility services that query the screen.
8022     *
8023     * @param mode How to determine whether this view is important for accessibility.
8024     *
8025     * @attr ref android.R.styleable#View_importantForAccessibility
8026     *
8027     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8028     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8029     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8030     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8031     */
8032    public void setImportantForAccessibility(int mode) {
8033        final int oldMode = getImportantForAccessibility();
8034        if (mode != oldMode) {
8035            // If we're moving between AUTO and another state, we might not need
8036            // to send a subtree changed notification. We'll store the computed
8037            // importance, since we'll need to check it later to make sure.
8038            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8039                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8040            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8041            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8042            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8043                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8044            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8045                notifySubtreeAccessibilityStateChangedIfNeeded();
8046            } else {
8047                notifyViewAccessibilityStateChangedIfNeeded(
8048                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8049            }
8050        }
8051    }
8052
8053    /**
8054     * Computes whether this view should be exposed for accessibility. In
8055     * general, views that are interactive or provide information are exposed
8056     * while views that serve only as containers are hidden.
8057     * <p>
8058     * If an ancestor of this view has importance
8059     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8060     * returns <code>false</code>.
8061     * <p>
8062     * Otherwise, the value is computed according to the view's
8063     * {@link #getImportantForAccessibility()} value:
8064     * <ol>
8065     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8066     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8067     * </code>
8068     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8069     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8070     * view satisfies any of the following:
8071     * <ul>
8072     * <li>Is actionable, e.g. {@link #isClickable()},
8073     * {@link #isLongClickable()}, or {@link #isFocusable()}
8074     * <li>Has an {@link AccessibilityDelegate}
8075     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8076     * {@link OnKeyListener}, etc.
8077     * <li>Is an accessibility live region, e.g.
8078     * {@link #getAccessibilityLiveRegion()} is not
8079     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8080     * </ul>
8081     * </ol>
8082     *
8083     * @return Whether the view is exposed for accessibility.
8084     * @see #setImportantForAccessibility(int)
8085     * @see #getImportantForAccessibility()
8086     */
8087    public boolean isImportantForAccessibility() {
8088        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8089                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8090        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8091                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8092            return false;
8093        }
8094
8095        // Check parent mode to ensure we're not hidden.
8096        ViewParent parent = mParent;
8097        while (parent instanceof View) {
8098            if (((View) parent).getImportantForAccessibility()
8099                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8100                return false;
8101            }
8102            parent = parent.getParent();
8103        }
8104
8105        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8106                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8107                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8108    }
8109
8110    /**
8111     * Gets the parent for accessibility purposes. Note that the parent for
8112     * accessibility is not necessary the immediate parent. It is the first
8113     * predecessor that is important for accessibility.
8114     *
8115     * @return The parent for accessibility purposes.
8116     */
8117    public ViewParent getParentForAccessibility() {
8118        if (mParent instanceof View) {
8119            View parentView = (View) mParent;
8120            if (parentView.includeForAccessibility()) {
8121                return mParent;
8122            } else {
8123                return mParent.getParentForAccessibility();
8124            }
8125        }
8126        return null;
8127    }
8128
8129    /**
8130     * Adds the children of a given View for accessibility. Since some Views are
8131     * not important for accessibility the children for accessibility are not
8132     * necessarily direct children of the view, rather they are the first level of
8133     * descendants important for accessibility.
8134     *
8135     * @param children The list of children for accessibility.
8136     */
8137    public void addChildrenForAccessibility(ArrayList<View> children) {
8138
8139    }
8140
8141    /**
8142     * Whether to regard this view for accessibility. A view is regarded for
8143     * accessibility if it is important for accessibility or the querying
8144     * accessibility service has explicitly requested that view not
8145     * important for accessibility are regarded.
8146     *
8147     * @return Whether to regard the view for accessibility.
8148     *
8149     * @hide
8150     */
8151    public boolean includeForAccessibility() {
8152        if (mAttachInfo != null) {
8153            return (mAttachInfo.mAccessibilityFetchFlags
8154                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8155                    || isImportantForAccessibility();
8156        }
8157        return false;
8158    }
8159
8160    /**
8161     * Returns whether the View is considered actionable from
8162     * accessibility perspective. Such view are important for
8163     * accessibility.
8164     *
8165     * @return True if the view is actionable for accessibility.
8166     *
8167     * @hide
8168     */
8169    public boolean isActionableForAccessibility() {
8170        return (isClickable() || isLongClickable() || isFocusable());
8171    }
8172
8173    /**
8174     * Returns whether the View has registered callbacks which makes it
8175     * important for accessibility.
8176     *
8177     * @return True if the view is actionable for accessibility.
8178     */
8179    private boolean hasListenersForAccessibility() {
8180        ListenerInfo info = getListenerInfo();
8181        return mTouchDelegate != null || info.mOnKeyListener != null
8182                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8183                || info.mOnHoverListener != null || info.mOnDragListener != null;
8184    }
8185
8186    /**
8187     * Notifies that the accessibility state of this view changed. The change
8188     * is local to this view and does not represent structural changes such
8189     * as children and parent. For example, the view became focusable. The
8190     * notification is at at most once every
8191     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8192     * to avoid unnecessary load to the system. Also once a view has a pending
8193     * notification this method is a NOP until the notification has been sent.
8194     *
8195     * @hide
8196     */
8197    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8198        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8199            return;
8200        }
8201        if (mSendViewStateChangedAccessibilityEvent == null) {
8202            mSendViewStateChangedAccessibilityEvent =
8203                    new SendViewStateChangedAccessibilityEvent();
8204        }
8205        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8206    }
8207
8208    /**
8209     * Notifies that the accessibility state of this view changed. The change
8210     * is *not* local to this view and does represent structural changes such
8211     * as children and parent. For example, the view size changed. The
8212     * notification is at at most once every
8213     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8214     * to avoid unnecessary load to the system. Also once a view has a pending
8215     * notification this method is a NOP until the notification has been sent.
8216     *
8217     * @hide
8218     */
8219    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8220        if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
8221            return;
8222        }
8223        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8224            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8225            if (mParent != null) {
8226                try {
8227                    mParent.notifySubtreeAccessibilityStateChanged(
8228                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8229                } catch (AbstractMethodError e) {
8230                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8231                            " does not fully implement ViewParent", e);
8232                }
8233            }
8234        }
8235    }
8236
8237    /**
8238     * Reset the flag indicating the accessibility state of the subtree rooted
8239     * at this view changed.
8240     */
8241    void resetSubtreeAccessibilityStateChanged() {
8242        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8243    }
8244
8245    /**
8246     * Report an accessibility action to this view's parents for delegated processing.
8247     *
8248     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8249     * call this method to delegate an accessibility action to a supporting parent. If the parent
8250     * returns true from its
8251     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8252     * method this method will return true to signify that the action was consumed.</p>
8253     *
8254     * <p>This method is useful for implementing nested scrolling child views. If
8255     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8256     * a custom view implementation may invoke this method to allow a parent to consume the
8257     * scroll first. If this method returns true the custom view should skip its own scrolling
8258     * behavior.</p>
8259     *
8260     * @param action Accessibility action to delegate
8261     * @param arguments Optional action arguments
8262     * @return true if the action was consumed by a parent
8263     */
8264    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8265        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8266            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8267                return true;
8268            }
8269        }
8270        return false;
8271    }
8272
8273    /**
8274     * Performs the specified accessibility action on the view. For
8275     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8276     * <p>
8277     * If an {@link AccessibilityDelegate} has been specified via calling
8278     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8279     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8280     * is responsible for handling this call.
8281     * </p>
8282     *
8283     * <p>The default implementation will delegate
8284     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8285     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8286     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8287     *
8288     * @param action The action to perform.
8289     * @param arguments Optional action arguments.
8290     * @return Whether the action was performed.
8291     */
8292    public boolean performAccessibilityAction(int action, Bundle arguments) {
8293      if (mAccessibilityDelegate != null) {
8294          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8295      } else {
8296          return performAccessibilityActionInternal(action, arguments);
8297      }
8298    }
8299
8300   /**
8301    * @see #performAccessibilityAction(int, Bundle)
8302    *
8303    * Note: Called from the default {@link AccessibilityDelegate}.
8304    *
8305    * @hide
8306    */
8307    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8308        if (isNestedScrollingEnabled()
8309                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8310                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
8311            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8312                return true;
8313            }
8314        }
8315
8316        switch (action) {
8317            case AccessibilityNodeInfo.ACTION_CLICK: {
8318                if (isClickable()) {
8319                    performClick();
8320                    return true;
8321                }
8322            } break;
8323            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8324                if (isLongClickable()) {
8325                    performLongClick();
8326                    return true;
8327                }
8328            } break;
8329            case AccessibilityNodeInfo.ACTION_FOCUS: {
8330                if (!hasFocus()) {
8331                    // Get out of touch mode since accessibility
8332                    // wants to move focus around.
8333                    getViewRootImpl().ensureTouchMode(false);
8334                    return requestFocus();
8335                }
8336            } break;
8337            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8338                if (hasFocus()) {
8339                    clearFocus();
8340                    return !isFocused();
8341                }
8342            } break;
8343            case AccessibilityNodeInfo.ACTION_SELECT: {
8344                if (!isSelected()) {
8345                    setSelected(true);
8346                    return isSelected();
8347                }
8348            } break;
8349            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8350                if (isSelected()) {
8351                    setSelected(false);
8352                    return !isSelected();
8353                }
8354            } break;
8355            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8356                if (!isAccessibilityFocused()) {
8357                    return requestAccessibilityFocus();
8358                }
8359            } break;
8360            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8361                if (isAccessibilityFocused()) {
8362                    clearAccessibilityFocus();
8363                    return true;
8364                }
8365            } break;
8366            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8367                if (arguments != null) {
8368                    final int granularity = arguments.getInt(
8369                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8370                    final boolean extendSelection = arguments.getBoolean(
8371                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8372                    return traverseAtGranularity(granularity, true, extendSelection);
8373                }
8374            } break;
8375            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8376                if (arguments != null) {
8377                    final int granularity = arguments.getInt(
8378                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8379                    final boolean extendSelection = arguments.getBoolean(
8380                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8381                    return traverseAtGranularity(granularity, false, extendSelection);
8382                }
8383            } break;
8384            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8385                CharSequence text = getIterableTextForAccessibility();
8386                if (text == null) {
8387                    return false;
8388                }
8389                final int start = (arguments != null) ? arguments.getInt(
8390                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8391                final int end = (arguments != null) ? arguments.getInt(
8392                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8393                // Only cursor position can be specified (selection length == 0)
8394                if ((getAccessibilitySelectionStart() != start
8395                        || getAccessibilitySelectionEnd() != end)
8396                        && (start == end)) {
8397                    setAccessibilitySelection(start, end);
8398                    notifyViewAccessibilityStateChangedIfNeeded(
8399                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8400                    return true;
8401                }
8402            } break;
8403            case R.id.accessibility_action_show_on_screen: {
8404                if (mAttachInfo != null) {
8405                    final Rect r = mAttachInfo.mTmpInvalRect;
8406                    getDrawingRect(r);
8407                    return requestRectangleOnScreen(r, true);
8408                }
8409            } break;
8410        }
8411        return false;
8412    }
8413
8414    private boolean traverseAtGranularity(int granularity, boolean forward,
8415            boolean extendSelection) {
8416        CharSequence text = getIterableTextForAccessibility();
8417        if (text == null || text.length() == 0) {
8418            return false;
8419        }
8420        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
8421        if (iterator == null) {
8422            return false;
8423        }
8424        int current = getAccessibilitySelectionEnd();
8425        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8426            current = forward ? 0 : text.length();
8427        }
8428        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
8429        if (range == null) {
8430            return false;
8431        }
8432        final int segmentStart = range[0];
8433        final int segmentEnd = range[1];
8434        int selectionStart;
8435        int selectionEnd;
8436        if (extendSelection && isAccessibilitySelectionExtendable()) {
8437            selectionStart = getAccessibilitySelectionStart();
8438            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
8439                selectionStart = forward ? segmentStart : segmentEnd;
8440            }
8441            selectionEnd = forward ? segmentEnd : segmentStart;
8442        } else {
8443            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
8444        }
8445        setAccessibilitySelection(selectionStart, selectionEnd);
8446        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
8447                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
8448        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
8449        return true;
8450    }
8451
8452    /**
8453     * Gets the text reported for accessibility purposes.
8454     *
8455     * @return The accessibility text.
8456     *
8457     * @hide
8458     */
8459    public CharSequence getIterableTextForAccessibility() {
8460        return getContentDescription();
8461    }
8462
8463    /**
8464     * Gets whether accessibility selection can be extended.
8465     *
8466     * @return If selection is extensible.
8467     *
8468     * @hide
8469     */
8470    public boolean isAccessibilitySelectionExtendable() {
8471        return false;
8472    }
8473
8474    /**
8475     * @hide
8476     */
8477    public int getAccessibilitySelectionStart() {
8478        return mAccessibilityCursorPosition;
8479    }
8480
8481    /**
8482     * @hide
8483     */
8484    public int getAccessibilitySelectionEnd() {
8485        return getAccessibilitySelectionStart();
8486    }
8487
8488    /**
8489     * @hide
8490     */
8491    public void setAccessibilitySelection(int start, int end) {
8492        if (start ==  end && end == mAccessibilityCursorPosition) {
8493            return;
8494        }
8495        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
8496            mAccessibilityCursorPosition = start;
8497        } else {
8498            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
8499        }
8500        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
8501    }
8502
8503    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
8504            int fromIndex, int toIndex) {
8505        if (mParent == null) {
8506            return;
8507        }
8508        AccessibilityEvent event = AccessibilityEvent.obtain(
8509                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
8510        onInitializeAccessibilityEvent(event);
8511        onPopulateAccessibilityEvent(event);
8512        event.setFromIndex(fromIndex);
8513        event.setToIndex(toIndex);
8514        event.setAction(action);
8515        event.setMovementGranularity(granularity);
8516        mParent.requestSendAccessibilityEvent(this, event);
8517    }
8518
8519    /**
8520     * @hide
8521     */
8522    public TextSegmentIterator getIteratorForGranularity(int granularity) {
8523        switch (granularity) {
8524            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
8525                CharSequence text = getIterableTextForAccessibility();
8526                if (text != null && text.length() > 0) {
8527                    CharacterTextSegmentIterator iterator =
8528                        CharacterTextSegmentIterator.getInstance(
8529                                mContext.getResources().getConfiguration().locale);
8530                    iterator.initialize(text.toString());
8531                    return iterator;
8532                }
8533            } break;
8534            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
8535                CharSequence text = getIterableTextForAccessibility();
8536                if (text != null && text.length() > 0) {
8537                    WordTextSegmentIterator iterator =
8538                        WordTextSegmentIterator.getInstance(
8539                                mContext.getResources().getConfiguration().locale);
8540                    iterator.initialize(text.toString());
8541                    return iterator;
8542                }
8543            } break;
8544            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
8545                CharSequence text = getIterableTextForAccessibility();
8546                if (text != null && text.length() > 0) {
8547                    ParagraphTextSegmentIterator iterator =
8548                        ParagraphTextSegmentIterator.getInstance();
8549                    iterator.initialize(text.toString());
8550                    return iterator;
8551                }
8552            } break;
8553        }
8554        return null;
8555    }
8556
8557    /**
8558     * @hide
8559     */
8560    public void dispatchStartTemporaryDetach() {
8561        onStartTemporaryDetach();
8562    }
8563
8564    /**
8565     * This is called when a container is going to temporarily detach a child, with
8566     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
8567     * It will either be followed by {@link #onFinishTemporaryDetach()} or
8568     * {@link #onDetachedFromWindow()} when the container is done.
8569     */
8570    public void onStartTemporaryDetach() {
8571        removeUnsetPressCallback();
8572        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
8573    }
8574
8575    /**
8576     * @hide
8577     */
8578    public void dispatchFinishTemporaryDetach() {
8579        onFinishTemporaryDetach();
8580    }
8581
8582    /**
8583     * Called after {@link #onStartTemporaryDetach} when the container is done
8584     * changing the view.
8585     */
8586    public void onFinishTemporaryDetach() {
8587    }
8588
8589    /**
8590     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
8591     * for this view's window.  Returns null if the view is not currently attached
8592     * to the window.  Normally you will not need to use this directly, but
8593     * just use the standard high-level event callbacks like
8594     * {@link #onKeyDown(int, KeyEvent)}.
8595     */
8596    public KeyEvent.DispatcherState getKeyDispatcherState() {
8597        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
8598    }
8599
8600    /**
8601     * Dispatch a key event before it is processed by any input method
8602     * associated with the view hierarchy.  This can be used to intercept
8603     * key events in special situations before the IME consumes them; a
8604     * typical example would be handling the BACK key to update the application's
8605     * UI instead of allowing the IME to see it and close itself.
8606     *
8607     * @param event The key event to be dispatched.
8608     * @return True if the event was handled, false otherwise.
8609     */
8610    public boolean dispatchKeyEventPreIme(KeyEvent event) {
8611        return onKeyPreIme(event.getKeyCode(), event);
8612    }
8613
8614    /**
8615     * Dispatch a key event to the next view on the focus path. This path runs
8616     * from the top of the view tree down to the currently focused view. If this
8617     * view has focus, it will dispatch to itself. Otherwise it will dispatch
8618     * the next node down the focus path. This method also fires any key
8619     * listeners.
8620     *
8621     * @param event The key event to be dispatched.
8622     * @return True if the event was handled, false otherwise.
8623     */
8624    public boolean dispatchKeyEvent(KeyEvent event) {
8625        if (mInputEventConsistencyVerifier != null) {
8626            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
8627        }
8628
8629        // Give any attached key listener a first crack at the event.
8630        //noinspection SimplifiableIfStatement
8631        ListenerInfo li = mListenerInfo;
8632        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
8633                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
8634            return true;
8635        }
8636
8637        if (event.dispatch(this, mAttachInfo != null
8638                ? mAttachInfo.mKeyDispatchState : null, this)) {
8639            return true;
8640        }
8641
8642        if (mInputEventConsistencyVerifier != null) {
8643            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8644        }
8645        return false;
8646    }
8647
8648    /**
8649     * Dispatches a key shortcut event.
8650     *
8651     * @param event The key event to be dispatched.
8652     * @return True if the event was handled by the view, false otherwise.
8653     */
8654    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
8655        return onKeyShortcut(event.getKeyCode(), event);
8656    }
8657
8658    /**
8659     * Pass the touch screen motion event down to the target view, or this
8660     * view if it is the target.
8661     *
8662     * @param event The motion event to be dispatched.
8663     * @return True if the event was handled by the view, false otherwise.
8664     */
8665    public boolean dispatchTouchEvent(MotionEvent event) {
8666        // If the event should be handled by accessibility focus first.
8667        if (event.isTargetAccessibilityFocus()) {
8668            // We don't have focus or no virtual descendant has it, do not handle the event.
8669            if (!isAccessibilityFocusedViewOrHost()) {
8670                return false;
8671            }
8672            // We have focus and got the event, then use normal event dispatch.
8673            event.setTargetAccessibilityFocus(false);
8674        }
8675
8676        boolean result = false;
8677
8678        if (mInputEventConsistencyVerifier != null) {
8679            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
8680        }
8681
8682        final int actionMasked = event.getActionMasked();
8683        if (actionMasked == MotionEvent.ACTION_DOWN) {
8684            // Defensive cleanup for new gesture
8685            stopNestedScroll();
8686        }
8687
8688        if (onFilterTouchEventForSecurity(event)) {
8689            //noinspection SimplifiableIfStatement
8690            ListenerInfo li = mListenerInfo;
8691            if (li != null && li.mOnTouchListener != null
8692                    && (mViewFlags & ENABLED_MASK) == ENABLED
8693                    && li.mOnTouchListener.onTouch(this, event)) {
8694                result = true;
8695            }
8696
8697            if (!result && onTouchEvent(event)) {
8698                result = true;
8699            }
8700        }
8701
8702        if (!result && mInputEventConsistencyVerifier != null) {
8703            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8704        }
8705
8706        // Clean up after nested scrolls if this is the end of a gesture;
8707        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
8708        // of the gesture.
8709        if (actionMasked == MotionEvent.ACTION_UP ||
8710                actionMasked == MotionEvent.ACTION_CANCEL ||
8711                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
8712            stopNestedScroll();
8713        }
8714
8715        return result;
8716    }
8717
8718    boolean isAccessibilityFocusedViewOrHost() {
8719        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
8720                .getAccessibilityFocusedHost() == this);
8721    }
8722
8723    /**
8724     * Filter the touch event to apply security policies.
8725     *
8726     * @param event The motion event to be filtered.
8727     * @return True if the event should be dispatched, false if the event should be dropped.
8728     *
8729     * @see #getFilterTouchesWhenObscured
8730     */
8731    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
8732        //noinspection RedundantIfStatement
8733        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
8734                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
8735            // Window is obscured, drop this touch.
8736            return false;
8737        }
8738        return true;
8739    }
8740
8741    /**
8742     * Pass a trackball motion event down to the focused view.
8743     *
8744     * @param event The motion event to be dispatched.
8745     * @return True if the event was handled by the view, false otherwise.
8746     */
8747    public boolean dispatchTrackballEvent(MotionEvent event) {
8748        if (mInputEventConsistencyVerifier != null) {
8749            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
8750        }
8751
8752        return onTrackballEvent(event);
8753    }
8754
8755    /**
8756     * Dispatch a generic motion event.
8757     * <p>
8758     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
8759     * are delivered to the view under the pointer.  All other generic motion events are
8760     * delivered to the focused view.  Hover events are handled specially and are delivered
8761     * to {@link #onHoverEvent(MotionEvent)}.
8762     * </p>
8763     *
8764     * @param event The motion event to be dispatched.
8765     * @return True if the event was handled by the view, false otherwise.
8766     */
8767    public boolean dispatchGenericMotionEvent(MotionEvent event) {
8768        if (mInputEventConsistencyVerifier != null) {
8769            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
8770        }
8771
8772        final int source = event.getSource();
8773        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
8774            final int action = event.getAction();
8775            if (action == MotionEvent.ACTION_HOVER_ENTER
8776                    || action == MotionEvent.ACTION_HOVER_MOVE
8777                    || action == MotionEvent.ACTION_HOVER_EXIT) {
8778                if (dispatchHoverEvent(event)) {
8779                    return true;
8780                }
8781            } else if (dispatchGenericPointerEvent(event)) {
8782                return true;
8783            }
8784        } else if (dispatchGenericFocusedEvent(event)) {
8785            return true;
8786        }
8787
8788        if (dispatchGenericMotionEventInternal(event)) {
8789            return true;
8790        }
8791
8792        if (mInputEventConsistencyVerifier != null) {
8793            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8794        }
8795        return false;
8796    }
8797
8798    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
8799        //noinspection SimplifiableIfStatement
8800        ListenerInfo li = mListenerInfo;
8801        if (li != null && li.mOnGenericMotionListener != null
8802                && (mViewFlags & ENABLED_MASK) == ENABLED
8803                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
8804            return true;
8805        }
8806
8807        if (onGenericMotionEvent(event)) {
8808            return true;
8809        }
8810
8811        if (mInputEventConsistencyVerifier != null) {
8812            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
8813        }
8814        return false;
8815    }
8816
8817    /**
8818     * Dispatch a hover event.
8819     * <p>
8820     * Do not call this method directly.
8821     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8822     * </p>
8823     *
8824     * @param event The motion event to be dispatched.
8825     * @return True if the event was handled by the view, false otherwise.
8826     */
8827    protected boolean dispatchHoverEvent(MotionEvent event) {
8828        ListenerInfo li = mListenerInfo;
8829        //noinspection SimplifiableIfStatement
8830        if (li != null && li.mOnHoverListener != null
8831                && (mViewFlags & ENABLED_MASK) == ENABLED
8832                && li.mOnHoverListener.onHover(this, event)) {
8833            return true;
8834        }
8835
8836        return onHoverEvent(event);
8837    }
8838
8839    /**
8840     * Returns true if the view has a child to which it has recently sent
8841     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
8842     * it does not have a hovered child, then it must be the innermost hovered view.
8843     * @hide
8844     */
8845    protected boolean hasHoveredChild() {
8846        return false;
8847    }
8848
8849    /**
8850     * Dispatch a generic motion event to the view under the first pointer.
8851     * <p>
8852     * Do not call this method directly.
8853     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8854     * </p>
8855     *
8856     * @param event The motion event to be dispatched.
8857     * @return True if the event was handled by the view, false otherwise.
8858     */
8859    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
8860        return false;
8861    }
8862
8863    /**
8864     * Dispatch a generic motion event to the currently focused view.
8865     * <p>
8866     * Do not call this method directly.
8867     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
8868     * </p>
8869     *
8870     * @param event The motion event to be dispatched.
8871     * @return True if the event was handled by the view, false otherwise.
8872     */
8873    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
8874        return false;
8875    }
8876
8877    /**
8878     * Dispatch a pointer event.
8879     * <p>
8880     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
8881     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
8882     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
8883     * and should not be expected to handle other pointing device features.
8884     * </p>
8885     *
8886     * @param event The motion event to be dispatched.
8887     * @return True if the event was handled by the view, false otherwise.
8888     * @hide
8889     */
8890    public final boolean dispatchPointerEvent(MotionEvent event) {
8891        if (event.isTouchEvent()) {
8892            return dispatchTouchEvent(event);
8893        } else {
8894            return dispatchGenericMotionEvent(event);
8895        }
8896    }
8897
8898    /**
8899     * Called when the window containing this view gains or loses window focus.
8900     * ViewGroups should override to route to their children.
8901     *
8902     * @param hasFocus True if the window containing this view now has focus,
8903     *        false otherwise.
8904     */
8905    public void dispatchWindowFocusChanged(boolean hasFocus) {
8906        onWindowFocusChanged(hasFocus);
8907    }
8908
8909    /**
8910     * Called when the window containing this view gains or loses focus.  Note
8911     * that this is separate from view focus: to receive key events, both
8912     * your view and its window must have focus.  If a window is displayed
8913     * on top of yours that takes input focus, then your own window will lose
8914     * focus but the view focus will remain unchanged.
8915     *
8916     * @param hasWindowFocus True if the window containing this view now has
8917     *        focus, false otherwise.
8918     */
8919    public void onWindowFocusChanged(boolean hasWindowFocus) {
8920        InputMethodManager imm = InputMethodManager.peekInstance();
8921        if (!hasWindowFocus) {
8922            if (isPressed()) {
8923                setPressed(false);
8924            }
8925            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8926                imm.focusOut(this);
8927            }
8928            removeLongPressCallback();
8929            removeTapCallback();
8930            onFocusLost();
8931        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
8932            imm.focusIn(this);
8933        }
8934        refreshDrawableState();
8935    }
8936
8937    /**
8938     * Returns true if this view is in a window that currently has window focus.
8939     * Note that this is not the same as the view itself having focus.
8940     *
8941     * @return True if this view is in a window that currently has window focus.
8942     */
8943    public boolean hasWindowFocus() {
8944        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
8945    }
8946
8947    /**
8948     * Dispatch a view visibility change down the view hierarchy.
8949     * ViewGroups should override to route to their children.
8950     * @param changedView The view whose visibility changed. Could be 'this' or
8951     * an ancestor view.
8952     * @param visibility The new visibility of changedView: {@link #VISIBLE},
8953     * {@link #INVISIBLE} or {@link #GONE}.
8954     */
8955    protected void dispatchVisibilityChanged(@NonNull View changedView,
8956            @Visibility int visibility) {
8957        onVisibilityChanged(changedView, visibility);
8958    }
8959
8960    /**
8961     * Called when the visibility of the view or an ancestor of the view has
8962     * changed.
8963     *
8964     * @param changedView The view whose visibility changed. May be
8965     *                    {@code this} or an ancestor view.
8966     * @param visibility The new visibility, one of {@link #VISIBLE},
8967     *                   {@link #INVISIBLE} or {@link #GONE}.
8968     */
8969    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
8970        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
8971        if (visible) {
8972            if (mAttachInfo != null) {
8973                initialAwakenScrollBars();
8974            } else {
8975                mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
8976            }
8977        }
8978
8979        final Drawable dr = mBackground;
8980        if (dr != null && visible != dr.isVisible()) {
8981            dr.setVisible(visible, false);
8982        }
8983        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
8984        if (fg != null && visible != fg.isVisible()) {
8985            fg.setVisible(visible, false);
8986        }
8987    }
8988
8989    /**
8990     * Dispatch a hint about whether this view is displayed. For instance, when
8991     * a View moves out of the screen, it might receives a display hint indicating
8992     * the view is not displayed. Applications should not <em>rely</em> on this hint
8993     * as there is no guarantee that they will receive one.
8994     *
8995     * @param hint A hint about whether or not this view is displayed:
8996     * {@link #VISIBLE} or {@link #INVISIBLE}.
8997     */
8998    public void dispatchDisplayHint(@Visibility int hint) {
8999        onDisplayHint(hint);
9000    }
9001
9002    /**
9003     * Gives this view a hint about whether is displayed or not. For instance, when
9004     * a View moves out of the screen, it might receives a display hint indicating
9005     * the view is not displayed. Applications should not <em>rely</em> on this hint
9006     * as there is no guarantee that they will receive one.
9007     *
9008     * @param hint A hint about whether or not this view is displayed:
9009     * {@link #VISIBLE} or {@link #INVISIBLE}.
9010     */
9011    protected void onDisplayHint(@Visibility int hint) {
9012    }
9013
9014    /**
9015     * Dispatch a window visibility change down the view hierarchy.
9016     * ViewGroups should override to route to their children.
9017     *
9018     * @param visibility The new visibility of the window.
9019     *
9020     * @see #onWindowVisibilityChanged(int)
9021     */
9022    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9023        onWindowVisibilityChanged(visibility);
9024    }
9025
9026    /**
9027     * Called when the window containing has change its visibility
9028     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9029     * that this tells you whether or not your window is being made visible
9030     * to the window manager; this does <em>not</em> tell you whether or not
9031     * your window is obscured by other windows on the screen, even if it
9032     * is itself visible.
9033     *
9034     * @param visibility The new visibility of the window.
9035     */
9036    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9037        if (visibility == VISIBLE) {
9038            initialAwakenScrollBars();
9039        }
9040    }
9041
9042    /**
9043     * Returns the current visibility of the window this view is attached to
9044     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9045     *
9046     * @return Returns the current visibility of the view's window.
9047     */
9048    @Visibility
9049    public int getWindowVisibility() {
9050        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9051    }
9052
9053    /**
9054     * Retrieve the overall visible display size in which the window this view is
9055     * attached to has been positioned in.  This takes into account screen
9056     * decorations above the window, for both cases where the window itself
9057     * is being position inside of them or the window is being placed under
9058     * then and covered insets are used for the window to position its content
9059     * inside.  In effect, this tells you the available area where content can
9060     * be placed and remain visible to users.
9061     *
9062     * <p>This function requires an IPC back to the window manager to retrieve
9063     * the requested information, so should not be used in performance critical
9064     * code like drawing.
9065     *
9066     * @param outRect Filled in with the visible display frame.  If the view
9067     * is not attached to a window, this is simply the raw display size.
9068     */
9069    public void getWindowVisibleDisplayFrame(Rect outRect) {
9070        if (mAttachInfo != null) {
9071            try {
9072                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9073            } catch (RemoteException e) {
9074                return;
9075            }
9076            // XXX This is really broken, and probably all needs to be done
9077            // in the window manager, and we need to know more about whether
9078            // we want the area behind or in front of the IME.
9079            final Rect insets = mAttachInfo.mVisibleInsets;
9080            outRect.left += insets.left;
9081            outRect.top += insets.top;
9082            outRect.right -= insets.right;
9083            outRect.bottom -= insets.bottom;
9084            return;
9085        }
9086        // The view is not attached to a display so we don't have a context.
9087        // Make a best guess about the display size.
9088        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9089        d.getRectSize(outRect);
9090    }
9091
9092    /**
9093     * Dispatch a notification about a resource configuration change down
9094     * the view hierarchy.
9095     * ViewGroups should override to route to their children.
9096     *
9097     * @param newConfig The new resource configuration.
9098     *
9099     * @see #onConfigurationChanged(android.content.res.Configuration)
9100     */
9101    public void dispatchConfigurationChanged(Configuration newConfig) {
9102        onConfigurationChanged(newConfig);
9103    }
9104
9105    /**
9106     * Called when the current configuration of the resources being used
9107     * by the application have changed.  You can use this to decide when
9108     * to reload resources that can changed based on orientation and other
9109     * configuration characteristics.  You only need to use this if you are
9110     * not relying on the normal {@link android.app.Activity} mechanism of
9111     * recreating the activity instance upon a configuration change.
9112     *
9113     * @param newConfig The new resource configuration.
9114     */
9115    protected void onConfigurationChanged(Configuration newConfig) {
9116    }
9117
9118    /**
9119     * Private function to aggregate all per-view attributes in to the view
9120     * root.
9121     */
9122    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9123        performCollectViewAttributes(attachInfo, visibility);
9124    }
9125
9126    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9127        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9128            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9129                attachInfo.mKeepScreenOn = true;
9130            }
9131            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9132            ListenerInfo li = mListenerInfo;
9133            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9134                attachInfo.mHasSystemUiListeners = true;
9135            }
9136        }
9137    }
9138
9139    void needGlobalAttributesUpdate(boolean force) {
9140        final AttachInfo ai = mAttachInfo;
9141        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9142            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9143                    || ai.mHasSystemUiListeners) {
9144                ai.mRecomputeGlobalAttributes = true;
9145            }
9146        }
9147    }
9148
9149    /**
9150     * Returns whether the device is currently in touch mode.  Touch mode is entered
9151     * once the user begins interacting with the device by touch, and affects various
9152     * things like whether focus is always visible to the user.
9153     *
9154     * @return Whether the device is in touch mode.
9155     */
9156    @ViewDebug.ExportedProperty
9157    public boolean isInTouchMode() {
9158        if (mAttachInfo != null) {
9159            return mAttachInfo.mInTouchMode;
9160        } else {
9161            return ViewRootImpl.isInTouchMode();
9162        }
9163    }
9164
9165    /**
9166     * Returns the context the view is running in, through which it can
9167     * access the current theme, resources, etc.
9168     *
9169     * @return The view's Context.
9170     */
9171    @ViewDebug.CapturedViewProperty
9172    public final Context getContext() {
9173        return mContext;
9174    }
9175
9176    /**
9177     * Handle a key event before it is processed by any input method
9178     * associated with the view hierarchy.  This can be used to intercept
9179     * key events in special situations before the IME consumes them; a
9180     * typical example would be handling the BACK key to update the application's
9181     * UI instead of allowing the IME to see it and close itself.
9182     *
9183     * @param keyCode The value in event.getKeyCode().
9184     * @param event Description of the key event.
9185     * @return If you handled the event, return true. If you want to allow the
9186     *         event to be handled by the next receiver, return false.
9187     */
9188    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9189        return false;
9190    }
9191
9192    /**
9193     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9194     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9195     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9196     * is released, if the view is enabled and clickable.
9197     *
9198     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9199     * although some may elect to do so in some situations. Do not rely on this to
9200     * catch software key presses.
9201     *
9202     * @param keyCode A key code that represents the button pressed, from
9203     *                {@link android.view.KeyEvent}.
9204     * @param event   The KeyEvent object that defines the button action.
9205     */
9206    public boolean onKeyDown(int keyCode, KeyEvent event) {
9207        boolean result = false;
9208
9209        if (KeyEvent.isConfirmKey(keyCode)) {
9210            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9211                return true;
9212            }
9213            // Long clickable items don't necessarily have to be clickable
9214            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9215                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9216                    (event.getRepeatCount() == 0)) {
9217                setPressed(true);
9218                checkForLongClick(0);
9219                return true;
9220            }
9221        }
9222        return result;
9223    }
9224
9225    /**
9226     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9227     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9228     * the event).
9229     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9230     * although some may elect to do so in some situations. Do not rely on this to
9231     * catch software key presses.
9232     */
9233    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9234        return false;
9235    }
9236
9237    /**
9238     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9239     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9240     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9241     * {@link KeyEvent#KEYCODE_ENTER} is released.
9242     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9243     * although some may elect to do so in some situations. Do not rely on this to
9244     * catch software key presses.
9245     *
9246     * @param keyCode A key code that represents the button pressed, from
9247     *                {@link android.view.KeyEvent}.
9248     * @param event   The KeyEvent object that defines the button action.
9249     */
9250    public boolean onKeyUp(int keyCode, KeyEvent event) {
9251        if (KeyEvent.isConfirmKey(keyCode)) {
9252            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9253                return true;
9254            }
9255            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9256                setPressed(false);
9257
9258                if (!mHasPerformedLongPress) {
9259                    // This is a tap, so remove the longpress check
9260                    removeLongPressCallback();
9261                    return performClick();
9262                }
9263            }
9264        }
9265        return false;
9266    }
9267
9268    /**
9269     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9270     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9271     * the event).
9272     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9273     * although some may elect to do so in some situations. Do not rely on this to
9274     * catch software key presses.
9275     *
9276     * @param keyCode     A key code that represents the button pressed, from
9277     *                    {@link android.view.KeyEvent}.
9278     * @param repeatCount The number of times the action was made.
9279     * @param event       The KeyEvent object that defines the button action.
9280     */
9281    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9282        return false;
9283    }
9284
9285    /**
9286     * Called on the focused view when a key shortcut event is not handled.
9287     * Override this method to implement local key shortcuts for the View.
9288     * Key shortcuts can also be implemented by setting the
9289     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9290     *
9291     * @param keyCode The value in event.getKeyCode().
9292     * @param event Description of the key event.
9293     * @return If you handled the event, return true. If you want to allow the
9294     *         event to be handled by the next receiver, return false.
9295     */
9296    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9297        return false;
9298    }
9299
9300    /**
9301     * Check whether the called view is a text editor, in which case it
9302     * would make sense to automatically display a soft input window for
9303     * it.  Subclasses should override this if they implement
9304     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9305     * a call on that method would return a non-null InputConnection, and
9306     * they are really a first-class editor that the user would normally
9307     * start typing on when the go into a window containing your view.
9308     *
9309     * <p>The default implementation always returns false.  This does
9310     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9311     * will not be called or the user can not otherwise perform edits on your
9312     * view; it is just a hint to the system that this is not the primary
9313     * purpose of this view.
9314     *
9315     * @return Returns true if this view is a text editor, else false.
9316     */
9317    public boolean onCheckIsTextEditor() {
9318        return false;
9319    }
9320
9321    /**
9322     * Create a new InputConnection for an InputMethod to interact
9323     * with the view.  The default implementation returns null, since it doesn't
9324     * support input methods.  You can override this to implement such support.
9325     * This is only needed for views that take focus and text input.
9326     *
9327     * <p>When implementing this, you probably also want to implement
9328     * {@link #onCheckIsTextEditor()} to indicate you will return a
9329     * non-null InputConnection.</p>
9330     *
9331     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9332     * object correctly and in its entirety, so that the connected IME can rely
9333     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9334     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9335     * must be filled in with the correct cursor position for IMEs to work correctly
9336     * with your application.</p>
9337     *
9338     * @param outAttrs Fill in with attribute information about the connection.
9339     */
9340    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9341        return null;
9342    }
9343
9344    /**
9345     * Called by the {@link android.view.inputmethod.InputMethodManager}
9346     * when a view who is not the current
9347     * input connection target is trying to make a call on the manager.  The
9348     * default implementation returns false; you can override this to return
9349     * true for certain views if you are performing InputConnection proxying
9350     * to them.
9351     * @param view The View that is making the InputMethodManager call.
9352     * @return Return true to allow the call, false to reject.
9353     */
9354    public boolean checkInputConnectionProxy(View view) {
9355        return false;
9356    }
9357
9358    /**
9359     * Show the context menu for this view. It is not safe to hold on to the
9360     * menu after returning from this method.
9361     *
9362     * You should normally not overload this method. Overload
9363     * {@link #onCreateContextMenu(ContextMenu)} or define an
9364     * {@link OnCreateContextMenuListener} to add items to the context menu.
9365     *
9366     * @param menu The context menu to populate
9367     */
9368    public void createContextMenu(ContextMenu menu) {
9369        ContextMenuInfo menuInfo = getContextMenuInfo();
9370
9371        // Sets the current menu info so all items added to menu will have
9372        // my extra info set.
9373        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9374
9375        onCreateContextMenu(menu);
9376        ListenerInfo li = mListenerInfo;
9377        if (li != null && li.mOnCreateContextMenuListener != null) {
9378            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
9379        }
9380
9381        // Clear the extra information so subsequent items that aren't mine don't
9382        // have my extra info.
9383        ((MenuBuilder)menu).setCurrentMenuInfo(null);
9384
9385        if (mParent != null) {
9386            mParent.createContextMenu(menu);
9387        }
9388    }
9389
9390    /**
9391     * Views should implement this if they have extra information to associate
9392     * with the context menu. The return result is supplied as a parameter to
9393     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
9394     * callback.
9395     *
9396     * @return Extra information about the item for which the context menu
9397     *         should be shown. This information will vary across different
9398     *         subclasses of View.
9399     */
9400    protected ContextMenuInfo getContextMenuInfo() {
9401        return null;
9402    }
9403
9404    /**
9405     * Views should implement this if the view itself is going to add items to
9406     * the context menu.
9407     *
9408     * @param menu the context menu to populate
9409     */
9410    protected void onCreateContextMenu(ContextMenu menu) {
9411    }
9412
9413    /**
9414     * Implement this method to handle trackball motion events.  The
9415     * <em>relative</em> movement of the trackball since the last event
9416     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
9417     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
9418     * that a movement of 1 corresponds to the user pressing one DPAD key (so
9419     * they will often be fractional values, representing the more fine-grained
9420     * movement information available from a trackball).
9421     *
9422     * @param event The motion event.
9423     * @return True if the event was handled, false otherwise.
9424     */
9425    public boolean onTrackballEvent(MotionEvent event) {
9426        return false;
9427    }
9428
9429    /**
9430     * Implement this method to handle generic motion events.
9431     * <p>
9432     * Generic motion events describe joystick movements, mouse hovers, track pad
9433     * touches, scroll wheel movements and other input events.  The
9434     * {@link MotionEvent#getSource() source} of the motion event specifies
9435     * the class of input that was received.  Implementations of this method
9436     * must examine the bits in the source before processing the event.
9437     * The following code example shows how this is done.
9438     * </p><p>
9439     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9440     * are delivered to the view under the pointer.  All other generic motion events are
9441     * delivered to the focused view.
9442     * </p>
9443     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
9444     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
9445     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
9446     *             // process the joystick movement...
9447     *             return true;
9448     *         }
9449     *     }
9450     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
9451     *         switch (event.getAction()) {
9452     *             case MotionEvent.ACTION_HOVER_MOVE:
9453     *                 // process the mouse hover movement...
9454     *                 return true;
9455     *             case MotionEvent.ACTION_SCROLL:
9456     *                 // process the scroll wheel movement...
9457     *                 return true;
9458     *         }
9459     *     }
9460     *     return super.onGenericMotionEvent(event);
9461     * }</pre>
9462     *
9463     * @param event The generic motion event being processed.
9464     * @return True if the event was handled, false otherwise.
9465     */
9466    public boolean onGenericMotionEvent(MotionEvent event) {
9467        return false;
9468    }
9469
9470    /**
9471     * Implement this method to handle hover events.
9472     * <p>
9473     * This method is called whenever a pointer is hovering into, over, or out of the
9474     * bounds of a view and the view is not currently being touched.
9475     * Hover events are represented as pointer events with action
9476     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
9477     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
9478     * </p>
9479     * <ul>
9480     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
9481     * when the pointer enters the bounds of the view.</li>
9482     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
9483     * when the pointer has already entered the bounds of the view and has moved.</li>
9484     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
9485     * when the pointer has exited the bounds of the view or when the pointer is
9486     * about to go down due to a button click, tap, or similar user action that
9487     * causes the view to be touched.</li>
9488     * </ul>
9489     * <p>
9490     * The view should implement this method to return true to indicate that it is
9491     * handling the hover event, such as by changing its drawable state.
9492     * </p><p>
9493     * The default implementation calls {@link #setHovered} to update the hovered state
9494     * of the view when a hover enter or hover exit event is received, if the view
9495     * is enabled and is clickable.  The default implementation also sends hover
9496     * accessibility events.
9497     * </p>
9498     *
9499     * @param event The motion event that describes the hover.
9500     * @return True if the view handled the hover event.
9501     *
9502     * @see #isHovered
9503     * @see #setHovered
9504     * @see #onHoverChanged
9505     */
9506    public boolean onHoverEvent(MotionEvent event) {
9507        // The root view may receive hover (or touch) events that are outside the bounds of
9508        // the window.  This code ensures that we only send accessibility events for
9509        // hovers that are actually within the bounds of the root view.
9510        final int action = event.getActionMasked();
9511        if (!mSendingHoverAccessibilityEvents) {
9512            if ((action == MotionEvent.ACTION_HOVER_ENTER
9513                    || action == MotionEvent.ACTION_HOVER_MOVE)
9514                    && !hasHoveredChild()
9515                    && pointInView(event.getX(), event.getY())) {
9516                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
9517                mSendingHoverAccessibilityEvents = true;
9518            }
9519        } else {
9520            if (action == MotionEvent.ACTION_HOVER_EXIT
9521                    || (action == MotionEvent.ACTION_MOVE
9522                            && !pointInView(event.getX(), event.getY()))) {
9523                mSendingHoverAccessibilityEvents = false;
9524                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
9525            }
9526        }
9527
9528        if (isHoverable()) {
9529            switch (action) {
9530                case MotionEvent.ACTION_HOVER_ENTER:
9531                    setHovered(true);
9532                    break;
9533                case MotionEvent.ACTION_HOVER_EXIT:
9534                    setHovered(false);
9535                    break;
9536            }
9537
9538            // Dispatch the event to onGenericMotionEvent before returning true.
9539            // This is to provide compatibility with existing applications that
9540            // handled HOVER_MOVE events in onGenericMotionEvent and that would
9541            // break because of the new default handling for hoverable views
9542            // in onHoverEvent.
9543            // Note that onGenericMotionEvent will be called by default when
9544            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
9545            dispatchGenericMotionEventInternal(event);
9546            // The event was already handled by calling setHovered(), so always
9547            // return true.
9548            return true;
9549        }
9550
9551        return false;
9552    }
9553
9554    /**
9555     * Returns true if the view should handle {@link #onHoverEvent}
9556     * by calling {@link #setHovered} to change its hovered state.
9557     *
9558     * @return True if the view is hoverable.
9559     */
9560    private boolean isHoverable() {
9561        final int viewFlags = mViewFlags;
9562        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9563            return false;
9564        }
9565
9566        return (viewFlags & CLICKABLE) == CLICKABLE
9567                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
9568    }
9569
9570    /**
9571     * Returns true if the view is currently hovered.
9572     *
9573     * @return True if the view is currently hovered.
9574     *
9575     * @see #setHovered
9576     * @see #onHoverChanged
9577     */
9578    @ViewDebug.ExportedProperty
9579    public boolean isHovered() {
9580        return (mPrivateFlags & PFLAG_HOVERED) != 0;
9581    }
9582
9583    /**
9584     * Sets whether the view is currently hovered.
9585     * <p>
9586     * Calling this method also changes the drawable state of the view.  This
9587     * enables the view to react to hover by using different drawable resources
9588     * to change its appearance.
9589     * </p><p>
9590     * The {@link #onHoverChanged} method is called when the hovered state changes.
9591     * </p>
9592     *
9593     * @param hovered True if the view is hovered.
9594     *
9595     * @see #isHovered
9596     * @see #onHoverChanged
9597     */
9598    public void setHovered(boolean hovered) {
9599        if (hovered) {
9600            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
9601                mPrivateFlags |= PFLAG_HOVERED;
9602                refreshDrawableState();
9603                onHoverChanged(true);
9604            }
9605        } else {
9606            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
9607                mPrivateFlags &= ~PFLAG_HOVERED;
9608                refreshDrawableState();
9609                onHoverChanged(false);
9610            }
9611        }
9612    }
9613
9614    /**
9615     * Implement this method to handle hover state changes.
9616     * <p>
9617     * This method is called whenever the hover state changes as a result of a
9618     * call to {@link #setHovered}.
9619     * </p>
9620     *
9621     * @param hovered The current hover state, as returned by {@link #isHovered}.
9622     *
9623     * @see #isHovered
9624     * @see #setHovered
9625     */
9626    public void onHoverChanged(boolean hovered) {
9627    }
9628
9629    /**
9630     * Implement this method to handle touch screen motion events.
9631     * <p>
9632     * If this method is used to detect click actions, it is recommended that
9633     * the actions be performed by implementing and calling
9634     * {@link #performClick()}. This will ensure consistent system behavior,
9635     * including:
9636     * <ul>
9637     * <li>obeying click sound preferences
9638     * <li>dispatching OnClickListener calls
9639     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
9640     * accessibility features are enabled
9641     * </ul>
9642     *
9643     * @param event The motion event.
9644     * @return True if the event was handled, false otherwise.
9645     */
9646    public boolean onTouchEvent(MotionEvent event) {
9647        final float x = event.getX();
9648        final float y = event.getY();
9649        final int viewFlags = mViewFlags;
9650
9651        if ((viewFlags & ENABLED_MASK) == DISABLED) {
9652            if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
9653                setPressed(false);
9654            }
9655            // A disabled view that is clickable still consumes the touch
9656            // events, it just doesn't respond to them.
9657            return (((viewFlags & CLICKABLE) == CLICKABLE ||
9658                    (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
9659        }
9660
9661        if (mTouchDelegate != null) {
9662            if (mTouchDelegate.onTouchEvent(event)) {
9663                return true;
9664            }
9665        }
9666
9667        if (((viewFlags & CLICKABLE) == CLICKABLE ||
9668                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
9669            switch (event.getAction()) {
9670                case MotionEvent.ACTION_UP:
9671                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
9672                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
9673                        // take focus if we don't have it already and we should in
9674                        // touch mode.
9675                        boolean focusTaken = false;
9676                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
9677                            focusTaken = requestFocus();
9678                        }
9679
9680                        if (prepressed) {
9681                            // The button is being released before we actually
9682                            // showed it as pressed.  Make it show the pressed
9683                            // state now (before scheduling the click) to ensure
9684                            // the user sees it.
9685                            setPressed(true, x, y);
9686                       }
9687
9688                        if (!mHasPerformedLongPress) {
9689                            // This is a tap, so remove the longpress check
9690                            removeLongPressCallback();
9691
9692                            // Only perform take click actions if we were in the pressed state
9693                            if (!focusTaken) {
9694                                // Use a Runnable and post this rather than calling
9695                                // performClick directly. This lets other visual state
9696                                // of the view update before click actions start.
9697                                if (mPerformClick == null) {
9698                                    mPerformClick = new PerformClick();
9699                                }
9700                                if (!post(mPerformClick)) {
9701                                    performClick();
9702                                }
9703                            }
9704                        }
9705
9706                        if (mUnsetPressedState == null) {
9707                            mUnsetPressedState = new UnsetPressedState();
9708                        }
9709
9710                        if (prepressed) {
9711                            postDelayed(mUnsetPressedState,
9712                                    ViewConfiguration.getPressedStateDuration());
9713                        } else if (!post(mUnsetPressedState)) {
9714                            // If the post failed, unpress right now
9715                            mUnsetPressedState.run();
9716                        }
9717
9718                        removeTapCallback();
9719                    }
9720                    break;
9721
9722                case MotionEvent.ACTION_DOWN:
9723                    mHasPerformedLongPress = false;
9724
9725                    if (performButtonActionOnTouchDown(event)) {
9726                        break;
9727                    }
9728
9729                    // Walk up the hierarchy to determine if we're inside a scrolling container.
9730                    boolean isInScrollingContainer = isInScrollingContainer();
9731
9732                    // For views inside a scrolling container, delay the pressed feedback for
9733                    // a short period in case this is a scroll.
9734                    if (isInScrollingContainer) {
9735                        mPrivateFlags |= PFLAG_PREPRESSED;
9736                        if (mPendingCheckForTap == null) {
9737                            mPendingCheckForTap = new CheckForTap();
9738                        }
9739                        mPendingCheckForTap.x = event.getX();
9740                        mPendingCheckForTap.y = event.getY();
9741                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
9742                    } else {
9743                        // Not inside a scrolling container, so show the feedback right away
9744                        setPressed(true, x, y);
9745                        checkForLongClick(0);
9746                    }
9747                    break;
9748
9749                case MotionEvent.ACTION_CANCEL:
9750                    setPressed(false);
9751                    removeTapCallback();
9752                    removeLongPressCallback();
9753                    break;
9754
9755                case MotionEvent.ACTION_MOVE:
9756                    drawableHotspotChanged(x, y);
9757
9758                    // Be lenient about moving outside of buttons
9759                    if (!pointInView(x, y, mTouchSlop)) {
9760                        // Outside button
9761                        removeTapCallback();
9762                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
9763                            // Remove any future long press/tap checks
9764                            removeLongPressCallback();
9765
9766                            setPressed(false);
9767                        }
9768                    }
9769                    break;
9770            }
9771
9772            return true;
9773        }
9774
9775        return false;
9776    }
9777
9778    /**
9779     * @hide
9780     */
9781    public boolean isInScrollingContainer() {
9782        ViewParent p = getParent();
9783        while (p != null && p instanceof ViewGroup) {
9784            if (((ViewGroup) p).shouldDelayChildPressedState()) {
9785                return true;
9786            }
9787            p = p.getParent();
9788        }
9789        return false;
9790    }
9791
9792    /**
9793     * Remove the longpress detection timer.
9794     */
9795    private void removeLongPressCallback() {
9796        if (mPendingCheckForLongPress != null) {
9797          removeCallbacks(mPendingCheckForLongPress);
9798        }
9799    }
9800
9801    /**
9802     * Remove the pending click action
9803     */
9804    private void removePerformClickCallback() {
9805        if (mPerformClick != null) {
9806            removeCallbacks(mPerformClick);
9807        }
9808    }
9809
9810    /**
9811     * Remove the prepress detection timer.
9812     */
9813    private void removeUnsetPressCallback() {
9814        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
9815            setPressed(false);
9816            removeCallbacks(mUnsetPressedState);
9817        }
9818    }
9819
9820    /**
9821     * Remove the tap detection timer.
9822     */
9823    private void removeTapCallback() {
9824        if (mPendingCheckForTap != null) {
9825            mPrivateFlags &= ~PFLAG_PREPRESSED;
9826            removeCallbacks(mPendingCheckForTap);
9827        }
9828    }
9829
9830    /**
9831     * Cancels a pending long press.  Your subclass can use this if you
9832     * want the context menu to come up if the user presses and holds
9833     * at the same place, but you don't want it to come up if they press
9834     * and then move around enough to cause scrolling.
9835     */
9836    public void cancelLongPress() {
9837        removeLongPressCallback();
9838
9839        /*
9840         * The prepressed state handled by the tap callback is a display
9841         * construct, but the tap callback will post a long press callback
9842         * less its own timeout. Remove it here.
9843         */
9844        removeTapCallback();
9845    }
9846
9847    /**
9848     * Remove the pending callback for sending a
9849     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
9850     */
9851    private void removeSendViewScrolledAccessibilityEventCallback() {
9852        if (mSendViewScrolledAccessibilityEvent != null) {
9853            removeCallbacks(mSendViewScrolledAccessibilityEvent);
9854            mSendViewScrolledAccessibilityEvent.mIsPending = false;
9855        }
9856    }
9857
9858    /**
9859     * Sets the TouchDelegate for this View.
9860     */
9861    public void setTouchDelegate(TouchDelegate delegate) {
9862        mTouchDelegate = delegate;
9863    }
9864
9865    /**
9866     * Gets the TouchDelegate for this View.
9867     */
9868    public TouchDelegate getTouchDelegate() {
9869        return mTouchDelegate;
9870    }
9871
9872    /**
9873     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
9874     *
9875     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
9876     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
9877     * available. This method should only be called for touch events.
9878     *
9879     * <p class="note">This api is not intended for most applications. Buffered dispatch
9880     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
9881     * streams will not improve your input latency. Side effects include: increased latency,
9882     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
9883     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
9884     * you.</p>
9885     */
9886    public final void requestUnbufferedDispatch(MotionEvent event) {
9887        final int action = event.getAction();
9888        if (mAttachInfo == null
9889                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
9890                || !event.isTouchEvent()) {
9891            return;
9892        }
9893        mAttachInfo.mUnbufferedDispatchRequested = true;
9894    }
9895
9896    /**
9897     * Set flags controlling behavior of this view.
9898     *
9899     * @param flags Constant indicating the value which should be set
9900     * @param mask Constant indicating the bit range that should be changed
9901     */
9902    void setFlags(int flags, int mask) {
9903        final boolean accessibilityEnabled =
9904                AccessibilityManager.getInstance(mContext).isEnabled();
9905        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
9906
9907        int old = mViewFlags;
9908        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
9909
9910        int changed = mViewFlags ^ old;
9911        if (changed == 0) {
9912            return;
9913        }
9914        int privateFlags = mPrivateFlags;
9915
9916        /* Check if the FOCUSABLE bit has changed */
9917        if (((changed & FOCUSABLE_MASK) != 0) &&
9918                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
9919            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
9920                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
9921                /* Give up focus if we are no longer focusable */
9922                clearFocus();
9923            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
9924                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
9925                /*
9926                 * Tell the view system that we are now available to take focus
9927                 * if no one else already has it.
9928                 */
9929                if (mParent != null) mParent.focusableViewAvailable(this);
9930            }
9931        }
9932
9933        final int newVisibility = flags & VISIBILITY_MASK;
9934        if (newVisibility == VISIBLE) {
9935            if ((changed & VISIBILITY_MASK) != 0) {
9936                /*
9937                 * If this view is becoming visible, invalidate it in case it changed while
9938                 * it was not visible. Marking it drawn ensures that the invalidation will
9939                 * go through.
9940                 */
9941                mPrivateFlags |= PFLAG_DRAWN;
9942                invalidate(true);
9943
9944                needGlobalAttributesUpdate(true);
9945
9946                // a view becoming visible is worth notifying the parent
9947                // about in case nothing has focus.  even if this specific view
9948                // isn't focusable, it may contain something that is, so let
9949                // the root view try to give this focus if nothing else does.
9950                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
9951                    mParent.focusableViewAvailable(this);
9952                }
9953            }
9954        }
9955
9956        /* Check if the GONE bit has changed */
9957        if ((changed & GONE) != 0) {
9958            needGlobalAttributesUpdate(false);
9959            requestLayout();
9960
9961            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
9962                if (hasFocus()) clearFocus();
9963                clearAccessibilityFocus();
9964                destroyDrawingCache();
9965                if (mParent instanceof View) {
9966                    // GONE views noop invalidation, so invalidate the parent
9967                    ((View) mParent).invalidate(true);
9968                }
9969                // Mark the view drawn to ensure that it gets invalidated properly the next
9970                // time it is visible and gets invalidated
9971                mPrivateFlags |= PFLAG_DRAWN;
9972            }
9973            if (mAttachInfo != null) {
9974                mAttachInfo.mViewVisibilityChanged = true;
9975            }
9976        }
9977
9978        /* Check if the VISIBLE bit has changed */
9979        if ((changed & INVISIBLE) != 0) {
9980            needGlobalAttributesUpdate(false);
9981            /*
9982             * If this view is becoming invisible, set the DRAWN flag so that
9983             * the next invalidate() will not be skipped.
9984             */
9985            mPrivateFlags |= PFLAG_DRAWN;
9986
9987            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
9988                // root view becoming invisible shouldn't clear focus and accessibility focus
9989                if (getRootView() != this) {
9990                    if (hasFocus()) clearFocus();
9991                    clearAccessibilityFocus();
9992                }
9993            }
9994            if (mAttachInfo != null) {
9995                mAttachInfo.mViewVisibilityChanged = true;
9996            }
9997        }
9998
9999        if ((changed & VISIBILITY_MASK) != 0) {
10000            // If the view is invisible, cleanup its display list to free up resources
10001            if (newVisibility != VISIBLE && mAttachInfo != null) {
10002                cleanupDraw();
10003            }
10004
10005            if (mParent instanceof ViewGroup) {
10006                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10007                        (changed & VISIBILITY_MASK), newVisibility);
10008                ((View) mParent).invalidate(true);
10009            } else if (mParent != null) {
10010                mParent.invalidateChild(this, null);
10011            }
10012            dispatchVisibilityChanged(this, newVisibility);
10013
10014            notifySubtreeAccessibilityStateChangedIfNeeded();
10015        }
10016
10017        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10018            destroyDrawingCache();
10019        }
10020
10021        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10022            destroyDrawingCache();
10023            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10024            invalidateParentCaches();
10025        }
10026
10027        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10028            destroyDrawingCache();
10029            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10030        }
10031
10032        if ((changed & DRAW_MASK) != 0) {
10033            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10034                if (mBackground != null) {
10035                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10036                    mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
10037                } else {
10038                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10039                }
10040            } else {
10041                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10042            }
10043            requestLayout();
10044            invalidate(true);
10045        }
10046
10047        if ((changed & KEEP_SCREEN_ON) != 0) {
10048            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10049                mParent.recomputeViewAttributes(this);
10050            }
10051        }
10052
10053        if (accessibilityEnabled) {
10054            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10055                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
10056                if (oldIncludeForAccessibility != includeForAccessibility()) {
10057                    notifySubtreeAccessibilityStateChangedIfNeeded();
10058                } else {
10059                    notifyViewAccessibilityStateChangedIfNeeded(
10060                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10061                }
10062            } else if ((changed & ENABLED_MASK) != 0) {
10063                notifyViewAccessibilityStateChangedIfNeeded(
10064                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10065            }
10066        }
10067    }
10068
10069    /**
10070     * Change the view's z order in the tree, so it's on top of other sibling
10071     * views. This ordering change may affect layout, if the parent container
10072     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10073     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10074     * method should be followed by calls to {@link #requestLayout()} and
10075     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10076     * with the new child ordering.
10077     *
10078     * @see ViewGroup#bringChildToFront(View)
10079     */
10080    public void bringToFront() {
10081        if (mParent != null) {
10082            mParent.bringChildToFront(this);
10083        }
10084    }
10085
10086    /**
10087     * This is called in response to an internal scroll in this view (i.e., the
10088     * view scrolled its own contents). This is typically as a result of
10089     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10090     * called.
10091     *
10092     * @param l Current horizontal scroll origin.
10093     * @param t Current vertical scroll origin.
10094     * @param oldl Previous horizontal scroll origin.
10095     * @param oldt Previous vertical scroll origin.
10096     */
10097    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10098        notifySubtreeAccessibilityStateChangedIfNeeded();
10099
10100        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10101            postSendViewScrolledAccessibilityEventCallback();
10102        }
10103
10104        mBackgroundSizeChanged = true;
10105        if (mForegroundInfo != null) {
10106            mForegroundInfo.mBoundsChanged = true;
10107        }
10108
10109        final AttachInfo ai = mAttachInfo;
10110        if (ai != null) {
10111            ai.mViewScrollChanged = true;
10112        }
10113
10114        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10115            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10116        }
10117    }
10118
10119    /**
10120     * Interface definition for a callback to be invoked when the scroll
10121     * X or Y positions of a view change.
10122     * <p>
10123     * <b>Note:</b> Some views handle scrolling independently from View and may
10124     * have their own separate listeners for scroll-type events. For example,
10125     * {@link android.widget.ListView ListView} allows clients to register an
10126     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10127     * to listen for changes in list scroll position.
10128     *
10129     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10130     */
10131    public interface OnScrollChangeListener {
10132        /**
10133         * Called when the scroll position of a view changes.
10134         *
10135         * @param v The view whose scroll position has changed.
10136         * @param scrollX Current horizontal scroll origin.
10137         * @param scrollY Current vertical scroll origin.
10138         * @param oldScrollX Previous horizontal scroll origin.
10139         * @param oldScrollY Previous vertical scroll origin.
10140         */
10141        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10142    }
10143
10144    /**
10145     * Interface definition for a callback to be invoked when the layout bounds of a view
10146     * changes due to layout processing.
10147     */
10148    public interface OnLayoutChangeListener {
10149        /**
10150         * Called when the layout bounds of a view changes due to layout processing.
10151         *
10152         * @param v The view whose bounds have changed.
10153         * @param left The new value of the view's left property.
10154         * @param top The new value of the view's top property.
10155         * @param right The new value of the view's right property.
10156         * @param bottom The new value of the view's bottom property.
10157         * @param oldLeft The previous value of the view's left property.
10158         * @param oldTop The previous value of the view's top property.
10159         * @param oldRight The previous value of the view's right property.
10160         * @param oldBottom The previous value of the view's bottom property.
10161         */
10162        void onLayoutChange(View v, int left, int top, int right, int bottom,
10163            int oldLeft, int oldTop, int oldRight, int oldBottom);
10164    }
10165
10166    /**
10167     * This is called during layout when the size of this view has changed. If
10168     * you were just added to the view hierarchy, you're called with the old
10169     * values of 0.
10170     *
10171     * @param w Current width of this view.
10172     * @param h Current height of this view.
10173     * @param oldw Old width of this view.
10174     * @param oldh Old height of this view.
10175     */
10176    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10177    }
10178
10179    /**
10180     * Called by draw to draw the child views. This may be overridden
10181     * by derived classes to gain control just before its children are drawn
10182     * (but after its own view has been drawn).
10183     * @param canvas the canvas on which to draw the view
10184     */
10185    protected void dispatchDraw(Canvas canvas) {
10186
10187    }
10188
10189    /**
10190     * Gets the parent of this view. Note that the parent is a
10191     * ViewParent and not necessarily a View.
10192     *
10193     * @return Parent of this view.
10194     */
10195    public final ViewParent getParent() {
10196        return mParent;
10197    }
10198
10199    /**
10200     * Set the horizontal scrolled position of your view. This will cause a call to
10201     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10202     * invalidated.
10203     * @param value the x position to scroll to
10204     */
10205    public void setScrollX(int value) {
10206        scrollTo(value, mScrollY);
10207    }
10208
10209    /**
10210     * Set the vertical scrolled position of your view. This will cause a call to
10211     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10212     * invalidated.
10213     * @param value the y position to scroll to
10214     */
10215    public void setScrollY(int value) {
10216        scrollTo(mScrollX, value);
10217    }
10218
10219    /**
10220     * Return the scrolled left position of this view. This is the left edge of
10221     * the displayed part of your view. You do not need to draw any pixels
10222     * farther left, since those are outside of the frame of your view on
10223     * screen.
10224     *
10225     * @return The left edge of the displayed part of your view, in pixels.
10226     */
10227    public final int getScrollX() {
10228        return mScrollX;
10229    }
10230
10231    /**
10232     * Return the scrolled top position of this view. This is the top edge of
10233     * the displayed part of your view. You do not need to draw any pixels above
10234     * it, since those are outside of the frame of your view on screen.
10235     *
10236     * @return The top edge of the displayed part of your view, in pixels.
10237     */
10238    public final int getScrollY() {
10239        return mScrollY;
10240    }
10241
10242    /**
10243     * Return the width of the your view.
10244     *
10245     * @return The width of your view, in pixels.
10246     */
10247    @ViewDebug.ExportedProperty(category = "layout")
10248    public final int getWidth() {
10249        return mRight - mLeft;
10250    }
10251
10252    /**
10253     * Return the height of your view.
10254     *
10255     * @return The height of your view, in pixels.
10256     */
10257    @ViewDebug.ExportedProperty(category = "layout")
10258    public final int getHeight() {
10259        return mBottom - mTop;
10260    }
10261
10262    /**
10263     * Return the visible drawing bounds of your view. Fills in the output
10264     * rectangle with the values from getScrollX(), getScrollY(),
10265     * getWidth(), and getHeight(). These bounds do not account for any
10266     * transformation properties currently set on the view, such as
10267     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10268     *
10269     * @param outRect The (scrolled) drawing bounds of the view.
10270     */
10271    public void getDrawingRect(Rect outRect) {
10272        outRect.left = mScrollX;
10273        outRect.top = mScrollY;
10274        outRect.right = mScrollX + (mRight - mLeft);
10275        outRect.bottom = mScrollY + (mBottom - mTop);
10276    }
10277
10278    /**
10279     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10280     * raw width component (that is the result is masked by
10281     * {@link #MEASURED_SIZE_MASK}).
10282     *
10283     * @return The raw measured width of this view.
10284     */
10285    public final int getMeasuredWidth() {
10286        return mMeasuredWidth & MEASURED_SIZE_MASK;
10287    }
10288
10289    /**
10290     * Return the full width measurement information for this view as computed
10291     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10292     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10293     * This should be used during measurement and layout calculations only. Use
10294     * {@link #getWidth()} to see how wide a view is after layout.
10295     *
10296     * @return The measured width of this view as a bit mask.
10297     */
10298    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10299            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10300                    name = "MEASURED_STATE_TOO_SMALL"),
10301    })
10302    public final int getMeasuredWidthAndState() {
10303        return mMeasuredWidth;
10304    }
10305
10306    /**
10307     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10308     * raw width component (that is the result is masked by
10309     * {@link #MEASURED_SIZE_MASK}).
10310     *
10311     * @return The raw measured height of this view.
10312     */
10313    public final int getMeasuredHeight() {
10314        return mMeasuredHeight & MEASURED_SIZE_MASK;
10315    }
10316
10317    /**
10318     * Return the full height measurement information for this view as computed
10319     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10320     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10321     * This should be used during measurement and layout calculations only. Use
10322     * {@link #getHeight()} to see how wide a view is after layout.
10323     *
10324     * @return The measured width of this view as a bit mask.
10325     */
10326    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10327            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10328                    name = "MEASURED_STATE_TOO_SMALL"),
10329    })
10330    public final int getMeasuredHeightAndState() {
10331        return mMeasuredHeight;
10332    }
10333
10334    /**
10335     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10336     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10337     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10338     * and the height component is at the shifted bits
10339     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10340     */
10341    public final int getMeasuredState() {
10342        return (mMeasuredWidth&MEASURED_STATE_MASK)
10343                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10344                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10345    }
10346
10347    /**
10348     * The transform matrix of this view, which is calculated based on the current
10349     * rotation, scale, and pivot properties.
10350     *
10351     * @see #getRotation()
10352     * @see #getScaleX()
10353     * @see #getScaleY()
10354     * @see #getPivotX()
10355     * @see #getPivotY()
10356     * @return The current transform matrix for the view
10357     */
10358    public Matrix getMatrix() {
10359        ensureTransformationInfo();
10360        final Matrix matrix = mTransformationInfo.mMatrix;
10361        mRenderNode.getMatrix(matrix);
10362        return matrix;
10363    }
10364
10365    /**
10366     * Returns true if the transform matrix is the identity matrix.
10367     * Recomputes the matrix if necessary.
10368     *
10369     * @return True if the transform matrix is the identity matrix, false otherwise.
10370     */
10371    final boolean hasIdentityMatrix() {
10372        return mRenderNode.hasIdentityMatrix();
10373    }
10374
10375    void ensureTransformationInfo() {
10376        if (mTransformationInfo == null) {
10377            mTransformationInfo = new TransformationInfo();
10378        }
10379    }
10380
10381   /**
10382     * Utility method to retrieve the inverse of the current mMatrix property.
10383     * We cache the matrix to avoid recalculating it when transform properties
10384     * have not changed.
10385     *
10386     * @return The inverse of the current matrix of this view.
10387     * @hide
10388     */
10389    public final Matrix getInverseMatrix() {
10390        ensureTransformationInfo();
10391        if (mTransformationInfo.mInverseMatrix == null) {
10392            mTransformationInfo.mInverseMatrix = new Matrix();
10393        }
10394        final Matrix matrix = mTransformationInfo.mInverseMatrix;
10395        mRenderNode.getInverseMatrix(matrix);
10396        return matrix;
10397    }
10398
10399    /**
10400     * Gets the distance along the Z axis from the camera to this view.
10401     *
10402     * @see #setCameraDistance(float)
10403     *
10404     * @return The distance along the Z axis.
10405     */
10406    public float getCameraDistance() {
10407        final float dpi = mResources.getDisplayMetrics().densityDpi;
10408        return -(mRenderNode.getCameraDistance() * dpi);
10409    }
10410
10411    /**
10412     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
10413     * views are drawn) from the camera to this view. The camera's distance
10414     * affects 3D transformations, for instance rotations around the X and Y
10415     * axis. If the rotationX or rotationY properties are changed and this view is
10416     * large (more than half the size of the screen), it is recommended to always
10417     * use a camera distance that's greater than the height (X axis rotation) or
10418     * the width (Y axis rotation) of this view.</p>
10419     *
10420     * <p>The distance of the camera from the view plane can have an affect on the
10421     * perspective distortion of the view when it is rotated around the x or y axis.
10422     * For example, a large distance will result in a large viewing angle, and there
10423     * will not be much perspective distortion of the view as it rotates. A short
10424     * distance may cause much more perspective distortion upon rotation, and can
10425     * also result in some drawing artifacts if the rotated view ends up partially
10426     * behind the camera (which is why the recommendation is to use a distance at
10427     * least as far as the size of the view, if the view is to be rotated.)</p>
10428     *
10429     * <p>The distance is expressed in "depth pixels." The default distance depends
10430     * on the screen density. For instance, on a medium density display, the
10431     * default distance is 1280. On a high density display, the default distance
10432     * is 1920.</p>
10433     *
10434     * <p>If you want to specify a distance that leads to visually consistent
10435     * results across various densities, use the following formula:</p>
10436     * <pre>
10437     * float scale = context.getResources().getDisplayMetrics().density;
10438     * view.setCameraDistance(distance * scale);
10439     * </pre>
10440     *
10441     * <p>The density scale factor of a high density display is 1.5,
10442     * and 1920 = 1280 * 1.5.</p>
10443     *
10444     * @param distance The distance in "depth pixels", if negative the opposite
10445     *        value is used
10446     *
10447     * @see #setRotationX(float)
10448     * @see #setRotationY(float)
10449     */
10450    public void setCameraDistance(float distance) {
10451        final float dpi = mResources.getDisplayMetrics().densityDpi;
10452
10453        invalidateViewProperty(true, false);
10454        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
10455        invalidateViewProperty(false, false);
10456
10457        invalidateParentIfNeededAndWasQuickRejected();
10458    }
10459
10460    /**
10461     * The degrees that the view is rotated around the pivot point.
10462     *
10463     * @see #setRotation(float)
10464     * @see #getPivotX()
10465     * @see #getPivotY()
10466     *
10467     * @return The degrees of rotation.
10468     */
10469    @ViewDebug.ExportedProperty(category = "drawing")
10470    public float getRotation() {
10471        return mRenderNode.getRotation();
10472    }
10473
10474    /**
10475     * Sets the degrees that the view is rotated around the pivot point. Increasing values
10476     * result in clockwise rotation.
10477     *
10478     * @param rotation The degrees of rotation.
10479     *
10480     * @see #getRotation()
10481     * @see #getPivotX()
10482     * @see #getPivotY()
10483     * @see #setRotationX(float)
10484     * @see #setRotationY(float)
10485     *
10486     * @attr ref android.R.styleable#View_rotation
10487     */
10488    public void setRotation(float rotation) {
10489        if (rotation != getRotation()) {
10490            // Double-invalidation is necessary to capture view's old and new areas
10491            invalidateViewProperty(true, false);
10492            mRenderNode.setRotation(rotation);
10493            invalidateViewProperty(false, true);
10494
10495            invalidateParentIfNeededAndWasQuickRejected();
10496            notifySubtreeAccessibilityStateChangedIfNeeded();
10497        }
10498    }
10499
10500    /**
10501     * The degrees that the view is rotated around the vertical axis through the pivot point.
10502     *
10503     * @see #getPivotX()
10504     * @see #getPivotY()
10505     * @see #setRotationY(float)
10506     *
10507     * @return The degrees of Y rotation.
10508     */
10509    @ViewDebug.ExportedProperty(category = "drawing")
10510    public float getRotationY() {
10511        return mRenderNode.getRotationY();
10512    }
10513
10514    /**
10515     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
10516     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
10517     * down the y axis.
10518     *
10519     * When rotating large views, it is recommended to adjust the camera distance
10520     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10521     *
10522     * @param rotationY The degrees of Y rotation.
10523     *
10524     * @see #getRotationY()
10525     * @see #getPivotX()
10526     * @see #getPivotY()
10527     * @see #setRotation(float)
10528     * @see #setRotationX(float)
10529     * @see #setCameraDistance(float)
10530     *
10531     * @attr ref android.R.styleable#View_rotationY
10532     */
10533    public void setRotationY(float rotationY) {
10534        if (rotationY != getRotationY()) {
10535            invalidateViewProperty(true, false);
10536            mRenderNode.setRotationY(rotationY);
10537            invalidateViewProperty(false, true);
10538
10539            invalidateParentIfNeededAndWasQuickRejected();
10540            notifySubtreeAccessibilityStateChangedIfNeeded();
10541        }
10542    }
10543
10544    /**
10545     * The degrees that the view is rotated around the horizontal axis through the pivot point.
10546     *
10547     * @see #getPivotX()
10548     * @see #getPivotY()
10549     * @see #setRotationX(float)
10550     *
10551     * @return The degrees of X rotation.
10552     */
10553    @ViewDebug.ExportedProperty(category = "drawing")
10554    public float getRotationX() {
10555        return mRenderNode.getRotationX();
10556    }
10557
10558    /**
10559     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
10560     * Increasing values result in clockwise rotation from the viewpoint of looking down the
10561     * x axis.
10562     *
10563     * When rotating large views, it is recommended to adjust the camera distance
10564     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
10565     *
10566     * @param rotationX The degrees of X rotation.
10567     *
10568     * @see #getRotationX()
10569     * @see #getPivotX()
10570     * @see #getPivotY()
10571     * @see #setRotation(float)
10572     * @see #setRotationY(float)
10573     * @see #setCameraDistance(float)
10574     *
10575     * @attr ref android.R.styleable#View_rotationX
10576     */
10577    public void setRotationX(float rotationX) {
10578        if (rotationX != getRotationX()) {
10579            invalidateViewProperty(true, false);
10580            mRenderNode.setRotationX(rotationX);
10581            invalidateViewProperty(false, true);
10582
10583            invalidateParentIfNeededAndWasQuickRejected();
10584            notifySubtreeAccessibilityStateChangedIfNeeded();
10585        }
10586    }
10587
10588    /**
10589     * The amount that the view is scaled in x around the pivot point, as a proportion of
10590     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
10591     *
10592     * <p>By default, this is 1.0f.
10593     *
10594     * @see #getPivotX()
10595     * @see #getPivotY()
10596     * @return The scaling factor.
10597     */
10598    @ViewDebug.ExportedProperty(category = "drawing")
10599    public float getScaleX() {
10600        return mRenderNode.getScaleX();
10601    }
10602
10603    /**
10604     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
10605     * the view's unscaled width. A value of 1 means that no scaling is applied.
10606     *
10607     * @param scaleX The scaling factor.
10608     * @see #getPivotX()
10609     * @see #getPivotY()
10610     *
10611     * @attr ref android.R.styleable#View_scaleX
10612     */
10613    public void setScaleX(float scaleX) {
10614        if (scaleX != getScaleX()) {
10615            invalidateViewProperty(true, false);
10616            mRenderNode.setScaleX(scaleX);
10617            invalidateViewProperty(false, true);
10618
10619            invalidateParentIfNeededAndWasQuickRejected();
10620            notifySubtreeAccessibilityStateChangedIfNeeded();
10621        }
10622    }
10623
10624    /**
10625     * The amount that the view is scaled in y around the pivot point, as a proportion of
10626     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
10627     *
10628     * <p>By default, this is 1.0f.
10629     *
10630     * @see #getPivotX()
10631     * @see #getPivotY()
10632     * @return The scaling factor.
10633     */
10634    @ViewDebug.ExportedProperty(category = "drawing")
10635    public float getScaleY() {
10636        return mRenderNode.getScaleY();
10637    }
10638
10639    /**
10640     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
10641     * the view's unscaled width. A value of 1 means that no scaling is applied.
10642     *
10643     * @param scaleY The scaling factor.
10644     * @see #getPivotX()
10645     * @see #getPivotY()
10646     *
10647     * @attr ref android.R.styleable#View_scaleY
10648     */
10649    public void setScaleY(float scaleY) {
10650        if (scaleY != getScaleY()) {
10651            invalidateViewProperty(true, false);
10652            mRenderNode.setScaleY(scaleY);
10653            invalidateViewProperty(false, true);
10654
10655            invalidateParentIfNeededAndWasQuickRejected();
10656            notifySubtreeAccessibilityStateChangedIfNeeded();
10657        }
10658    }
10659
10660    /**
10661     * The x location of the point around which the view is {@link #setRotation(float) rotated}
10662     * and {@link #setScaleX(float) scaled}.
10663     *
10664     * @see #getRotation()
10665     * @see #getScaleX()
10666     * @see #getScaleY()
10667     * @see #getPivotY()
10668     * @return The x location of the pivot point.
10669     *
10670     * @attr ref android.R.styleable#View_transformPivotX
10671     */
10672    @ViewDebug.ExportedProperty(category = "drawing")
10673    public float getPivotX() {
10674        return mRenderNode.getPivotX();
10675    }
10676
10677    /**
10678     * Sets the x location of the point around which the view is
10679     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
10680     * By default, the pivot point is centered on the object.
10681     * Setting this property disables this behavior and causes the view to use only the
10682     * explicitly set pivotX and pivotY values.
10683     *
10684     * @param pivotX The x location of the pivot point.
10685     * @see #getRotation()
10686     * @see #getScaleX()
10687     * @see #getScaleY()
10688     * @see #getPivotY()
10689     *
10690     * @attr ref android.R.styleable#View_transformPivotX
10691     */
10692    public void setPivotX(float pivotX) {
10693        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
10694            invalidateViewProperty(true, false);
10695            mRenderNode.setPivotX(pivotX);
10696            invalidateViewProperty(false, true);
10697
10698            invalidateParentIfNeededAndWasQuickRejected();
10699        }
10700    }
10701
10702    /**
10703     * The y location of the point around which the view is {@link #setRotation(float) rotated}
10704     * and {@link #setScaleY(float) scaled}.
10705     *
10706     * @see #getRotation()
10707     * @see #getScaleX()
10708     * @see #getScaleY()
10709     * @see #getPivotY()
10710     * @return The y location of the pivot point.
10711     *
10712     * @attr ref android.R.styleable#View_transformPivotY
10713     */
10714    @ViewDebug.ExportedProperty(category = "drawing")
10715    public float getPivotY() {
10716        return mRenderNode.getPivotY();
10717    }
10718
10719    /**
10720     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
10721     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
10722     * Setting this property disables this behavior and causes the view to use only the
10723     * explicitly set pivotX and pivotY values.
10724     *
10725     * @param pivotY The y location of the pivot point.
10726     * @see #getRotation()
10727     * @see #getScaleX()
10728     * @see #getScaleY()
10729     * @see #getPivotY()
10730     *
10731     * @attr ref android.R.styleable#View_transformPivotY
10732     */
10733    public void setPivotY(float pivotY) {
10734        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
10735            invalidateViewProperty(true, false);
10736            mRenderNode.setPivotY(pivotY);
10737            invalidateViewProperty(false, true);
10738
10739            invalidateParentIfNeededAndWasQuickRejected();
10740        }
10741    }
10742
10743    /**
10744     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
10745     * completely transparent and 1 means the view is completely opaque.
10746     *
10747     * <p>By default this is 1.0f.
10748     * @return The opacity of the view.
10749     */
10750    @ViewDebug.ExportedProperty(category = "drawing")
10751    public float getAlpha() {
10752        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
10753    }
10754
10755    /**
10756     * Returns whether this View has content which overlaps.
10757     *
10758     * <p>This function, intended to be overridden by specific View types, is an optimization when
10759     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
10760     * an offscreen buffer and then composited into place, which can be expensive. If the view has
10761     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
10762     * directly. An example of overlapping rendering is a TextView with a background image, such as
10763     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
10764     * ImageView with only the foreground image. The default implementation returns true; subclasses
10765     * should override if they have cases which can be optimized.</p>
10766     *
10767     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
10768     * necessitates that a View return true if it uses the methods internally without passing the
10769     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
10770     *
10771     * @return true if the content in this view might overlap, false otherwise.
10772     */
10773    @ViewDebug.ExportedProperty(category = "drawing")
10774    public boolean hasOverlappingRendering() {
10775        return true;
10776    }
10777
10778    /**
10779     * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
10780     * completely transparent and 1 means the view is completely opaque.</p>
10781     *
10782     * <p> Note that setting alpha to a translucent value (0 < alpha < 1) can have significant
10783     * performance implications, especially for large views. It is best to use the alpha property
10784     * sparingly and transiently, as in the case of fading animations.</p>
10785     *
10786     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
10787     * strongly recommended for performance reasons to either override
10788     * {@link #hasOverlappingRendering()} to return false if appropriate, or setting a
10789     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view.</p>
10790     *
10791     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
10792     * responsible for applying the opacity itself.</p>
10793     *
10794     * <p>Note that if the view is backed by a
10795     * {@link #setLayerType(int, android.graphics.Paint) layer} and is associated with a
10796     * {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an alpha value less than
10797     * 1.0 will supersede the alpha of the layer paint.</p>
10798     *
10799     * @param alpha The opacity of the view.
10800     *
10801     * @see #hasOverlappingRendering()
10802     * @see #setLayerType(int, android.graphics.Paint)
10803     *
10804     * @attr ref android.R.styleable#View_alpha
10805     */
10806    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
10807        ensureTransformationInfo();
10808        if (mTransformationInfo.mAlpha != alpha) {
10809            mTransformationInfo.mAlpha = alpha;
10810            if (onSetAlpha((int) (alpha * 255))) {
10811                mPrivateFlags |= PFLAG_ALPHA_SET;
10812                // subclass is handling alpha - don't optimize rendering cache invalidation
10813                invalidateParentCaches();
10814                invalidate(true);
10815            } else {
10816                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10817                invalidateViewProperty(true, false);
10818                mRenderNode.setAlpha(getFinalAlpha());
10819                notifyViewAccessibilityStateChangedIfNeeded(
10820                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10821            }
10822        }
10823    }
10824
10825    /**
10826     * Faster version of setAlpha() which performs the same steps except there are
10827     * no calls to invalidate(). The caller of this function should perform proper invalidation
10828     * on the parent and this object. The return value indicates whether the subclass handles
10829     * alpha (the return value for onSetAlpha()).
10830     *
10831     * @param alpha The new value for the alpha property
10832     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
10833     *         the new value for the alpha property is different from the old value
10834     */
10835    boolean setAlphaNoInvalidation(float alpha) {
10836        ensureTransformationInfo();
10837        if (mTransformationInfo.mAlpha != alpha) {
10838            mTransformationInfo.mAlpha = alpha;
10839            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
10840            if (subclassHandlesAlpha) {
10841                mPrivateFlags |= PFLAG_ALPHA_SET;
10842                return true;
10843            } else {
10844                mPrivateFlags &= ~PFLAG_ALPHA_SET;
10845                mRenderNode.setAlpha(getFinalAlpha());
10846            }
10847        }
10848        return false;
10849    }
10850
10851    /**
10852     * This property is hidden and intended only for use by the Fade transition, which
10853     * animates it to produce a visual translucency that does not side-effect (or get
10854     * affected by) the real alpha property. This value is composited with the other
10855     * alpha value (and the AlphaAnimation value, when that is present) to produce
10856     * a final visual translucency result, which is what is passed into the DisplayList.
10857     *
10858     * @hide
10859     */
10860    public void setTransitionAlpha(float alpha) {
10861        ensureTransformationInfo();
10862        if (mTransformationInfo.mTransitionAlpha != alpha) {
10863            mTransformationInfo.mTransitionAlpha = alpha;
10864            mPrivateFlags &= ~PFLAG_ALPHA_SET;
10865            invalidateViewProperty(true, false);
10866            mRenderNode.setAlpha(getFinalAlpha());
10867        }
10868    }
10869
10870    /**
10871     * Calculates the visual alpha of this view, which is a combination of the actual
10872     * alpha value and the transitionAlpha value (if set).
10873     */
10874    private float getFinalAlpha() {
10875        if (mTransformationInfo != null) {
10876            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
10877        }
10878        return 1;
10879    }
10880
10881    /**
10882     * This property is hidden and intended only for use by the Fade transition, which
10883     * animates it to produce a visual translucency that does not side-effect (or get
10884     * affected by) the real alpha property. This value is composited with the other
10885     * alpha value (and the AlphaAnimation value, when that is present) to produce
10886     * a final visual translucency result, which is what is passed into the DisplayList.
10887     *
10888     * @hide
10889     */
10890    @ViewDebug.ExportedProperty(category = "drawing")
10891    public float getTransitionAlpha() {
10892        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
10893    }
10894
10895    /**
10896     * Top position of this view relative to its parent.
10897     *
10898     * @return The top of this view, in pixels.
10899     */
10900    @ViewDebug.CapturedViewProperty
10901    public final int getTop() {
10902        return mTop;
10903    }
10904
10905    /**
10906     * Sets the top position of this view relative to its parent. This method is meant to be called
10907     * by the layout system and should not generally be called otherwise, because the property
10908     * may be changed at any time by the layout.
10909     *
10910     * @param top The top of this view, in pixels.
10911     */
10912    public final void setTop(int top) {
10913        if (top != mTop) {
10914            final boolean matrixIsIdentity = hasIdentityMatrix();
10915            if (matrixIsIdentity) {
10916                if (mAttachInfo != null) {
10917                    int minTop;
10918                    int yLoc;
10919                    if (top < mTop) {
10920                        minTop = top;
10921                        yLoc = top - mTop;
10922                    } else {
10923                        minTop = mTop;
10924                        yLoc = 0;
10925                    }
10926                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
10927                }
10928            } else {
10929                // Double-invalidation is necessary to capture view's old and new areas
10930                invalidate(true);
10931            }
10932
10933            int width = mRight - mLeft;
10934            int oldHeight = mBottom - mTop;
10935
10936            mTop = top;
10937            mRenderNode.setTop(mTop);
10938
10939            sizeChange(width, mBottom - mTop, width, oldHeight);
10940
10941            if (!matrixIsIdentity) {
10942                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
10943                invalidate(true);
10944            }
10945            mBackgroundSizeChanged = true;
10946            if (mForegroundInfo != null) {
10947                mForegroundInfo.mBoundsChanged = true;
10948            }
10949            invalidateParentIfNeeded();
10950            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
10951                // View was rejected last time it was drawn by its parent; this may have changed
10952                invalidateParentIfNeeded();
10953            }
10954        }
10955    }
10956
10957    /**
10958     * Bottom position of this view relative to its parent.
10959     *
10960     * @return The bottom of this view, in pixels.
10961     */
10962    @ViewDebug.CapturedViewProperty
10963    public final int getBottom() {
10964        return mBottom;
10965    }
10966
10967    /**
10968     * True if this view has changed since the last time being drawn.
10969     *
10970     * @return The dirty state of this view.
10971     */
10972    public boolean isDirty() {
10973        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
10974    }
10975
10976    /**
10977     * Sets the bottom position of this view relative to its parent. This method is meant to be
10978     * called by the layout system and should not generally be called otherwise, because the
10979     * property may be changed at any time by the layout.
10980     *
10981     * @param bottom The bottom of this view, in pixels.
10982     */
10983    public final void setBottom(int bottom) {
10984        if (bottom != mBottom) {
10985            final boolean matrixIsIdentity = hasIdentityMatrix();
10986            if (matrixIsIdentity) {
10987                if (mAttachInfo != null) {
10988                    int maxBottom;
10989                    if (bottom < mBottom) {
10990                        maxBottom = mBottom;
10991                    } else {
10992                        maxBottom = bottom;
10993                    }
10994                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
10995                }
10996            } else {
10997                // Double-invalidation is necessary to capture view's old and new areas
10998                invalidate(true);
10999            }
11000
11001            int width = mRight - mLeft;
11002            int oldHeight = mBottom - mTop;
11003
11004            mBottom = bottom;
11005            mRenderNode.setBottom(mBottom);
11006
11007            sizeChange(width, mBottom - mTop, width, oldHeight);
11008
11009            if (!matrixIsIdentity) {
11010                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11011                invalidate(true);
11012            }
11013            mBackgroundSizeChanged = true;
11014            if (mForegroundInfo != null) {
11015                mForegroundInfo.mBoundsChanged = true;
11016            }
11017            invalidateParentIfNeeded();
11018            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11019                // View was rejected last time it was drawn by its parent; this may have changed
11020                invalidateParentIfNeeded();
11021            }
11022        }
11023    }
11024
11025    /**
11026     * Left position of this view relative to its parent.
11027     *
11028     * @return The left edge of this view, in pixels.
11029     */
11030    @ViewDebug.CapturedViewProperty
11031    public final int getLeft() {
11032        return mLeft;
11033    }
11034
11035    /**
11036     * Sets the left position of this view relative to its parent. This method is meant to be called
11037     * by the layout system and should not generally be called otherwise, because the property
11038     * may be changed at any time by the layout.
11039     *
11040     * @param left The left of this view, in pixels.
11041     */
11042    public final void setLeft(int left) {
11043        if (left != mLeft) {
11044            final boolean matrixIsIdentity = hasIdentityMatrix();
11045            if (matrixIsIdentity) {
11046                if (mAttachInfo != null) {
11047                    int minLeft;
11048                    int xLoc;
11049                    if (left < mLeft) {
11050                        minLeft = left;
11051                        xLoc = left - mLeft;
11052                    } else {
11053                        minLeft = mLeft;
11054                        xLoc = 0;
11055                    }
11056                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11057                }
11058            } else {
11059                // Double-invalidation is necessary to capture view's old and new areas
11060                invalidate(true);
11061            }
11062
11063            int oldWidth = mRight - mLeft;
11064            int height = mBottom - mTop;
11065
11066            mLeft = left;
11067            mRenderNode.setLeft(left);
11068
11069            sizeChange(mRight - mLeft, height, oldWidth, height);
11070
11071            if (!matrixIsIdentity) {
11072                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11073                invalidate(true);
11074            }
11075            mBackgroundSizeChanged = true;
11076            if (mForegroundInfo != null) {
11077                mForegroundInfo.mBoundsChanged = true;
11078            }
11079            invalidateParentIfNeeded();
11080            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11081                // View was rejected last time it was drawn by its parent; this may have changed
11082                invalidateParentIfNeeded();
11083            }
11084        }
11085    }
11086
11087    /**
11088     * Right position of this view relative to its parent.
11089     *
11090     * @return The right edge of this view, in pixels.
11091     */
11092    @ViewDebug.CapturedViewProperty
11093    public final int getRight() {
11094        return mRight;
11095    }
11096
11097    /**
11098     * Sets the right position of this view relative to its parent. This method is meant to be called
11099     * by the layout system and should not generally be called otherwise, because the property
11100     * may be changed at any time by the layout.
11101     *
11102     * @param right The right of this view, in pixels.
11103     */
11104    public final void setRight(int right) {
11105        if (right != mRight) {
11106            final boolean matrixIsIdentity = hasIdentityMatrix();
11107            if (matrixIsIdentity) {
11108                if (mAttachInfo != null) {
11109                    int maxRight;
11110                    if (right < mRight) {
11111                        maxRight = mRight;
11112                    } else {
11113                        maxRight = right;
11114                    }
11115                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11116                }
11117            } else {
11118                // Double-invalidation is necessary to capture view's old and new areas
11119                invalidate(true);
11120            }
11121
11122            int oldWidth = mRight - mLeft;
11123            int height = mBottom - mTop;
11124
11125            mRight = right;
11126            mRenderNode.setRight(mRight);
11127
11128            sizeChange(mRight - mLeft, height, oldWidth, height);
11129
11130            if (!matrixIsIdentity) {
11131                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11132                invalidate(true);
11133            }
11134            mBackgroundSizeChanged = true;
11135            if (mForegroundInfo != null) {
11136                mForegroundInfo.mBoundsChanged = true;
11137            }
11138            invalidateParentIfNeeded();
11139            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11140                // View was rejected last time it was drawn by its parent; this may have changed
11141                invalidateParentIfNeeded();
11142            }
11143        }
11144    }
11145
11146    /**
11147     * The visual x position of this view, in pixels. This is equivalent to the
11148     * {@link #setTranslationX(float) translationX} property plus the current
11149     * {@link #getLeft() left} property.
11150     *
11151     * @return The visual x position of this view, in pixels.
11152     */
11153    @ViewDebug.ExportedProperty(category = "drawing")
11154    public float getX() {
11155        return mLeft + getTranslationX();
11156    }
11157
11158    /**
11159     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11160     * {@link #setTranslationX(float) translationX} property to be the difference between
11161     * the x value passed in and the current {@link #getLeft() left} property.
11162     *
11163     * @param x The visual x position of this view, in pixels.
11164     */
11165    public void setX(float x) {
11166        setTranslationX(x - mLeft);
11167    }
11168
11169    /**
11170     * The visual y position of this view, in pixels. This is equivalent to the
11171     * {@link #setTranslationY(float) translationY} property plus the current
11172     * {@link #getTop() top} property.
11173     *
11174     * @return The visual y position of this view, in pixels.
11175     */
11176    @ViewDebug.ExportedProperty(category = "drawing")
11177    public float getY() {
11178        return mTop + getTranslationY();
11179    }
11180
11181    /**
11182     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11183     * {@link #setTranslationY(float) translationY} property to be the difference between
11184     * the y value passed in and the current {@link #getTop() top} property.
11185     *
11186     * @param y The visual y position of this view, in pixels.
11187     */
11188    public void setY(float y) {
11189        setTranslationY(y - mTop);
11190    }
11191
11192    /**
11193     * The visual z position of this view, in pixels. This is equivalent to the
11194     * {@link #setTranslationZ(float) translationZ} property plus the current
11195     * {@link #getElevation() elevation} property.
11196     *
11197     * @return The visual z position of this view, in pixels.
11198     */
11199    @ViewDebug.ExportedProperty(category = "drawing")
11200    public float getZ() {
11201        return getElevation() + getTranslationZ();
11202    }
11203
11204    /**
11205     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11206     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11207     * the x value passed in and the current {@link #getElevation() elevation} property.
11208     *
11209     * @param z The visual z position of this view, in pixels.
11210     */
11211    public void setZ(float z) {
11212        setTranslationZ(z - getElevation());
11213    }
11214
11215    /**
11216     * The base elevation of this view relative to its parent, in pixels.
11217     *
11218     * @return The base depth position of the view, in pixels.
11219     */
11220    @ViewDebug.ExportedProperty(category = "drawing")
11221    public float getElevation() {
11222        return mRenderNode.getElevation();
11223    }
11224
11225    /**
11226     * Sets the base elevation of this view, in pixels.
11227     *
11228     * @attr ref android.R.styleable#View_elevation
11229     */
11230    public void setElevation(float elevation) {
11231        if (elevation != getElevation()) {
11232            invalidateViewProperty(true, false);
11233            mRenderNode.setElevation(elevation);
11234            invalidateViewProperty(false, true);
11235
11236            invalidateParentIfNeededAndWasQuickRejected();
11237        }
11238    }
11239
11240    /**
11241     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11242     * This position is post-layout, in addition to wherever the object's
11243     * layout placed it.
11244     *
11245     * @return The horizontal position of this view relative to its left position, in pixels.
11246     */
11247    @ViewDebug.ExportedProperty(category = "drawing")
11248    public float getTranslationX() {
11249        return mRenderNode.getTranslationX();
11250    }
11251
11252    /**
11253     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11254     * This effectively positions the object post-layout, in addition to wherever the object's
11255     * layout placed it.
11256     *
11257     * @param translationX The horizontal position of this view relative to its left position,
11258     * in pixels.
11259     *
11260     * @attr ref android.R.styleable#View_translationX
11261     */
11262    public void setTranslationX(float translationX) {
11263        if (translationX != getTranslationX()) {
11264            invalidateViewProperty(true, false);
11265            mRenderNode.setTranslationX(translationX);
11266            invalidateViewProperty(false, true);
11267
11268            invalidateParentIfNeededAndWasQuickRejected();
11269            notifySubtreeAccessibilityStateChangedIfNeeded();
11270        }
11271    }
11272
11273    /**
11274     * The vertical location of this view relative to its {@link #getTop() top} position.
11275     * This position is post-layout, in addition to wherever the object's
11276     * layout placed it.
11277     *
11278     * @return The vertical position of this view relative to its top position,
11279     * in pixels.
11280     */
11281    @ViewDebug.ExportedProperty(category = "drawing")
11282    public float getTranslationY() {
11283        return mRenderNode.getTranslationY();
11284    }
11285
11286    /**
11287     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11288     * This effectively positions the object post-layout, in addition to wherever the object's
11289     * layout placed it.
11290     *
11291     * @param translationY The vertical position of this view relative to its top position,
11292     * in pixels.
11293     *
11294     * @attr ref android.R.styleable#View_translationY
11295     */
11296    public void setTranslationY(float translationY) {
11297        if (translationY != getTranslationY()) {
11298            invalidateViewProperty(true, false);
11299            mRenderNode.setTranslationY(translationY);
11300            invalidateViewProperty(false, true);
11301
11302            invalidateParentIfNeededAndWasQuickRejected();
11303            notifySubtreeAccessibilityStateChangedIfNeeded();
11304        }
11305    }
11306
11307    /**
11308     * The depth location of this view relative to its {@link #getElevation() elevation}.
11309     *
11310     * @return The depth of this view relative to its elevation.
11311     */
11312    @ViewDebug.ExportedProperty(category = "drawing")
11313    public float getTranslationZ() {
11314        return mRenderNode.getTranslationZ();
11315    }
11316
11317    /**
11318     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11319     *
11320     * @attr ref android.R.styleable#View_translationZ
11321     */
11322    public void setTranslationZ(float translationZ) {
11323        if (translationZ != getTranslationZ()) {
11324            invalidateViewProperty(true, false);
11325            mRenderNode.setTranslationZ(translationZ);
11326            invalidateViewProperty(false, true);
11327
11328            invalidateParentIfNeededAndWasQuickRejected();
11329        }
11330    }
11331
11332    /** @hide */
11333    public void setAnimationMatrix(Matrix matrix) {
11334        invalidateViewProperty(true, false);
11335        mRenderNode.setAnimationMatrix(matrix);
11336        invalidateViewProperty(false, true);
11337
11338        invalidateParentIfNeededAndWasQuickRejected();
11339    }
11340
11341    /**
11342     * Returns the current StateListAnimator if exists.
11343     *
11344     * @return StateListAnimator or null if it does not exists
11345     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11346     */
11347    public StateListAnimator getStateListAnimator() {
11348        return mStateListAnimator;
11349    }
11350
11351    /**
11352     * Attaches the provided StateListAnimator to this View.
11353     * <p>
11354     * Any previously attached StateListAnimator will be detached.
11355     *
11356     * @param stateListAnimator The StateListAnimator to update the view
11357     * @see {@link android.animation.StateListAnimator}
11358     */
11359    public void setStateListAnimator(StateListAnimator stateListAnimator) {
11360        if (mStateListAnimator == stateListAnimator) {
11361            return;
11362        }
11363        if (mStateListAnimator != null) {
11364            mStateListAnimator.setTarget(null);
11365        }
11366        mStateListAnimator = stateListAnimator;
11367        if (stateListAnimator != null) {
11368            stateListAnimator.setTarget(this);
11369            if (isAttachedToWindow()) {
11370                stateListAnimator.setState(getDrawableState());
11371            }
11372        }
11373    }
11374
11375    /**
11376     * Returns whether the Outline should be used to clip the contents of the View.
11377     * <p>
11378     * Note that this flag will only be respected if the View's Outline returns true from
11379     * {@link Outline#canClip()}.
11380     *
11381     * @see #setOutlineProvider(ViewOutlineProvider)
11382     * @see #setClipToOutline(boolean)
11383     */
11384    public final boolean getClipToOutline() {
11385        return mRenderNode.getClipToOutline();
11386    }
11387
11388    /**
11389     * Sets whether the View's Outline should be used to clip the contents of the View.
11390     * <p>
11391     * Only a single non-rectangular clip can be applied on a View at any time.
11392     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
11393     * circular reveal} animation take priority over Outline clipping, and
11394     * child Outline clipping takes priority over Outline clipping done by a
11395     * parent.
11396     * <p>
11397     * Note that this flag will only be respected if the View's Outline returns true from
11398     * {@link Outline#canClip()}.
11399     *
11400     * @see #setOutlineProvider(ViewOutlineProvider)
11401     * @see #getClipToOutline()
11402     */
11403    public void setClipToOutline(boolean clipToOutline) {
11404        damageInParent();
11405        if (getClipToOutline() != clipToOutline) {
11406            mRenderNode.setClipToOutline(clipToOutline);
11407        }
11408    }
11409
11410    // correspond to the enum values of View_outlineProvider
11411    private static final int PROVIDER_BACKGROUND = 0;
11412    private static final int PROVIDER_NONE = 1;
11413    private static final int PROVIDER_BOUNDS = 2;
11414    private static final int PROVIDER_PADDED_BOUNDS = 3;
11415    private void setOutlineProviderFromAttribute(int providerInt) {
11416        switch (providerInt) {
11417            case PROVIDER_BACKGROUND:
11418                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
11419                break;
11420            case PROVIDER_NONE:
11421                setOutlineProvider(null);
11422                break;
11423            case PROVIDER_BOUNDS:
11424                setOutlineProvider(ViewOutlineProvider.BOUNDS);
11425                break;
11426            case PROVIDER_PADDED_BOUNDS:
11427                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
11428                break;
11429        }
11430    }
11431
11432    /**
11433     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
11434     * the shape of the shadow it casts, and enables outline clipping.
11435     * <p>
11436     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
11437     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
11438     * outline provider with this method allows this behavior to be overridden.
11439     * <p>
11440     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
11441     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
11442     * <p>
11443     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
11444     *
11445     * @see #setClipToOutline(boolean)
11446     * @see #getClipToOutline()
11447     * @see #getOutlineProvider()
11448     */
11449    public void setOutlineProvider(ViewOutlineProvider provider) {
11450        mOutlineProvider = provider;
11451        invalidateOutline();
11452    }
11453
11454    /**
11455     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
11456     * that defines the shape of the shadow it casts, and enables outline clipping.
11457     *
11458     * @see #setOutlineProvider(ViewOutlineProvider)
11459     */
11460    public ViewOutlineProvider getOutlineProvider() {
11461        return mOutlineProvider;
11462    }
11463
11464    /**
11465     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
11466     *
11467     * @see #setOutlineProvider(ViewOutlineProvider)
11468     */
11469    public void invalidateOutline() {
11470        rebuildOutline();
11471
11472        notifySubtreeAccessibilityStateChangedIfNeeded();
11473        invalidateViewProperty(false, false);
11474    }
11475
11476    /**
11477     * Internal version of {@link #invalidateOutline()} which invalidates the
11478     * outline without invalidating the view itself. This is intended to be called from
11479     * within methods in the View class itself which are the result of the view being
11480     * invalidated already. For example, when we are drawing the background of a View,
11481     * we invalidate the outline in case it changed in the meantime, but we do not
11482     * need to invalidate the view because we're already drawing the background as part
11483     * of drawing the view in response to an earlier invalidation of the view.
11484     */
11485    private void rebuildOutline() {
11486        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
11487        if (mAttachInfo == null) return;
11488
11489        if (mOutlineProvider == null) {
11490            // no provider, remove outline
11491            mRenderNode.setOutline(null);
11492        } else {
11493            final Outline outline = mAttachInfo.mTmpOutline;
11494            outline.setEmpty();
11495            outline.setAlpha(1.0f);
11496
11497            mOutlineProvider.getOutline(this, outline);
11498            mRenderNode.setOutline(outline);
11499        }
11500    }
11501
11502    /**
11503     * HierarchyViewer only
11504     *
11505     * @hide
11506     */
11507    @ViewDebug.ExportedProperty(category = "drawing")
11508    public boolean hasShadow() {
11509        return mRenderNode.hasShadow();
11510    }
11511
11512
11513    /** @hide */
11514    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
11515        mRenderNode.setRevealClip(shouldClip, x, y, radius);
11516        invalidateViewProperty(false, false);
11517    }
11518
11519    /**
11520     * Hit rectangle in parent's coordinates
11521     *
11522     * @param outRect The hit rectangle of the view.
11523     */
11524    public void getHitRect(Rect outRect) {
11525        if (hasIdentityMatrix() || mAttachInfo == null) {
11526            outRect.set(mLeft, mTop, mRight, mBottom);
11527        } else {
11528            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
11529            tmpRect.set(0, 0, getWidth(), getHeight());
11530            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
11531            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
11532                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
11533        }
11534    }
11535
11536    /**
11537     * Determines whether the given point, in local coordinates is inside the view.
11538     */
11539    /*package*/ final boolean pointInView(float localX, float localY) {
11540        return localX >= 0 && localX < (mRight - mLeft)
11541                && localY >= 0 && localY < (mBottom - mTop);
11542    }
11543
11544    /**
11545     * Utility method to determine whether the given point, in local coordinates,
11546     * is inside the view, where the area of the view is expanded by the slop factor.
11547     * This method is called while processing touch-move events to determine if the event
11548     * is still within the view.
11549     *
11550     * @hide
11551     */
11552    public boolean pointInView(float localX, float localY, float slop) {
11553        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
11554                localY < ((mBottom - mTop) + slop);
11555    }
11556
11557    /**
11558     * When a view has focus and the user navigates away from it, the next view is searched for
11559     * starting from the rectangle filled in by this method.
11560     *
11561     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
11562     * of the view.  However, if your view maintains some idea of internal selection,
11563     * such as a cursor, or a selected row or column, you should override this method and
11564     * fill in a more specific rectangle.
11565     *
11566     * @param r The rectangle to fill in, in this view's coordinates.
11567     */
11568    public void getFocusedRect(Rect r) {
11569        getDrawingRect(r);
11570    }
11571
11572    /**
11573     * If some part of this view is not clipped by any of its parents, then
11574     * return that area in r in global (root) coordinates. To convert r to local
11575     * coordinates (without taking possible View rotations into account), offset
11576     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
11577     * If the view is completely clipped or translated out, return false.
11578     *
11579     * @param r If true is returned, r holds the global coordinates of the
11580     *        visible portion of this view.
11581     * @param globalOffset If true is returned, globalOffset holds the dx,dy
11582     *        between this view and its root. globalOffet may be null.
11583     * @return true if r is non-empty (i.e. part of the view is visible at the
11584     *         root level.
11585     */
11586    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
11587        int width = mRight - mLeft;
11588        int height = mBottom - mTop;
11589        if (width > 0 && height > 0) {
11590            r.set(0, 0, width, height);
11591            if (globalOffset != null) {
11592                globalOffset.set(-mScrollX, -mScrollY);
11593            }
11594            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
11595        }
11596        return false;
11597    }
11598
11599    public final boolean getGlobalVisibleRect(Rect r) {
11600        return getGlobalVisibleRect(r, null);
11601    }
11602
11603    public final boolean getLocalVisibleRect(Rect r) {
11604        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
11605        if (getGlobalVisibleRect(r, offset)) {
11606            r.offset(-offset.x, -offset.y); // make r local
11607            return true;
11608        }
11609        return false;
11610    }
11611
11612    /**
11613     * Offset this view's vertical location by the specified number of pixels.
11614     *
11615     * @param offset the number of pixels to offset the view by
11616     */
11617    public void offsetTopAndBottom(int offset) {
11618        if (offset != 0) {
11619            final boolean matrixIsIdentity = hasIdentityMatrix();
11620            if (matrixIsIdentity) {
11621                if (isHardwareAccelerated()) {
11622                    invalidateViewProperty(false, false);
11623                } else {
11624                    final ViewParent p = mParent;
11625                    if (p != null && mAttachInfo != null) {
11626                        final Rect r = mAttachInfo.mTmpInvalRect;
11627                        int minTop;
11628                        int maxBottom;
11629                        int yLoc;
11630                        if (offset < 0) {
11631                            minTop = mTop + offset;
11632                            maxBottom = mBottom;
11633                            yLoc = offset;
11634                        } else {
11635                            minTop = mTop;
11636                            maxBottom = mBottom + offset;
11637                            yLoc = 0;
11638                        }
11639                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
11640                        p.invalidateChild(this, r);
11641                    }
11642                }
11643            } else {
11644                invalidateViewProperty(false, false);
11645            }
11646
11647            mTop += offset;
11648            mBottom += offset;
11649            mRenderNode.offsetTopAndBottom(offset);
11650            if (isHardwareAccelerated()) {
11651                invalidateViewProperty(false, false);
11652            } else {
11653                if (!matrixIsIdentity) {
11654                    invalidateViewProperty(false, true);
11655                }
11656                invalidateParentIfNeeded();
11657            }
11658            notifySubtreeAccessibilityStateChangedIfNeeded();
11659        }
11660    }
11661
11662    /**
11663     * Offset this view's horizontal location by the specified amount of pixels.
11664     *
11665     * @param offset the number of pixels to offset the view by
11666     */
11667    public void offsetLeftAndRight(int offset) {
11668        if (offset != 0) {
11669            final boolean matrixIsIdentity = hasIdentityMatrix();
11670            if (matrixIsIdentity) {
11671                if (isHardwareAccelerated()) {
11672                    invalidateViewProperty(false, false);
11673                } else {
11674                    final ViewParent p = mParent;
11675                    if (p != null && mAttachInfo != null) {
11676                        final Rect r = mAttachInfo.mTmpInvalRect;
11677                        int minLeft;
11678                        int maxRight;
11679                        if (offset < 0) {
11680                            minLeft = mLeft + offset;
11681                            maxRight = mRight;
11682                        } else {
11683                            minLeft = mLeft;
11684                            maxRight = mRight + offset;
11685                        }
11686                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
11687                        p.invalidateChild(this, r);
11688                    }
11689                }
11690            } else {
11691                invalidateViewProperty(false, false);
11692            }
11693
11694            mLeft += offset;
11695            mRight += offset;
11696            mRenderNode.offsetLeftAndRight(offset);
11697            if (isHardwareAccelerated()) {
11698                invalidateViewProperty(false, false);
11699            } else {
11700                if (!matrixIsIdentity) {
11701                    invalidateViewProperty(false, true);
11702                }
11703                invalidateParentIfNeeded();
11704            }
11705            notifySubtreeAccessibilityStateChangedIfNeeded();
11706        }
11707    }
11708
11709    /**
11710     * Get the LayoutParams associated with this view. All views should have
11711     * layout parameters. These supply parameters to the <i>parent</i> of this
11712     * view specifying how it should be arranged. There are many subclasses of
11713     * ViewGroup.LayoutParams, and these correspond to the different subclasses
11714     * of ViewGroup that are responsible for arranging their children.
11715     *
11716     * This method may return null if this View is not attached to a parent
11717     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
11718     * was not invoked successfully. When a View is attached to a parent
11719     * ViewGroup, this method must not return null.
11720     *
11721     * @return The LayoutParams associated with this view, or null if no
11722     *         parameters have been set yet
11723     */
11724    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
11725    public ViewGroup.LayoutParams getLayoutParams() {
11726        return mLayoutParams;
11727    }
11728
11729    /**
11730     * Set the layout parameters associated with this view. These supply
11731     * parameters to the <i>parent</i> of this view specifying how it should be
11732     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
11733     * correspond to the different subclasses of ViewGroup that are responsible
11734     * for arranging their children.
11735     *
11736     * @param params The layout parameters for this view, cannot be null
11737     */
11738    public void setLayoutParams(ViewGroup.LayoutParams params) {
11739        if (params == null) {
11740            throw new NullPointerException("Layout parameters cannot be null");
11741        }
11742        mLayoutParams = params;
11743        resolveLayoutParams();
11744        if (mParent instanceof ViewGroup) {
11745            ((ViewGroup) mParent).onSetLayoutParams(this, params);
11746        }
11747        requestLayout();
11748    }
11749
11750    /**
11751     * Resolve the layout parameters depending on the resolved layout direction
11752     *
11753     * @hide
11754     */
11755    public void resolveLayoutParams() {
11756        if (mLayoutParams != null) {
11757            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
11758        }
11759    }
11760
11761    /**
11762     * Set the scrolled position of your view. This will cause a call to
11763     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11764     * invalidated.
11765     * @param x the x position to scroll to
11766     * @param y the y position to scroll to
11767     */
11768    public void scrollTo(int x, int y) {
11769        if (mScrollX != x || mScrollY != y) {
11770            int oldX = mScrollX;
11771            int oldY = mScrollY;
11772            mScrollX = x;
11773            mScrollY = y;
11774            invalidateParentCaches();
11775            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
11776            if (!awakenScrollBars()) {
11777                postInvalidateOnAnimation();
11778            }
11779        }
11780    }
11781
11782    /**
11783     * Move the scrolled position of your view. This will cause a call to
11784     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11785     * invalidated.
11786     * @param x the amount of pixels to scroll by horizontally
11787     * @param y the amount of pixels to scroll by vertically
11788     */
11789    public void scrollBy(int x, int y) {
11790        scrollTo(mScrollX + x, mScrollY + y);
11791    }
11792
11793    /**
11794     * <p>Trigger the scrollbars to draw. When invoked this method starts an
11795     * animation to fade the scrollbars out after a default delay. If a subclass
11796     * provides animated scrolling, the start delay should equal the duration
11797     * of the scrolling animation.</p>
11798     *
11799     * <p>The animation starts only if at least one of the scrollbars is
11800     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
11801     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11802     * this method returns true, and false otherwise. If the animation is
11803     * started, this method calls {@link #invalidate()}; in that case the
11804     * caller should not call {@link #invalidate()}.</p>
11805     *
11806     * <p>This method should be invoked every time a subclass directly updates
11807     * the scroll parameters.</p>
11808     *
11809     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
11810     * and {@link #scrollTo(int, int)}.</p>
11811     *
11812     * @return true if the animation is played, false otherwise
11813     *
11814     * @see #awakenScrollBars(int)
11815     * @see #scrollBy(int, int)
11816     * @see #scrollTo(int, int)
11817     * @see #isHorizontalScrollBarEnabled()
11818     * @see #isVerticalScrollBarEnabled()
11819     * @see #setHorizontalScrollBarEnabled(boolean)
11820     * @see #setVerticalScrollBarEnabled(boolean)
11821     */
11822    protected boolean awakenScrollBars() {
11823        return mScrollCache != null &&
11824                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
11825    }
11826
11827    /**
11828     * Trigger the scrollbars to draw.
11829     * This method differs from awakenScrollBars() only in its default duration.
11830     * initialAwakenScrollBars() will show the scroll bars for longer than
11831     * usual to give the user more of a chance to notice them.
11832     *
11833     * @return true if the animation is played, false otherwise.
11834     */
11835    private boolean initialAwakenScrollBars() {
11836        return mScrollCache != null &&
11837                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
11838    }
11839
11840    /**
11841     * <p>
11842     * Trigger the scrollbars to draw. When invoked this method starts an
11843     * animation to fade the scrollbars out after a fixed delay. If a subclass
11844     * provides animated scrolling, the start delay should equal the duration of
11845     * the scrolling animation.
11846     * </p>
11847     *
11848     * <p>
11849     * The animation starts only if at least one of the scrollbars is enabled,
11850     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11851     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11852     * this method returns true, and false otherwise. If the animation is
11853     * started, this method calls {@link #invalidate()}; in that case the caller
11854     * should not call {@link #invalidate()}.
11855     * </p>
11856     *
11857     * <p>
11858     * This method should be invoked every time a subclass directly updates the
11859     * scroll parameters.
11860     * </p>
11861     *
11862     * @param startDelay the delay, in milliseconds, after which the animation
11863     *        should start; when the delay is 0, the animation starts
11864     *        immediately
11865     * @return true if the animation is played, false otherwise
11866     *
11867     * @see #scrollBy(int, int)
11868     * @see #scrollTo(int, int)
11869     * @see #isHorizontalScrollBarEnabled()
11870     * @see #isVerticalScrollBarEnabled()
11871     * @see #setHorizontalScrollBarEnabled(boolean)
11872     * @see #setVerticalScrollBarEnabled(boolean)
11873     */
11874    protected boolean awakenScrollBars(int startDelay) {
11875        return awakenScrollBars(startDelay, true);
11876    }
11877
11878    /**
11879     * <p>
11880     * Trigger the scrollbars to draw. When invoked this method starts an
11881     * animation to fade the scrollbars out after a fixed delay. If a subclass
11882     * provides animated scrolling, the start delay should equal the duration of
11883     * the scrolling animation.
11884     * </p>
11885     *
11886     * <p>
11887     * The animation starts only if at least one of the scrollbars is enabled,
11888     * as specified by {@link #isHorizontalScrollBarEnabled()} and
11889     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
11890     * this method returns true, and false otherwise. If the animation is
11891     * started, this method calls {@link #invalidate()} if the invalidate parameter
11892     * is set to true; in that case the caller
11893     * should not call {@link #invalidate()}.
11894     * </p>
11895     *
11896     * <p>
11897     * This method should be invoked every time a subclass directly updates the
11898     * scroll parameters.
11899     * </p>
11900     *
11901     * @param startDelay the delay, in milliseconds, after which the animation
11902     *        should start; when the delay is 0, the animation starts
11903     *        immediately
11904     *
11905     * @param invalidate Whether this method should call invalidate
11906     *
11907     * @return true if the animation is played, false otherwise
11908     *
11909     * @see #scrollBy(int, int)
11910     * @see #scrollTo(int, int)
11911     * @see #isHorizontalScrollBarEnabled()
11912     * @see #isVerticalScrollBarEnabled()
11913     * @see #setHorizontalScrollBarEnabled(boolean)
11914     * @see #setVerticalScrollBarEnabled(boolean)
11915     */
11916    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
11917        final ScrollabilityCache scrollCache = mScrollCache;
11918
11919        if (scrollCache == null || !scrollCache.fadeScrollBars) {
11920            return false;
11921        }
11922
11923        if (scrollCache.scrollBar == null) {
11924            scrollCache.scrollBar = new ScrollBarDrawable();
11925            scrollCache.scrollBar.setCallback(this);
11926            scrollCache.scrollBar.setState(getDrawableState());
11927        }
11928
11929        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
11930
11931            if (invalidate) {
11932                // Invalidate to show the scrollbars
11933                postInvalidateOnAnimation();
11934            }
11935
11936            if (scrollCache.state == ScrollabilityCache.OFF) {
11937                // FIXME: this is copied from WindowManagerService.
11938                // We should get this value from the system when it
11939                // is possible to do so.
11940                final int KEY_REPEAT_FIRST_DELAY = 750;
11941                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
11942            }
11943
11944            // Tell mScrollCache when we should start fading. This may
11945            // extend the fade start time if one was already scheduled
11946            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
11947            scrollCache.fadeStartTime = fadeStartTime;
11948            scrollCache.state = ScrollabilityCache.ON;
11949
11950            // Schedule our fader to run, unscheduling any old ones first
11951            if (mAttachInfo != null) {
11952                mAttachInfo.mHandler.removeCallbacks(scrollCache);
11953                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
11954            }
11955
11956            return true;
11957        }
11958
11959        return false;
11960    }
11961
11962    /**
11963     * Do not invalidate views which are not visible and which are not running an animation. They
11964     * will not get drawn and they should not set dirty flags as if they will be drawn
11965     */
11966    private boolean skipInvalidate() {
11967        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
11968                (!(mParent instanceof ViewGroup) ||
11969                        !((ViewGroup) mParent).isViewTransitioning(this));
11970    }
11971
11972    /**
11973     * Mark the area defined by dirty as needing to be drawn. If the view is
11974     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11975     * point in the future.
11976     * <p>
11977     * This must be called from a UI thread. To call from a non-UI thread, call
11978     * {@link #postInvalidate()}.
11979     * <p>
11980     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
11981     * {@code dirty}.
11982     *
11983     * @param dirty the rectangle representing the bounds of the dirty region
11984     */
11985    public void invalidate(Rect dirty) {
11986        final int scrollX = mScrollX;
11987        final int scrollY = mScrollY;
11988        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
11989                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
11990    }
11991
11992    /**
11993     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
11994     * coordinates of the dirty rect are relative to the view. If the view is
11995     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
11996     * point in the future.
11997     * <p>
11998     * This must be called from a UI thread. To call from a non-UI thread, call
11999     * {@link #postInvalidate()}.
12000     *
12001     * @param l the left position of the dirty region
12002     * @param t the top position of the dirty region
12003     * @param r the right position of the dirty region
12004     * @param b the bottom position of the dirty region
12005     */
12006    public void invalidate(int l, int t, int r, int b) {
12007        final int scrollX = mScrollX;
12008        final int scrollY = mScrollY;
12009        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12010    }
12011
12012    /**
12013     * Invalidate the whole view. If the view is visible,
12014     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12015     * the future.
12016     * <p>
12017     * This must be called from a UI thread. To call from a non-UI thread, call
12018     * {@link #postInvalidate()}.
12019     */
12020    public void invalidate() {
12021        invalidate(true);
12022    }
12023
12024    /**
12025     * This is where the invalidate() work actually happens. A full invalidate()
12026     * causes the drawing cache to be invalidated, but this function can be
12027     * called with invalidateCache set to false to skip that invalidation step
12028     * for cases that do not need it (for example, a component that remains at
12029     * the same dimensions with the same content).
12030     *
12031     * @param invalidateCache Whether the drawing cache for this view should be
12032     *            invalidated as well. This is usually true for a full
12033     *            invalidate, but may be set to false if the View's contents or
12034     *            dimensions have not changed.
12035     */
12036    void invalidate(boolean invalidateCache) {
12037        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12038    }
12039
12040    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12041            boolean fullInvalidate) {
12042        if (mGhostView != null) {
12043            mGhostView.invalidate(true);
12044            return;
12045        }
12046
12047        if (skipInvalidate()) {
12048            return;
12049        }
12050
12051        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12052                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12053                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12054                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12055            if (fullInvalidate) {
12056                mLastIsOpaque = isOpaque();
12057                mPrivateFlags &= ~PFLAG_DRAWN;
12058            }
12059
12060            mPrivateFlags |= PFLAG_DIRTY;
12061
12062            if (invalidateCache) {
12063                mPrivateFlags |= PFLAG_INVALIDATED;
12064                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12065            }
12066
12067            // Propagate the damage rectangle to the parent view.
12068            final AttachInfo ai = mAttachInfo;
12069            final ViewParent p = mParent;
12070            if (p != null && ai != null && l < r && t < b) {
12071                final Rect damage = ai.mTmpInvalRect;
12072                damage.set(l, t, r, b);
12073                p.invalidateChild(this, damage);
12074            }
12075
12076            // Damage the entire projection receiver, if necessary.
12077            if (mBackground != null && mBackground.isProjected()) {
12078                final View receiver = getProjectionReceiver();
12079                if (receiver != null) {
12080                    receiver.damageInParent();
12081                }
12082            }
12083
12084            // Damage the entire IsolatedZVolume receiving this view's shadow.
12085            if (isHardwareAccelerated() && getZ() != 0) {
12086                damageShadowReceiver();
12087            }
12088        }
12089    }
12090
12091    /**
12092     * @return this view's projection receiver, or {@code null} if none exists
12093     */
12094    private View getProjectionReceiver() {
12095        ViewParent p = getParent();
12096        while (p != null && p instanceof View) {
12097            final View v = (View) p;
12098            if (v.isProjectionReceiver()) {
12099                return v;
12100            }
12101            p = p.getParent();
12102        }
12103
12104        return null;
12105    }
12106
12107    /**
12108     * @return whether the view is a projection receiver
12109     */
12110    private boolean isProjectionReceiver() {
12111        return mBackground != null;
12112    }
12113
12114    /**
12115     * Damage area of the screen that can be covered by this View's shadow.
12116     *
12117     * This method will guarantee that any changes to shadows cast by a View
12118     * are damaged on the screen for future redraw.
12119     */
12120    private void damageShadowReceiver() {
12121        final AttachInfo ai = mAttachInfo;
12122        if (ai != null) {
12123            ViewParent p = getParent();
12124            if (p != null && p instanceof ViewGroup) {
12125                final ViewGroup vg = (ViewGroup) p;
12126                vg.damageInParent();
12127            }
12128        }
12129    }
12130
12131    /**
12132     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12133     * set any flags or handle all of the cases handled by the default invalidation methods.
12134     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12135     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12136     * walk up the hierarchy, transforming the dirty rect as necessary.
12137     *
12138     * The method also handles normal invalidation logic if display list properties are not
12139     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12140     * backup approach, to handle these cases used in the various property-setting methods.
12141     *
12142     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12143     * are not being used in this view
12144     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12145     * list properties are not being used in this view
12146     */
12147    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12148        if (!isHardwareAccelerated()
12149                || !mRenderNode.isValid()
12150                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12151            if (invalidateParent) {
12152                invalidateParentCaches();
12153            }
12154            if (forceRedraw) {
12155                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12156            }
12157            invalidate(false);
12158        } else {
12159            damageInParent();
12160        }
12161        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12162            damageShadowReceiver();
12163        }
12164    }
12165
12166    /**
12167     * Tells the parent view to damage this view's bounds.
12168     *
12169     * @hide
12170     */
12171    protected void damageInParent() {
12172        final AttachInfo ai = mAttachInfo;
12173        final ViewParent p = mParent;
12174        if (p != null && ai != null) {
12175            final Rect r = ai.mTmpInvalRect;
12176            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12177            if (mParent instanceof ViewGroup) {
12178                ((ViewGroup) mParent).damageChild(this, r);
12179            } else {
12180                mParent.invalidateChild(this, r);
12181            }
12182        }
12183    }
12184
12185    /**
12186     * Utility method to transform a given Rect by the current matrix of this view.
12187     */
12188    void transformRect(final Rect rect) {
12189        if (!getMatrix().isIdentity()) {
12190            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12191            boundingRect.set(rect);
12192            getMatrix().mapRect(boundingRect);
12193            rect.set((int) Math.floor(boundingRect.left),
12194                    (int) Math.floor(boundingRect.top),
12195                    (int) Math.ceil(boundingRect.right),
12196                    (int) Math.ceil(boundingRect.bottom));
12197        }
12198    }
12199
12200    /**
12201     * Used to indicate that the parent of this view should clear its caches. This functionality
12202     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12203     * which is necessary when various parent-managed properties of the view change, such as
12204     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12205     * clears the parent caches and does not causes an invalidate event.
12206     *
12207     * @hide
12208     */
12209    protected void invalidateParentCaches() {
12210        if (mParent instanceof View) {
12211            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12212        }
12213    }
12214
12215    /**
12216     * Used to indicate that the parent of this view should be invalidated. This functionality
12217     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12218     * which is necessary when various parent-managed properties of the view change, such as
12219     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12220     * an invalidation event to the parent.
12221     *
12222     * @hide
12223     */
12224    protected void invalidateParentIfNeeded() {
12225        if (isHardwareAccelerated() && mParent instanceof View) {
12226            ((View) mParent).invalidate(true);
12227        }
12228    }
12229
12230    /**
12231     * @hide
12232     */
12233    protected void invalidateParentIfNeededAndWasQuickRejected() {
12234        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12235            // View was rejected last time it was drawn by its parent; this may have changed
12236            invalidateParentIfNeeded();
12237        }
12238    }
12239
12240    /**
12241     * Indicates whether this View is opaque. An opaque View guarantees that it will
12242     * draw all the pixels overlapping its bounds using a fully opaque color.
12243     *
12244     * Subclasses of View should override this method whenever possible to indicate
12245     * whether an instance is opaque. Opaque Views are treated in a special way by
12246     * the View hierarchy, possibly allowing it to perform optimizations during
12247     * invalidate/draw passes.
12248     *
12249     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12250     */
12251    @ViewDebug.ExportedProperty(category = "drawing")
12252    public boolean isOpaque() {
12253        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12254                getFinalAlpha() >= 1.0f;
12255    }
12256
12257    /**
12258     * @hide
12259     */
12260    protected void computeOpaqueFlags() {
12261        // Opaque if:
12262        //   - Has a background
12263        //   - Background is opaque
12264        //   - Doesn't have scrollbars or scrollbars overlay
12265
12266        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12267            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12268        } else {
12269            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12270        }
12271
12272        final int flags = mViewFlags;
12273        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12274                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12275                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12276            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12277        } else {
12278            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12279        }
12280    }
12281
12282    /**
12283     * @hide
12284     */
12285    protected boolean hasOpaqueScrollbars() {
12286        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12287    }
12288
12289    /**
12290     * @return A handler associated with the thread running the View. This
12291     * handler can be used to pump events in the UI events queue.
12292     */
12293    public Handler getHandler() {
12294        final AttachInfo attachInfo = mAttachInfo;
12295        if (attachInfo != null) {
12296            return attachInfo.mHandler;
12297        }
12298        return null;
12299    }
12300
12301    /**
12302     * Gets the view root associated with the View.
12303     * @return The view root, or null if none.
12304     * @hide
12305     */
12306    public ViewRootImpl getViewRootImpl() {
12307        if (mAttachInfo != null) {
12308            return mAttachInfo.mViewRootImpl;
12309        }
12310        return null;
12311    }
12312
12313    /**
12314     * @hide
12315     */
12316    public HardwareRenderer getHardwareRenderer() {
12317        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12318    }
12319
12320    /**
12321     * <p>Causes the Runnable to be added to the message queue.
12322     * The runnable will be run on the user interface thread.</p>
12323     *
12324     * @param action The Runnable that will be executed.
12325     *
12326     * @return Returns true if the Runnable was successfully placed in to the
12327     *         message queue.  Returns false on failure, usually because the
12328     *         looper processing the message queue is exiting.
12329     *
12330     * @see #postDelayed
12331     * @see #removeCallbacks
12332     */
12333    public boolean post(Runnable action) {
12334        final AttachInfo attachInfo = mAttachInfo;
12335        if (attachInfo != null) {
12336            return attachInfo.mHandler.post(action);
12337        }
12338        // Assume that post will succeed later
12339        ViewRootImpl.getRunQueue().post(action);
12340        return true;
12341    }
12342
12343    /**
12344     * <p>Causes the Runnable to be added to the message queue, to be run
12345     * after the specified amount of time elapses.
12346     * The runnable will be run on the user interface thread.</p>
12347     *
12348     * @param action The Runnable that will be executed.
12349     * @param delayMillis The delay (in milliseconds) until the Runnable
12350     *        will be executed.
12351     *
12352     * @return true if the Runnable was successfully placed in to the
12353     *         message queue.  Returns false on failure, usually because the
12354     *         looper processing the message queue is exiting.  Note that a
12355     *         result of true does not mean the Runnable will be processed --
12356     *         if the looper is quit before the delivery time of the message
12357     *         occurs then the message will be dropped.
12358     *
12359     * @see #post
12360     * @see #removeCallbacks
12361     */
12362    public boolean postDelayed(Runnable action, long delayMillis) {
12363        final AttachInfo attachInfo = mAttachInfo;
12364        if (attachInfo != null) {
12365            return attachInfo.mHandler.postDelayed(action, delayMillis);
12366        }
12367        // Assume that post will succeed later
12368        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12369        return true;
12370    }
12371
12372    /**
12373     * <p>Causes the Runnable to execute on the next animation time step.
12374     * The runnable will be run on the user interface thread.</p>
12375     *
12376     * @param action The Runnable that will be executed.
12377     *
12378     * @see #postOnAnimationDelayed
12379     * @see #removeCallbacks
12380     */
12381    public void postOnAnimation(Runnable action) {
12382        final AttachInfo attachInfo = mAttachInfo;
12383        if (attachInfo != null) {
12384            attachInfo.mViewRootImpl.mChoreographer.postCallback(
12385                    Choreographer.CALLBACK_ANIMATION, action, null);
12386        } else {
12387            // Assume that post will succeed later
12388            ViewRootImpl.getRunQueue().post(action);
12389        }
12390    }
12391
12392    /**
12393     * <p>Causes the Runnable to execute on the next animation time step,
12394     * after the specified amount of time elapses.
12395     * The runnable will be run on the user interface thread.</p>
12396     *
12397     * @param action The Runnable that will be executed.
12398     * @param delayMillis The delay (in milliseconds) until the Runnable
12399     *        will be executed.
12400     *
12401     * @see #postOnAnimation
12402     * @see #removeCallbacks
12403     */
12404    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
12405        final AttachInfo attachInfo = mAttachInfo;
12406        if (attachInfo != null) {
12407            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
12408                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
12409        } else {
12410            // Assume that post will succeed later
12411            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
12412        }
12413    }
12414
12415    /**
12416     * <p>Removes the specified Runnable from the message queue.</p>
12417     *
12418     * @param action The Runnable to remove from the message handling queue
12419     *
12420     * @return true if this view could ask the Handler to remove the Runnable,
12421     *         false otherwise. When the returned value is true, the Runnable
12422     *         may or may not have been actually removed from the message queue
12423     *         (for instance, if the Runnable was not in the queue already.)
12424     *
12425     * @see #post
12426     * @see #postDelayed
12427     * @see #postOnAnimation
12428     * @see #postOnAnimationDelayed
12429     */
12430    public boolean removeCallbacks(Runnable action) {
12431        if (action != null) {
12432            final AttachInfo attachInfo = mAttachInfo;
12433            if (attachInfo != null) {
12434                attachInfo.mHandler.removeCallbacks(action);
12435                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
12436                        Choreographer.CALLBACK_ANIMATION, action, null);
12437            }
12438            // Assume that post will succeed later
12439            ViewRootImpl.getRunQueue().removeCallbacks(action);
12440        }
12441        return true;
12442    }
12443
12444    /**
12445     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
12446     * Use this to invalidate the View from a non-UI thread.</p>
12447     *
12448     * <p>This method can be invoked from outside of the UI thread
12449     * only when this View is attached to a window.</p>
12450     *
12451     * @see #invalidate()
12452     * @see #postInvalidateDelayed(long)
12453     */
12454    public void postInvalidate() {
12455        postInvalidateDelayed(0);
12456    }
12457
12458    /**
12459     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12460     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
12461     *
12462     * <p>This method can be invoked from outside of the UI thread
12463     * only when this View is attached to a window.</p>
12464     *
12465     * @param left The left coordinate of the rectangle to invalidate.
12466     * @param top The top coordinate of the rectangle to invalidate.
12467     * @param right The right coordinate of the rectangle to invalidate.
12468     * @param bottom The bottom coordinate of the rectangle to invalidate.
12469     *
12470     * @see #invalidate(int, int, int, int)
12471     * @see #invalidate(Rect)
12472     * @see #postInvalidateDelayed(long, int, int, int, int)
12473     */
12474    public void postInvalidate(int left, int top, int right, int bottom) {
12475        postInvalidateDelayed(0, left, top, right, bottom);
12476    }
12477
12478    /**
12479     * <p>Cause an invalidate to happen on a subsequent cycle through the event
12480     * loop. Waits for the specified amount of time.</p>
12481     *
12482     * <p>This method can be invoked from outside of the UI thread
12483     * only when this View is attached to a window.</p>
12484     *
12485     * @param delayMilliseconds the duration in milliseconds to delay the
12486     *         invalidation by
12487     *
12488     * @see #invalidate()
12489     * @see #postInvalidate()
12490     */
12491    public void postInvalidateDelayed(long delayMilliseconds) {
12492        // We try only with the AttachInfo because there's no point in invalidating
12493        // if we are not attached to our window
12494        final AttachInfo attachInfo = mAttachInfo;
12495        if (attachInfo != null) {
12496            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
12497        }
12498    }
12499
12500    /**
12501     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
12502     * through the event loop. Waits for the specified amount of time.</p>
12503     *
12504     * <p>This method can be invoked from outside of the UI thread
12505     * only when this View is attached to a window.</p>
12506     *
12507     * @param delayMilliseconds the duration in milliseconds to delay the
12508     *         invalidation by
12509     * @param left The left coordinate of the rectangle to invalidate.
12510     * @param top The top coordinate of the rectangle to invalidate.
12511     * @param right The right coordinate of the rectangle to invalidate.
12512     * @param bottom The bottom coordinate of the rectangle to invalidate.
12513     *
12514     * @see #invalidate(int, int, int, int)
12515     * @see #invalidate(Rect)
12516     * @see #postInvalidate(int, int, int, int)
12517     */
12518    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
12519            int right, int bottom) {
12520
12521        // We try only with the AttachInfo because there's no point in invalidating
12522        // if we are not attached to our window
12523        final AttachInfo attachInfo = mAttachInfo;
12524        if (attachInfo != null) {
12525            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12526            info.target = this;
12527            info.left = left;
12528            info.top = top;
12529            info.right = right;
12530            info.bottom = bottom;
12531
12532            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
12533        }
12534    }
12535
12536    /**
12537     * <p>Cause an invalidate to happen on the next animation time step, typically the
12538     * next display frame.</p>
12539     *
12540     * <p>This method can be invoked from outside of the UI thread
12541     * only when this View is attached to a window.</p>
12542     *
12543     * @see #invalidate()
12544     */
12545    public void postInvalidateOnAnimation() {
12546        // We try only with the AttachInfo because there's no point in invalidating
12547        // if we are not attached to our window
12548        final AttachInfo attachInfo = mAttachInfo;
12549        if (attachInfo != null) {
12550            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
12551        }
12552    }
12553
12554    /**
12555     * <p>Cause an invalidate of the specified area to happen on the next animation
12556     * time step, typically the next display frame.</p>
12557     *
12558     * <p>This method can be invoked from outside of the UI thread
12559     * only when this View is attached to a window.</p>
12560     *
12561     * @param left The left coordinate of the rectangle to invalidate.
12562     * @param top The top coordinate of the rectangle to invalidate.
12563     * @param right The right coordinate of the rectangle to invalidate.
12564     * @param bottom The bottom coordinate of the rectangle to invalidate.
12565     *
12566     * @see #invalidate(int, int, int, int)
12567     * @see #invalidate(Rect)
12568     */
12569    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
12570        // We try only with the AttachInfo because there's no point in invalidating
12571        // if we are not attached to our window
12572        final AttachInfo attachInfo = mAttachInfo;
12573        if (attachInfo != null) {
12574            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
12575            info.target = this;
12576            info.left = left;
12577            info.top = top;
12578            info.right = right;
12579            info.bottom = bottom;
12580
12581            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
12582        }
12583    }
12584
12585    /**
12586     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
12587     * This event is sent at most once every
12588     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
12589     */
12590    private void postSendViewScrolledAccessibilityEventCallback() {
12591        if (mSendViewScrolledAccessibilityEvent == null) {
12592            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
12593        }
12594        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
12595            mSendViewScrolledAccessibilityEvent.mIsPending = true;
12596            postDelayed(mSendViewScrolledAccessibilityEvent,
12597                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
12598        }
12599    }
12600
12601    /**
12602     * Called by a parent to request that a child update its values for mScrollX
12603     * and mScrollY if necessary. This will typically be done if the child is
12604     * animating a scroll using a {@link android.widget.Scroller Scroller}
12605     * object.
12606     */
12607    public void computeScroll() {
12608    }
12609
12610    /**
12611     * <p>Indicate whether the horizontal edges are faded when the view is
12612     * scrolled horizontally.</p>
12613     *
12614     * @return true if the horizontal edges should are faded on scroll, false
12615     *         otherwise
12616     *
12617     * @see #setHorizontalFadingEdgeEnabled(boolean)
12618     *
12619     * @attr ref android.R.styleable#View_requiresFadingEdge
12620     */
12621    public boolean isHorizontalFadingEdgeEnabled() {
12622        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
12623    }
12624
12625    /**
12626     * <p>Define whether the horizontal edges should be faded when this view
12627     * is scrolled horizontally.</p>
12628     *
12629     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
12630     *                                    be faded when the view is scrolled
12631     *                                    horizontally
12632     *
12633     * @see #isHorizontalFadingEdgeEnabled()
12634     *
12635     * @attr ref android.R.styleable#View_requiresFadingEdge
12636     */
12637    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
12638        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
12639            if (horizontalFadingEdgeEnabled) {
12640                initScrollCache();
12641            }
12642
12643            mViewFlags ^= FADING_EDGE_HORIZONTAL;
12644        }
12645    }
12646
12647    /**
12648     * <p>Indicate whether the vertical edges are faded when the view is
12649     * scrolled horizontally.</p>
12650     *
12651     * @return true if the vertical edges should are faded on scroll, false
12652     *         otherwise
12653     *
12654     * @see #setVerticalFadingEdgeEnabled(boolean)
12655     *
12656     * @attr ref android.R.styleable#View_requiresFadingEdge
12657     */
12658    public boolean isVerticalFadingEdgeEnabled() {
12659        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
12660    }
12661
12662    /**
12663     * <p>Define whether the vertical edges should be faded when this view
12664     * is scrolled vertically.</p>
12665     *
12666     * @param verticalFadingEdgeEnabled true if the vertical edges should
12667     *                                  be faded when the view is scrolled
12668     *                                  vertically
12669     *
12670     * @see #isVerticalFadingEdgeEnabled()
12671     *
12672     * @attr ref android.R.styleable#View_requiresFadingEdge
12673     */
12674    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
12675        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
12676            if (verticalFadingEdgeEnabled) {
12677                initScrollCache();
12678            }
12679
12680            mViewFlags ^= FADING_EDGE_VERTICAL;
12681        }
12682    }
12683
12684    /**
12685     * Returns the strength, or intensity, of the top faded edge. The strength is
12686     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12687     * returns 0.0 or 1.0 but no value in between.
12688     *
12689     * Subclasses should override this method to provide a smoother fade transition
12690     * when scrolling occurs.
12691     *
12692     * @return the intensity of the top fade as a float between 0.0f and 1.0f
12693     */
12694    protected float getTopFadingEdgeStrength() {
12695        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
12696    }
12697
12698    /**
12699     * Returns the strength, or intensity, of the bottom faded edge. The strength is
12700     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12701     * returns 0.0 or 1.0 but no value in between.
12702     *
12703     * Subclasses should override this method to provide a smoother fade transition
12704     * when scrolling occurs.
12705     *
12706     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
12707     */
12708    protected float getBottomFadingEdgeStrength() {
12709        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
12710                computeVerticalScrollRange() ? 1.0f : 0.0f;
12711    }
12712
12713    /**
12714     * Returns the strength, or intensity, of the left faded edge. The strength is
12715     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12716     * returns 0.0 or 1.0 but no value in between.
12717     *
12718     * Subclasses should override this method to provide a smoother fade transition
12719     * when scrolling occurs.
12720     *
12721     * @return the intensity of the left fade as a float between 0.0f and 1.0f
12722     */
12723    protected float getLeftFadingEdgeStrength() {
12724        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
12725    }
12726
12727    /**
12728     * Returns the strength, or intensity, of the right faded edge. The strength is
12729     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
12730     * returns 0.0 or 1.0 but no value in between.
12731     *
12732     * Subclasses should override this method to provide a smoother fade transition
12733     * when scrolling occurs.
12734     *
12735     * @return the intensity of the right fade as a float between 0.0f and 1.0f
12736     */
12737    protected float getRightFadingEdgeStrength() {
12738        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
12739                computeHorizontalScrollRange() ? 1.0f : 0.0f;
12740    }
12741
12742    /**
12743     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
12744     * scrollbar is not drawn by default.</p>
12745     *
12746     * @return true if the horizontal scrollbar should be painted, false
12747     *         otherwise
12748     *
12749     * @see #setHorizontalScrollBarEnabled(boolean)
12750     */
12751    public boolean isHorizontalScrollBarEnabled() {
12752        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
12753    }
12754
12755    /**
12756     * <p>Define whether the horizontal scrollbar should be drawn or not. The
12757     * scrollbar is not drawn by default.</p>
12758     *
12759     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
12760     *                                   be painted
12761     *
12762     * @see #isHorizontalScrollBarEnabled()
12763     */
12764    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
12765        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
12766            mViewFlags ^= SCROLLBARS_HORIZONTAL;
12767            computeOpaqueFlags();
12768            resolvePadding();
12769        }
12770    }
12771
12772    /**
12773     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
12774     * scrollbar is not drawn by default.</p>
12775     *
12776     * @return true if the vertical scrollbar should be painted, false
12777     *         otherwise
12778     *
12779     * @see #setVerticalScrollBarEnabled(boolean)
12780     */
12781    public boolean isVerticalScrollBarEnabled() {
12782        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
12783    }
12784
12785    /**
12786     * <p>Define whether the vertical scrollbar should be drawn or not. The
12787     * scrollbar is not drawn by default.</p>
12788     *
12789     * @param verticalScrollBarEnabled true if the vertical scrollbar should
12790     *                                 be painted
12791     *
12792     * @see #isVerticalScrollBarEnabled()
12793     */
12794    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
12795        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
12796            mViewFlags ^= SCROLLBARS_VERTICAL;
12797            computeOpaqueFlags();
12798            resolvePadding();
12799        }
12800    }
12801
12802    /**
12803     * @hide
12804     */
12805    protected void recomputePadding() {
12806        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
12807    }
12808
12809    /**
12810     * Define whether scrollbars will fade when the view is not scrolling.
12811     *
12812     * @param fadeScrollbars whether to enable fading
12813     *
12814     * @attr ref android.R.styleable#View_fadeScrollbars
12815     */
12816    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
12817        initScrollCache();
12818        final ScrollabilityCache scrollabilityCache = mScrollCache;
12819        scrollabilityCache.fadeScrollBars = fadeScrollbars;
12820        if (fadeScrollbars) {
12821            scrollabilityCache.state = ScrollabilityCache.OFF;
12822        } else {
12823            scrollabilityCache.state = ScrollabilityCache.ON;
12824        }
12825    }
12826
12827    /**
12828     *
12829     * Returns true if scrollbars will fade when this view is not scrolling
12830     *
12831     * @return true if scrollbar fading is enabled
12832     *
12833     * @attr ref android.R.styleable#View_fadeScrollbars
12834     */
12835    public boolean isScrollbarFadingEnabled() {
12836        return mScrollCache != null && mScrollCache.fadeScrollBars;
12837    }
12838
12839    /**
12840     *
12841     * Returns the delay before scrollbars fade.
12842     *
12843     * @return the delay before scrollbars fade
12844     *
12845     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12846     */
12847    public int getScrollBarDefaultDelayBeforeFade() {
12848        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
12849                mScrollCache.scrollBarDefaultDelayBeforeFade;
12850    }
12851
12852    /**
12853     * Define the delay before scrollbars fade.
12854     *
12855     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
12856     *
12857     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
12858     */
12859    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
12860        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
12861    }
12862
12863    /**
12864     *
12865     * Returns the scrollbar fade duration.
12866     *
12867     * @return the scrollbar fade duration
12868     *
12869     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12870     */
12871    public int getScrollBarFadeDuration() {
12872        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
12873                mScrollCache.scrollBarFadeDuration;
12874    }
12875
12876    /**
12877     * Define the scrollbar fade duration.
12878     *
12879     * @param scrollBarFadeDuration - the scrollbar fade duration
12880     *
12881     * @attr ref android.R.styleable#View_scrollbarFadeDuration
12882     */
12883    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
12884        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
12885    }
12886
12887    /**
12888     *
12889     * Returns the scrollbar size.
12890     *
12891     * @return the scrollbar size
12892     *
12893     * @attr ref android.R.styleable#View_scrollbarSize
12894     */
12895    public int getScrollBarSize() {
12896        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
12897                mScrollCache.scrollBarSize;
12898    }
12899
12900    /**
12901     * Define the scrollbar size.
12902     *
12903     * @param scrollBarSize - the scrollbar size
12904     *
12905     * @attr ref android.R.styleable#View_scrollbarSize
12906     */
12907    public void setScrollBarSize(int scrollBarSize) {
12908        getScrollCache().scrollBarSize = scrollBarSize;
12909    }
12910
12911    /**
12912     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
12913     * inset. When inset, they add to the padding of the view. And the scrollbars
12914     * can be drawn inside the padding area or on the edge of the view. For example,
12915     * if a view has a background drawable and you want to draw the scrollbars
12916     * inside the padding specified by the drawable, you can use
12917     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
12918     * appear at the edge of the view, ignoring the padding, then you can use
12919     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
12920     * @param style the style of the scrollbars. Should be one of
12921     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
12922     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
12923     * @see #SCROLLBARS_INSIDE_OVERLAY
12924     * @see #SCROLLBARS_INSIDE_INSET
12925     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12926     * @see #SCROLLBARS_OUTSIDE_INSET
12927     *
12928     * @attr ref android.R.styleable#View_scrollbarStyle
12929     */
12930    public void setScrollBarStyle(@ScrollBarStyle int style) {
12931        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
12932            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
12933            computeOpaqueFlags();
12934            resolvePadding();
12935        }
12936    }
12937
12938    /**
12939     * <p>Returns the current scrollbar style.</p>
12940     * @return the current scrollbar style
12941     * @see #SCROLLBARS_INSIDE_OVERLAY
12942     * @see #SCROLLBARS_INSIDE_INSET
12943     * @see #SCROLLBARS_OUTSIDE_OVERLAY
12944     * @see #SCROLLBARS_OUTSIDE_INSET
12945     *
12946     * @attr ref android.R.styleable#View_scrollbarStyle
12947     */
12948    @ViewDebug.ExportedProperty(mapping = {
12949            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
12950            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
12951            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
12952            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
12953    })
12954    @ScrollBarStyle
12955    public int getScrollBarStyle() {
12956        return mViewFlags & SCROLLBARS_STYLE_MASK;
12957    }
12958
12959    /**
12960     * <p>Compute the horizontal range that the horizontal scrollbar
12961     * represents.</p>
12962     *
12963     * <p>The range is expressed in arbitrary units that must be the same as the
12964     * units used by {@link #computeHorizontalScrollExtent()} and
12965     * {@link #computeHorizontalScrollOffset()}.</p>
12966     *
12967     * <p>The default range is the drawing width of this view.</p>
12968     *
12969     * @return the total horizontal range represented by the horizontal
12970     *         scrollbar
12971     *
12972     * @see #computeHorizontalScrollExtent()
12973     * @see #computeHorizontalScrollOffset()
12974     * @see android.widget.ScrollBarDrawable
12975     */
12976    protected int computeHorizontalScrollRange() {
12977        return getWidth();
12978    }
12979
12980    /**
12981     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
12982     * within the horizontal range. This value is used to compute the position
12983     * of the thumb within the scrollbar's track.</p>
12984     *
12985     * <p>The range is expressed in arbitrary units that must be the same as the
12986     * units used by {@link #computeHorizontalScrollRange()} and
12987     * {@link #computeHorizontalScrollExtent()}.</p>
12988     *
12989     * <p>The default offset is the scroll offset of this view.</p>
12990     *
12991     * @return the horizontal offset of the scrollbar's thumb
12992     *
12993     * @see #computeHorizontalScrollRange()
12994     * @see #computeHorizontalScrollExtent()
12995     * @see android.widget.ScrollBarDrawable
12996     */
12997    protected int computeHorizontalScrollOffset() {
12998        return mScrollX;
12999    }
13000
13001    /**
13002     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13003     * within the horizontal range. This value is used to compute the length
13004     * of the thumb within the scrollbar's track.</p>
13005     *
13006     * <p>The range is expressed in arbitrary units that must be the same as the
13007     * units used by {@link #computeHorizontalScrollRange()} and
13008     * {@link #computeHorizontalScrollOffset()}.</p>
13009     *
13010     * <p>The default extent is the drawing width of this view.</p>
13011     *
13012     * @return the horizontal extent of the scrollbar's thumb
13013     *
13014     * @see #computeHorizontalScrollRange()
13015     * @see #computeHorizontalScrollOffset()
13016     * @see android.widget.ScrollBarDrawable
13017     */
13018    protected int computeHorizontalScrollExtent() {
13019        return getWidth();
13020    }
13021
13022    /**
13023     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13024     *
13025     * <p>The range is expressed in arbitrary units that must be the same as the
13026     * units used by {@link #computeVerticalScrollExtent()} and
13027     * {@link #computeVerticalScrollOffset()}.</p>
13028     *
13029     * @return the total vertical range represented by the vertical scrollbar
13030     *
13031     * <p>The default range is the drawing height of this view.</p>
13032     *
13033     * @see #computeVerticalScrollExtent()
13034     * @see #computeVerticalScrollOffset()
13035     * @see android.widget.ScrollBarDrawable
13036     */
13037    protected int computeVerticalScrollRange() {
13038        return getHeight();
13039    }
13040
13041    /**
13042     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13043     * within the horizontal range. This value is used to compute the position
13044     * of the thumb within the scrollbar's track.</p>
13045     *
13046     * <p>The range is expressed in arbitrary units that must be the same as the
13047     * units used by {@link #computeVerticalScrollRange()} and
13048     * {@link #computeVerticalScrollExtent()}.</p>
13049     *
13050     * <p>The default offset is the scroll offset of this view.</p>
13051     *
13052     * @return the vertical offset of the scrollbar's thumb
13053     *
13054     * @see #computeVerticalScrollRange()
13055     * @see #computeVerticalScrollExtent()
13056     * @see android.widget.ScrollBarDrawable
13057     */
13058    protected int computeVerticalScrollOffset() {
13059        return mScrollY;
13060    }
13061
13062    /**
13063     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13064     * within the vertical range. This value is used to compute the length
13065     * of the thumb within the scrollbar's track.</p>
13066     *
13067     * <p>The range is expressed in arbitrary units that must be the same as the
13068     * units used by {@link #computeVerticalScrollRange()} and
13069     * {@link #computeVerticalScrollOffset()}.</p>
13070     *
13071     * <p>The default extent is the drawing height of this view.</p>
13072     *
13073     * @return the vertical extent of the scrollbar's thumb
13074     *
13075     * @see #computeVerticalScrollRange()
13076     * @see #computeVerticalScrollOffset()
13077     * @see android.widget.ScrollBarDrawable
13078     */
13079    protected int computeVerticalScrollExtent() {
13080        return getHeight();
13081    }
13082
13083    /**
13084     * Check if this view can be scrolled horizontally in a certain direction.
13085     *
13086     * @param direction Negative to check scrolling left, positive to check scrolling right.
13087     * @return true if this view can be scrolled in the specified direction, false otherwise.
13088     */
13089    public boolean canScrollHorizontally(int direction) {
13090        final int offset = computeHorizontalScrollOffset();
13091        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13092        if (range == 0) return false;
13093        if (direction < 0) {
13094            return offset > 0;
13095        } else {
13096            return offset < range - 1;
13097        }
13098    }
13099
13100    /**
13101     * Check if this view can be scrolled vertically in a certain direction.
13102     *
13103     * @param direction Negative to check scrolling up, positive to check scrolling down.
13104     * @return true if this view can be scrolled in the specified direction, false otherwise.
13105     */
13106    public boolean canScrollVertically(int direction) {
13107        final int offset = computeVerticalScrollOffset();
13108        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13109        if (range == 0) return false;
13110        if (direction < 0) {
13111            return offset > 0;
13112        } else {
13113            return offset < range - 1;
13114        }
13115    }
13116
13117    /**
13118     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13119     * scrollbars are painted only if they have been awakened first.</p>
13120     *
13121     * @param canvas the canvas on which to draw the scrollbars
13122     *
13123     * @see #awakenScrollBars(int)
13124     */
13125    protected final void onDrawScrollBars(Canvas canvas) {
13126        // scrollbars are drawn only when the animation is running
13127        final ScrollabilityCache cache = mScrollCache;
13128        if (cache != null) {
13129
13130            int state = cache.state;
13131
13132            if (state == ScrollabilityCache.OFF) {
13133                return;
13134            }
13135
13136            boolean invalidate = false;
13137
13138            if (state == ScrollabilityCache.FADING) {
13139                // We're fading -- get our fade interpolation
13140                if (cache.interpolatorValues == null) {
13141                    cache.interpolatorValues = new float[1];
13142                }
13143
13144                float[] values = cache.interpolatorValues;
13145
13146                // Stops the animation if we're done
13147                if (cache.scrollBarInterpolator.timeToValues(values) ==
13148                        Interpolator.Result.FREEZE_END) {
13149                    cache.state = ScrollabilityCache.OFF;
13150                } else {
13151                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13152                }
13153
13154                // This will make the scroll bars inval themselves after
13155                // drawing. We only want this when we're fading so that
13156                // we prevent excessive redraws
13157                invalidate = true;
13158            } else {
13159                // We're just on -- but we may have been fading before so
13160                // reset alpha
13161                cache.scrollBar.mutate().setAlpha(255);
13162            }
13163
13164
13165            final int viewFlags = mViewFlags;
13166
13167            final boolean drawHorizontalScrollBar =
13168                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13169            final boolean drawVerticalScrollBar =
13170                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13171                && !isVerticalScrollBarHidden();
13172
13173            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13174                final int width = mRight - mLeft;
13175                final int height = mBottom - mTop;
13176
13177                final ScrollBarDrawable scrollBar = cache.scrollBar;
13178
13179                final int scrollX = mScrollX;
13180                final int scrollY = mScrollY;
13181                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13182
13183                int left;
13184                int top;
13185                int right;
13186                int bottom;
13187
13188                if (drawHorizontalScrollBar) {
13189                    int size = scrollBar.getSize(false);
13190                    if (size <= 0) {
13191                        size = cache.scrollBarSize;
13192                    }
13193
13194                    scrollBar.setParameters(computeHorizontalScrollRange(),
13195                                            computeHorizontalScrollOffset(),
13196                                            computeHorizontalScrollExtent(), false);
13197                    final int verticalScrollBarGap = drawVerticalScrollBar ?
13198                            getVerticalScrollbarWidth() : 0;
13199                    top = scrollY + height - size - (mUserPaddingBottom & inside);
13200                    left = scrollX + (mPaddingLeft & inside);
13201                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13202                    bottom = top + size;
13203                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13204                    if (invalidate) {
13205                        invalidate(left, top, right, bottom);
13206                    }
13207                }
13208
13209                if (drawVerticalScrollBar) {
13210                    int size = scrollBar.getSize(true);
13211                    if (size <= 0) {
13212                        size = cache.scrollBarSize;
13213                    }
13214
13215                    scrollBar.setParameters(computeVerticalScrollRange(),
13216                                            computeVerticalScrollOffset(),
13217                                            computeVerticalScrollExtent(), true);
13218                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
13219                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13220                        verticalScrollbarPosition = isLayoutRtl() ?
13221                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13222                    }
13223                    switch (verticalScrollbarPosition) {
13224                        default:
13225                        case SCROLLBAR_POSITION_RIGHT:
13226                            left = scrollX + width - size - (mUserPaddingRight & inside);
13227                            break;
13228                        case SCROLLBAR_POSITION_LEFT:
13229                            left = scrollX + (mUserPaddingLeft & inside);
13230                            break;
13231                    }
13232                    top = scrollY + (mPaddingTop & inside);
13233                    right = left + size;
13234                    bottom = scrollY + height - (mUserPaddingBottom & inside);
13235                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13236                    if (invalidate) {
13237                        invalidate(left, top, right, bottom);
13238                    }
13239                }
13240            }
13241        }
13242    }
13243
13244    /**
13245     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13246     * FastScroller is visible.
13247     * @return whether to temporarily hide the vertical scrollbar
13248     * @hide
13249     */
13250    protected boolean isVerticalScrollBarHidden() {
13251        return false;
13252    }
13253
13254    /**
13255     * <p>Draw the horizontal scrollbar if
13256     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13257     *
13258     * @param canvas the canvas on which to draw the scrollbar
13259     * @param scrollBar the scrollbar's drawable
13260     *
13261     * @see #isHorizontalScrollBarEnabled()
13262     * @see #computeHorizontalScrollRange()
13263     * @see #computeHorizontalScrollExtent()
13264     * @see #computeHorizontalScrollOffset()
13265     * @see android.widget.ScrollBarDrawable
13266     * @hide
13267     */
13268    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13269            int l, int t, int r, int b) {
13270        scrollBar.setBounds(l, t, r, b);
13271        scrollBar.draw(canvas);
13272    }
13273
13274    /**
13275     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13276     * returns true.</p>
13277     *
13278     * @param canvas the canvas on which to draw the scrollbar
13279     * @param scrollBar the scrollbar's drawable
13280     *
13281     * @see #isVerticalScrollBarEnabled()
13282     * @see #computeVerticalScrollRange()
13283     * @see #computeVerticalScrollExtent()
13284     * @see #computeVerticalScrollOffset()
13285     * @see android.widget.ScrollBarDrawable
13286     * @hide
13287     */
13288    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
13289            int l, int t, int r, int b) {
13290        scrollBar.setBounds(l, t, r, b);
13291        scrollBar.draw(canvas);
13292    }
13293
13294    /**
13295     * Implement this to do your drawing.
13296     *
13297     * @param canvas the canvas on which the background will be drawn
13298     */
13299    protected void onDraw(Canvas canvas) {
13300    }
13301
13302    /*
13303     * Caller is responsible for calling requestLayout if necessary.
13304     * (This allows addViewInLayout to not request a new layout.)
13305     */
13306    void assignParent(ViewParent parent) {
13307        if (mParent == null) {
13308            mParent = parent;
13309        } else if (parent == null) {
13310            mParent = null;
13311        } else {
13312            throw new RuntimeException("view " + this + " being added, but"
13313                    + " it already has a parent");
13314        }
13315    }
13316
13317    /**
13318     * This is called when the view is attached to a window.  At this point it
13319     * has a Surface and will start drawing.  Note that this function is
13320     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
13321     * however it may be called any time before the first onDraw -- including
13322     * before or after {@link #onMeasure(int, int)}.
13323     *
13324     * @see #onDetachedFromWindow()
13325     */
13326    @CallSuper
13327    protected void onAttachedToWindow() {
13328        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
13329            mParent.requestTransparentRegion(this);
13330        }
13331
13332        if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
13333            initialAwakenScrollBars();
13334            mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
13335        }
13336
13337        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13338
13339        jumpDrawablesToCurrentState();
13340
13341        resetSubtreeAccessibilityStateChanged();
13342
13343        // rebuild, since Outline not maintained while View is detached
13344        rebuildOutline();
13345
13346        if (isFocused()) {
13347            InputMethodManager imm = InputMethodManager.peekInstance();
13348            if (imm != null) {
13349                imm.focusIn(this);
13350            }
13351        }
13352    }
13353
13354    /**
13355     * Resolve all RTL related properties.
13356     *
13357     * @return true if resolution of RTL properties has been done
13358     *
13359     * @hide
13360     */
13361    public boolean resolveRtlPropertiesIfNeeded() {
13362        if (!needRtlPropertiesResolution()) return false;
13363
13364        // Order is important here: LayoutDirection MUST be resolved first
13365        if (!isLayoutDirectionResolved()) {
13366            resolveLayoutDirection();
13367            resolveLayoutParams();
13368        }
13369        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
13370        if (!isTextDirectionResolved()) {
13371            resolveTextDirection();
13372        }
13373        if (!isTextAlignmentResolved()) {
13374            resolveTextAlignment();
13375        }
13376        // Should resolve Drawables before Padding because we need the layout direction of the
13377        // Drawable to correctly resolve Padding.
13378        if (!areDrawablesResolved()) {
13379            resolveDrawables();
13380        }
13381        if (!isPaddingResolved()) {
13382            resolvePadding();
13383        }
13384        onRtlPropertiesChanged(getLayoutDirection());
13385        return true;
13386    }
13387
13388    /**
13389     * Reset resolution of all RTL related properties.
13390     *
13391     * @hide
13392     */
13393    public void resetRtlProperties() {
13394        resetResolvedLayoutDirection();
13395        resetResolvedTextDirection();
13396        resetResolvedTextAlignment();
13397        resetResolvedPadding();
13398        resetResolvedDrawables();
13399    }
13400
13401    /**
13402     * @see #onScreenStateChanged(int)
13403     */
13404    void dispatchScreenStateChanged(int screenState) {
13405        onScreenStateChanged(screenState);
13406    }
13407
13408    /**
13409     * This method is called whenever the state of the screen this view is
13410     * attached to changes. A state change will usually occurs when the screen
13411     * turns on or off (whether it happens automatically or the user does it
13412     * manually.)
13413     *
13414     * @param screenState The new state of the screen. Can be either
13415     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
13416     */
13417    public void onScreenStateChanged(int screenState) {
13418    }
13419
13420    /**
13421     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
13422     */
13423    private boolean hasRtlSupport() {
13424        return mContext.getApplicationInfo().hasRtlSupport();
13425    }
13426
13427    /**
13428     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
13429     * RTL not supported)
13430     */
13431    private boolean isRtlCompatibilityMode() {
13432        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
13433        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
13434    }
13435
13436    /**
13437     * @return true if RTL properties need resolution.
13438     *
13439     */
13440    private boolean needRtlPropertiesResolution() {
13441        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
13442    }
13443
13444    /**
13445     * Called when any RTL property (layout direction or text direction or text alignment) has
13446     * been changed.
13447     *
13448     * Subclasses need to override this method to take care of cached information that depends on the
13449     * resolved layout direction, or to inform child views that inherit their layout direction.
13450     *
13451     * The default implementation does nothing.
13452     *
13453     * @param layoutDirection the direction of the layout
13454     *
13455     * @see #LAYOUT_DIRECTION_LTR
13456     * @see #LAYOUT_DIRECTION_RTL
13457     */
13458    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
13459    }
13460
13461    /**
13462     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
13463     * that the parent directionality can and will be resolved before its children.
13464     *
13465     * @return true if resolution has been done, false otherwise.
13466     *
13467     * @hide
13468     */
13469    public boolean resolveLayoutDirection() {
13470        // Clear any previous layout direction resolution
13471        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13472
13473        if (hasRtlSupport()) {
13474            // Set resolved depending on layout direction
13475            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
13476                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
13477                case LAYOUT_DIRECTION_INHERIT:
13478                    // We cannot resolve yet. LTR is by default and let the resolution happen again
13479                    // later to get the correct resolved value
13480                    if (!canResolveLayoutDirection()) return false;
13481
13482                    // Parent has not yet resolved, LTR is still the default
13483                    try {
13484                        if (!mParent.isLayoutDirectionResolved()) return false;
13485
13486                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13487                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13488                        }
13489                    } catch (AbstractMethodError e) {
13490                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13491                                " does not fully implement ViewParent", e);
13492                    }
13493                    break;
13494                case LAYOUT_DIRECTION_RTL:
13495                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13496                    break;
13497                case LAYOUT_DIRECTION_LOCALE:
13498                    if((LAYOUT_DIRECTION_RTL ==
13499                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
13500                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
13501                    }
13502                    break;
13503                default:
13504                    // Nothing to do, LTR by default
13505            }
13506        }
13507
13508        // Set to resolved
13509        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13510        return true;
13511    }
13512
13513    /**
13514     * Check if layout direction resolution can be done.
13515     *
13516     * @return true if layout direction resolution can be done otherwise return false.
13517     */
13518    public boolean canResolveLayoutDirection() {
13519        switch (getRawLayoutDirection()) {
13520            case LAYOUT_DIRECTION_INHERIT:
13521                if (mParent != null) {
13522                    try {
13523                        return mParent.canResolveLayoutDirection();
13524                    } catch (AbstractMethodError e) {
13525                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
13526                                " does not fully implement ViewParent", e);
13527                    }
13528                }
13529                return false;
13530
13531            default:
13532                return true;
13533        }
13534    }
13535
13536    /**
13537     * Reset the resolved layout direction. Layout direction will be resolved during a call to
13538     * {@link #onMeasure(int, int)}.
13539     *
13540     * @hide
13541     */
13542    public void resetResolvedLayoutDirection() {
13543        // Reset the current resolved bits
13544        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
13545    }
13546
13547    /**
13548     * @return true if the layout direction is inherited.
13549     *
13550     * @hide
13551     */
13552    public boolean isLayoutDirectionInherited() {
13553        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
13554    }
13555
13556    /**
13557     * @return true if layout direction has been resolved.
13558     */
13559    public boolean isLayoutDirectionResolved() {
13560        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
13561    }
13562
13563    /**
13564     * Return if padding has been resolved
13565     *
13566     * @hide
13567     */
13568    boolean isPaddingResolved() {
13569        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
13570    }
13571
13572    /**
13573     * Resolves padding depending on layout direction, if applicable, and
13574     * recomputes internal padding values to adjust for scroll bars.
13575     *
13576     * @hide
13577     */
13578    public void resolvePadding() {
13579        final int resolvedLayoutDirection = getLayoutDirection();
13580
13581        if (!isRtlCompatibilityMode()) {
13582            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
13583            // If start / end padding are defined, they will be resolved (hence overriding) to
13584            // left / right or right / left depending on the resolved layout direction.
13585            // If start / end padding are not defined, use the left / right ones.
13586            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
13587                Rect padding = sThreadLocal.get();
13588                if (padding == null) {
13589                    padding = new Rect();
13590                    sThreadLocal.set(padding);
13591                }
13592                mBackground.getPadding(padding);
13593                if (!mLeftPaddingDefined) {
13594                    mUserPaddingLeftInitial = padding.left;
13595                }
13596                if (!mRightPaddingDefined) {
13597                    mUserPaddingRightInitial = padding.right;
13598                }
13599            }
13600            switch (resolvedLayoutDirection) {
13601                case LAYOUT_DIRECTION_RTL:
13602                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13603                        mUserPaddingRight = mUserPaddingStart;
13604                    } else {
13605                        mUserPaddingRight = mUserPaddingRightInitial;
13606                    }
13607                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13608                        mUserPaddingLeft = mUserPaddingEnd;
13609                    } else {
13610                        mUserPaddingLeft = mUserPaddingLeftInitial;
13611                    }
13612                    break;
13613                case LAYOUT_DIRECTION_LTR:
13614                default:
13615                    if (mUserPaddingStart != UNDEFINED_PADDING) {
13616                        mUserPaddingLeft = mUserPaddingStart;
13617                    } else {
13618                        mUserPaddingLeft = mUserPaddingLeftInitial;
13619                    }
13620                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
13621                        mUserPaddingRight = mUserPaddingEnd;
13622                    } else {
13623                        mUserPaddingRight = mUserPaddingRightInitial;
13624                    }
13625            }
13626
13627            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
13628        }
13629
13630        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13631        onRtlPropertiesChanged(resolvedLayoutDirection);
13632
13633        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
13634    }
13635
13636    /**
13637     * Reset the resolved layout direction.
13638     *
13639     * @hide
13640     */
13641    public void resetResolvedPadding() {
13642        resetResolvedPaddingInternal();
13643    }
13644
13645    /**
13646     * Used when we only want to reset *this* view's padding and not trigger overrides
13647     * in ViewGroup that reset children too.
13648     */
13649    void resetResolvedPaddingInternal() {
13650        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
13651    }
13652
13653    /**
13654     * This is called when the view is detached from a window.  At this point it
13655     * no longer has a surface for drawing.
13656     *
13657     * @see #onAttachedToWindow()
13658     */
13659    @CallSuper
13660    protected void onDetachedFromWindow() {
13661    }
13662
13663    /**
13664     * This is a framework-internal mirror of onDetachedFromWindow() that's called
13665     * after onDetachedFromWindow().
13666     *
13667     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
13668     * The super method should be called at the end of the overridden method to ensure
13669     * subclasses are destroyed first
13670     *
13671     * @hide
13672     */
13673    @CallSuper
13674    protected void onDetachedFromWindowInternal() {
13675        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
13676        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
13677
13678        removeUnsetPressCallback();
13679        removeLongPressCallback();
13680        removePerformClickCallback();
13681        removeSendViewScrolledAccessibilityEventCallback();
13682        stopNestedScroll();
13683
13684        // Anything that started animating right before detach should already
13685        // be in its final state when re-attached.
13686        jumpDrawablesToCurrentState();
13687
13688        destroyDrawingCache();
13689
13690        cleanupDraw();
13691        mCurrentAnimation = null;
13692    }
13693
13694    private void cleanupDraw() {
13695        resetDisplayList();
13696        if (mAttachInfo != null) {
13697            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
13698        }
13699    }
13700
13701    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
13702    }
13703
13704    /**
13705     * @return The number of times this view has been attached to a window
13706     */
13707    protected int getWindowAttachCount() {
13708        return mWindowAttachCount;
13709    }
13710
13711    /**
13712     * Retrieve a unique token identifying the window this view is attached to.
13713     * @return Return the window's token for use in
13714     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
13715     */
13716    public IBinder getWindowToken() {
13717        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
13718    }
13719
13720    /**
13721     * Retrieve the {@link WindowId} for the window this view is
13722     * currently attached to.
13723     */
13724    public WindowId getWindowId() {
13725        if (mAttachInfo == null) {
13726            return null;
13727        }
13728        if (mAttachInfo.mWindowId == null) {
13729            try {
13730                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
13731                        mAttachInfo.mWindowToken);
13732                mAttachInfo.mWindowId = new WindowId(
13733                        mAttachInfo.mIWindowId);
13734            } catch (RemoteException e) {
13735            }
13736        }
13737        return mAttachInfo.mWindowId;
13738    }
13739
13740    /**
13741     * Retrieve a unique token identifying the top-level "real" window of
13742     * the window that this view is attached to.  That is, this is like
13743     * {@link #getWindowToken}, except if the window this view in is a panel
13744     * window (attached to another containing window), then the token of
13745     * the containing window is returned instead.
13746     *
13747     * @return Returns the associated window token, either
13748     * {@link #getWindowToken()} or the containing window's token.
13749     */
13750    public IBinder getApplicationWindowToken() {
13751        AttachInfo ai = mAttachInfo;
13752        if (ai != null) {
13753            IBinder appWindowToken = ai.mPanelParentWindowToken;
13754            if (appWindowToken == null) {
13755                appWindowToken = ai.mWindowToken;
13756            }
13757            return appWindowToken;
13758        }
13759        return null;
13760    }
13761
13762    /**
13763     * Gets the logical display to which the view's window has been attached.
13764     *
13765     * @return The logical display, or null if the view is not currently attached to a window.
13766     */
13767    public Display getDisplay() {
13768        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
13769    }
13770
13771    /**
13772     * Retrieve private session object this view hierarchy is using to
13773     * communicate with the window manager.
13774     * @return the session object to communicate with the window manager
13775     */
13776    /*package*/ IWindowSession getWindowSession() {
13777        return mAttachInfo != null ? mAttachInfo.mSession : null;
13778    }
13779
13780    /**
13781     * @param info the {@link android.view.View.AttachInfo} to associated with
13782     *        this view
13783     */
13784    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
13785        //System.out.println("Attached! " + this);
13786        mAttachInfo = info;
13787        if (mOverlay != null) {
13788            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
13789        }
13790        mWindowAttachCount++;
13791        // We will need to evaluate the drawable state at least once.
13792        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
13793        if (mFloatingTreeObserver != null) {
13794            info.mTreeObserver.merge(mFloatingTreeObserver);
13795            mFloatingTreeObserver = null;
13796        }
13797        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
13798            mAttachInfo.mScrollContainers.add(this);
13799            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
13800        }
13801        performCollectViewAttributes(mAttachInfo, visibility);
13802        onAttachedToWindow();
13803
13804        ListenerInfo li = mListenerInfo;
13805        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13806                li != null ? li.mOnAttachStateChangeListeners : null;
13807        if (listeners != null && listeners.size() > 0) {
13808            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13809            // perform the dispatching. The iterator is a safe guard against listeners that
13810            // could mutate the list by calling the various add/remove methods. This prevents
13811            // the array from being modified while we iterate it.
13812            for (OnAttachStateChangeListener listener : listeners) {
13813                listener.onViewAttachedToWindow(this);
13814            }
13815        }
13816
13817        int vis = info.mWindowVisibility;
13818        if (vis != GONE) {
13819            onWindowVisibilityChanged(vis);
13820        }
13821        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
13822            // If nobody has evaluated the drawable state yet, then do it now.
13823            refreshDrawableState();
13824        }
13825        needGlobalAttributesUpdate(false);
13826    }
13827
13828    void dispatchDetachedFromWindow() {
13829        AttachInfo info = mAttachInfo;
13830        if (info != null) {
13831            int vis = info.mWindowVisibility;
13832            if (vis != GONE) {
13833                onWindowVisibilityChanged(GONE);
13834            }
13835        }
13836
13837        onDetachedFromWindow();
13838        onDetachedFromWindowInternal();
13839
13840        ListenerInfo li = mListenerInfo;
13841        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
13842                li != null ? li.mOnAttachStateChangeListeners : null;
13843        if (listeners != null && listeners.size() > 0) {
13844            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
13845            // perform the dispatching. The iterator is a safe guard against listeners that
13846            // could mutate the list by calling the various add/remove methods. This prevents
13847            // the array from being modified while we iterate it.
13848            for (OnAttachStateChangeListener listener : listeners) {
13849                listener.onViewDetachedFromWindow(this);
13850            }
13851        }
13852
13853        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
13854            mAttachInfo.mScrollContainers.remove(this);
13855            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
13856        }
13857
13858        mAttachInfo = null;
13859        if (mOverlay != null) {
13860            mOverlay.getOverlayView().dispatchDetachedFromWindow();
13861        }
13862    }
13863
13864    /**
13865     * Cancel any deferred high-level input events that were previously posted to the event queue.
13866     *
13867     * <p>Many views post high-level events such as click handlers to the event queue
13868     * to run deferred in order to preserve a desired user experience - clearing visible
13869     * pressed states before executing, etc. This method will abort any events of this nature
13870     * that are currently in flight.</p>
13871     *
13872     * <p>Custom views that generate their own high-level deferred input events should override
13873     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
13874     *
13875     * <p>This will also cancel pending input events for any child views.</p>
13876     *
13877     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
13878     * This will not impact newer events posted after this call that may occur as a result of
13879     * lower-level input events still waiting in the queue. If you are trying to prevent
13880     * double-submitted  events for the duration of some sort of asynchronous transaction
13881     * you should also take other steps to protect against unexpected double inputs e.g. calling
13882     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
13883     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
13884     */
13885    public final void cancelPendingInputEvents() {
13886        dispatchCancelPendingInputEvents();
13887    }
13888
13889    /**
13890     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
13891     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
13892     */
13893    void dispatchCancelPendingInputEvents() {
13894        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
13895        onCancelPendingInputEvents();
13896        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
13897            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
13898                    " did not call through to super.onCancelPendingInputEvents()");
13899        }
13900    }
13901
13902    /**
13903     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
13904     * a parent view.
13905     *
13906     * <p>This method is responsible for removing any pending high-level input events that were
13907     * posted to the event queue to run later. Custom view classes that post their own deferred
13908     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
13909     * {@link android.os.Handler} should override this method, call
13910     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
13911     * </p>
13912     */
13913    public void onCancelPendingInputEvents() {
13914        removePerformClickCallback();
13915        cancelLongPress();
13916        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
13917    }
13918
13919    /**
13920     * Store this view hierarchy's frozen state into the given container.
13921     *
13922     * @param container The SparseArray in which to save the view's state.
13923     *
13924     * @see #restoreHierarchyState(android.util.SparseArray)
13925     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13926     * @see #onSaveInstanceState()
13927     */
13928    public void saveHierarchyState(SparseArray<Parcelable> container) {
13929        dispatchSaveInstanceState(container);
13930    }
13931
13932    /**
13933     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
13934     * this view and its children. May be overridden to modify how freezing happens to a
13935     * view's children; for example, some views may want to not store state for their children.
13936     *
13937     * @param container The SparseArray in which to save the view's state.
13938     *
13939     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13940     * @see #saveHierarchyState(android.util.SparseArray)
13941     * @see #onSaveInstanceState()
13942     */
13943    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
13944        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
13945            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
13946            Parcelable state = onSaveInstanceState();
13947            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
13948                throw new IllegalStateException(
13949                        "Derived class did not call super.onSaveInstanceState()");
13950            }
13951            if (state != null) {
13952                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
13953                // + ": " + state);
13954                container.put(mID, state);
13955            }
13956        }
13957    }
13958
13959    /**
13960     * Hook allowing a view to generate a representation of its internal state
13961     * that can later be used to create a new instance with that same state.
13962     * This state should only contain information that is not persistent or can
13963     * not be reconstructed later. For example, you will never store your
13964     * current position on screen because that will be computed again when a
13965     * new instance of the view is placed in its view hierarchy.
13966     * <p>
13967     * Some examples of things you may store here: the current cursor position
13968     * in a text view (but usually not the text itself since that is stored in a
13969     * content provider or other persistent storage), the currently selected
13970     * item in a list view.
13971     *
13972     * @return Returns a Parcelable object containing the view's current dynamic
13973     *         state, or null if there is nothing interesting to save. The
13974     *         default implementation returns null.
13975     * @see #onRestoreInstanceState(android.os.Parcelable)
13976     * @see #saveHierarchyState(android.util.SparseArray)
13977     * @see #dispatchSaveInstanceState(android.util.SparseArray)
13978     * @see #setSaveEnabled(boolean)
13979     */
13980    @CallSuper
13981    protected Parcelable onSaveInstanceState() {
13982        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
13983        return BaseSavedState.EMPTY_STATE;
13984    }
13985
13986    /**
13987     * Restore this view hierarchy's frozen state from the given container.
13988     *
13989     * @param container The SparseArray which holds previously frozen states.
13990     *
13991     * @see #saveHierarchyState(android.util.SparseArray)
13992     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
13993     * @see #onRestoreInstanceState(android.os.Parcelable)
13994     */
13995    public void restoreHierarchyState(SparseArray<Parcelable> container) {
13996        dispatchRestoreInstanceState(container);
13997    }
13998
13999    /**
14000     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14001     * state for this view and its children. May be overridden to modify how restoring
14002     * happens to a view's children; for example, some views may want to not store state
14003     * for their children.
14004     *
14005     * @param container The SparseArray which holds previously saved state.
14006     *
14007     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14008     * @see #restoreHierarchyState(android.util.SparseArray)
14009     * @see #onRestoreInstanceState(android.os.Parcelable)
14010     */
14011    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14012        if (mID != NO_ID) {
14013            Parcelable state = container.get(mID);
14014            if (state != null) {
14015                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14016                // + ": " + state);
14017                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14018                onRestoreInstanceState(state);
14019                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14020                    throw new IllegalStateException(
14021                            "Derived class did not call super.onRestoreInstanceState()");
14022                }
14023            }
14024        }
14025    }
14026
14027    /**
14028     * Hook allowing a view to re-apply a representation of its internal state that had previously
14029     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14030     * null state.
14031     *
14032     * @param state The frozen state that had previously been returned by
14033     *        {@link #onSaveInstanceState}.
14034     *
14035     * @see #onSaveInstanceState()
14036     * @see #restoreHierarchyState(android.util.SparseArray)
14037     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14038     */
14039    @CallSuper
14040    protected void onRestoreInstanceState(Parcelable state) {
14041        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14042        if (state != BaseSavedState.EMPTY_STATE && state != null) {
14043            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14044                    + "received " + state.getClass().toString() + " instead. This usually happens "
14045                    + "when two views of different type have the same id in the same hierarchy. "
14046                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14047                    + "other views do not use the same id.");
14048        }
14049    }
14050
14051    /**
14052     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14053     *
14054     * @return the drawing start time in milliseconds
14055     */
14056    public long getDrawingTime() {
14057        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14058    }
14059
14060    /**
14061     * <p>Enables or disables the duplication of the parent's state into this view. When
14062     * duplication is enabled, this view gets its drawable state from its parent rather
14063     * than from its own internal properties.</p>
14064     *
14065     * <p>Note: in the current implementation, setting this property to true after the
14066     * view was added to a ViewGroup might have no effect at all. This property should
14067     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14068     *
14069     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14070     * property is enabled, an exception will be thrown.</p>
14071     *
14072     * <p>Note: if the child view uses and updates additional states which are unknown to the
14073     * parent, these states should not be affected by this method.</p>
14074     *
14075     * @param enabled True to enable duplication of the parent's drawable state, false
14076     *                to disable it.
14077     *
14078     * @see #getDrawableState()
14079     * @see #isDuplicateParentStateEnabled()
14080     */
14081    public void setDuplicateParentStateEnabled(boolean enabled) {
14082        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14083    }
14084
14085    /**
14086     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14087     *
14088     * @return True if this view's drawable state is duplicated from the parent,
14089     *         false otherwise
14090     *
14091     * @see #getDrawableState()
14092     * @see #setDuplicateParentStateEnabled(boolean)
14093     */
14094    public boolean isDuplicateParentStateEnabled() {
14095        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14096    }
14097
14098    /**
14099     * <p>Specifies the type of layer backing this view. The layer can be
14100     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14101     * {@link #LAYER_TYPE_HARDWARE}.</p>
14102     *
14103     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14104     * instance that controls how the layer is composed on screen. The following
14105     * properties of the paint are taken into account when composing the layer:</p>
14106     * <ul>
14107     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14108     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14109     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14110     * </ul>
14111     *
14112     * <p>If this view has an alpha value set to < 1.0 by calling
14113     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14114     * by this view's alpha value.</p>
14115     *
14116     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14117     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14118     * for more information on when and how to use layers.</p>
14119     *
14120     * @param layerType The type of layer to use with this view, must be one of
14121     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14122     *        {@link #LAYER_TYPE_HARDWARE}
14123     * @param paint The paint used to compose the layer. This argument is optional
14124     *        and can be null. It is ignored when the layer type is
14125     *        {@link #LAYER_TYPE_NONE}
14126     *
14127     * @see #getLayerType()
14128     * @see #LAYER_TYPE_NONE
14129     * @see #LAYER_TYPE_SOFTWARE
14130     * @see #LAYER_TYPE_HARDWARE
14131     * @see #setAlpha(float)
14132     *
14133     * @attr ref android.R.styleable#View_layerType
14134     */
14135    public void setLayerType(int layerType, Paint paint) {
14136        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14137            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14138                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14139        }
14140
14141        boolean typeChanged = mRenderNode.setLayerType(layerType);
14142
14143        if (!typeChanged) {
14144            setLayerPaint(paint);
14145            return;
14146        }
14147
14148        // Destroy any previous software drawing cache if needed
14149        if (mLayerType == LAYER_TYPE_SOFTWARE) {
14150            destroyDrawingCache();
14151        }
14152
14153        mLayerType = layerType;
14154        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14155        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14156        mRenderNode.setLayerPaint(mLayerPaint);
14157
14158        // draw() behaves differently if we are on a layer, so we need to
14159        // invalidate() here
14160        invalidateParentCaches();
14161        invalidate(true);
14162    }
14163
14164    /**
14165     * Updates the {@link Paint} object used with the current layer (used only if the current
14166     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14167     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14168     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14169     * ensure that the view gets redrawn immediately.
14170     *
14171     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14172     * instance that controls how the layer is composed on screen. The following
14173     * properties of the paint are taken into account when composing the layer:</p>
14174     * <ul>
14175     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14176     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14177     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14178     * </ul>
14179     *
14180     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14181     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14182     *
14183     * @param paint The paint used to compose the layer. This argument is optional
14184     *        and can be null. It is ignored when the layer type is
14185     *        {@link #LAYER_TYPE_NONE}
14186     *
14187     * @see #setLayerType(int, android.graphics.Paint)
14188     */
14189    public void setLayerPaint(Paint paint) {
14190        int layerType = getLayerType();
14191        if (layerType != LAYER_TYPE_NONE) {
14192            mLayerPaint = paint == null ? new Paint() : paint;
14193            if (layerType == LAYER_TYPE_HARDWARE) {
14194                if (mRenderNode.setLayerPaint(mLayerPaint)) {
14195                    invalidateViewProperty(false, false);
14196                }
14197            } else {
14198                invalidate();
14199            }
14200        }
14201    }
14202
14203    /**
14204     * Indicates whether this view has a static layer. A view with layer type
14205     * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
14206     * dynamic.
14207     */
14208    boolean hasStaticLayer() {
14209        return true;
14210    }
14211
14212    /**
14213     * Indicates what type of layer is currently associated with this view. By default
14214     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14215     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14216     * for more information on the different types of layers.
14217     *
14218     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14219     *         {@link #LAYER_TYPE_HARDWARE}
14220     *
14221     * @see #setLayerType(int, android.graphics.Paint)
14222     * @see #buildLayer()
14223     * @see #LAYER_TYPE_NONE
14224     * @see #LAYER_TYPE_SOFTWARE
14225     * @see #LAYER_TYPE_HARDWARE
14226     */
14227    public int getLayerType() {
14228        return mLayerType;
14229    }
14230
14231    /**
14232     * Forces this view's layer to be created and this view to be rendered
14233     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14234     * invoking this method will have no effect.
14235     *
14236     * This method can for instance be used to render a view into its layer before
14237     * starting an animation. If this view is complex, rendering into the layer
14238     * before starting the animation will avoid skipping frames.
14239     *
14240     * @throws IllegalStateException If this view is not attached to a window
14241     *
14242     * @see #setLayerType(int, android.graphics.Paint)
14243     */
14244    public void buildLayer() {
14245        if (mLayerType == LAYER_TYPE_NONE) return;
14246
14247        final AttachInfo attachInfo = mAttachInfo;
14248        if (attachInfo == null) {
14249            throw new IllegalStateException("This view must be attached to a window first");
14250        }
14251
14252        if (getWidth() == 0 || getHeight() == 0) {
14253            return;
14254        }
14255
14256        switch (mLayerType) {
14257            case LAYER_TYPE_HARDWARE:
14258                updateDisplayListIfDirty();
14259                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14260                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14261                }
14262                break;
14263            case LAYER_TYPE_SOFTWARE:
14264                buildDrawingCache(true);
14265                break;
14266        }
14267    }
14268
14269    /**
14270     * If this View draws with a HardwareLayer, returns it.
14271     * Otherwise returns null
14272     *
14273     * TODO: Only TextureView uses this, can we eliminate it?
14274     */
14275    HardwareLayer getHardwareLayer() {
14276        return null;
14277    }
14278
14279    /**
14280     * Destroys all hardware rendering resources. This method is invoked
14281     * when the system needs to reclaim resources. Upon execution of this
14282     * method, you should free any OpenGL resources created by the view.
14283     *
14284     * Note: you <strong>must</strong> call
14285     * <code>super.destroyHardwareResources()</code> when overriding
14286     * this method.
14287     *
14288     * @hide
14289     */
14290    @CallSuper
14291    protected void destroyHardwareResources() {
14292        // Although the Layer will be destroyed by RenderNode, we want to release
14293        // the staging display list, which is also a signal to RenderNode that it's
14294        // safe to free its copy of the display list as it knows that we will
14295        // push an updated DisplayList if we try to draw again
14296        resetDisplayList();
14297    }
14298
14299    /**
14300     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
14301     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
14302     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
14303     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
14304     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
14305     * null.</p>
14306     *
14307     * <p>Enabling the drawing cache is similar to
14308     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
14309     * acceleration is turned off. When hardware acceleration is turned on, enabling the
14310     * drawing cache has no effect on rendering because the system uses a different mechanism
14311     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
14312     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
14313     * for information on how to enable software and hardware layers.</p>
14314     *
14315     * <p>This API can be used to manually generate
14316     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
14317     * {@link #getDrawingCache()}.</p>
14318     *
14319     * @param enabled true to enable the drawing cache, false otherwise
14320     *
14321     * @see #isDrawingCacheEnabled()
14322     * @see #getDrawingCache()
14323     * @see #buildDrawingCache()
14324     * @see #setLayerType(int, android.graphics.Paint)
14325     */
14326    public void setDrawingCacheEnabled(boolean enabled) {
14327        mCachingFailed = false;
14328        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
14329    }
14330
14331    /**
14332     * <p>Indicates whether the drawing cache is enabled for this view.</p>
14333     *
14334     * @return true if the drawing cache is enabled
14335     *
14336     * @see #setDrawingCacheEnabled(boolean)
14337     * @see #getDrawingCache()
14338     */
14339    @ViewDebug.ExportedProperty(category = "drawing")
14340    public boolean isDrawingCacheEnabled() {
14341        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
14342    }
14343
14344    /**
14345     * Debugging utility which recursively outputs the dirty state of a view and its
14346     * descendants.
14347     *
14348     * @hide
14349     */
14350    @SuppressWarnings({"UnusedDeclaration"})
14351    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
14352        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
14353                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
14354                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
14355                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
14356        if (clear) {
14357            mPrivateFlags &= clearMask;
14358        }
14359        if (this instanceof ViewGroup) {
14360            ViewGroup parent = (ViewGroup) this;
14361            final int count = parent.getChildCount();
14362            for (int i = 0; i < count; i++) {
14363                final View child = parent.getChildAt(i);
14364                child.outputDirtyFlags(indent + "  ", clear, clearMask);
14365            }
14366        }
14367    }
14368
14369    /**
14370     * This method is used by ViewGroup to cause its children to restore or recreate their
14371     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
14372     * to recreate its own display list, which would happen if it went through the normal
14373     * draw/dispatchDraw mechanisms.
14374     *
14375     * @hide
14376     */
14377    protected void dispatchGetDisplayList() {}
14378
14379    /**
14380     * A view that is not attached or hardware accelerated cannot create a display list.
14381     * This method checks these conditions and returns the appropriate result.
14382     *
14383     * @return true if view has the ability to create a display list, false otherwise.
14384     *
14385     * @hide
14386     */
14387    public boolean canHaveDisplayList() {
14388        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
14389    }
14390
14391    private void updateDisplayListIfDirty() {
14392        final RenderNode renderNode = mRenderNode;
14393        if (!canHaveDisplayList()) {
14394            // can't populate RenderNode, don't try
14395            return;
14396        }
14397
14398        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
14399                || !renderNode.isValid()
14400                || (mRecreateDisplayList)) {
14401            // Don't need to recreate the display list, just need to tell our
14402            // children to restore/recreate theirs
14403            if (renderNode.isValid()
14404                    && !mRecreateDisplayList) {
14405                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14406                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14407                dispatchGetDisplayList();
14408
14409                return; // no work needed
14410            }
14411
14412            // If we got here, we're recreating it. Mark it as such to ensure that
14413            // we copy in child display lists into ours in drawChild()
14414            mRecreateDisplayList = true;
14415
14416            int width = mRight - mLeft;
14417            int height = mBottom - mTop;
14418            int layerType = getLayerType();
14419
14420            final DisplayListCanvas canvas = renderNode.start(width, height);
14421            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
14422
14423            try {
14424                final HardwareLayer layer = getHardwareLayer();
14425                if (layer != null && layer.isValid()) {
14426                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
14427                } else if (layerType == LAYER_TYPE_SOFTWARE) {
14428                    buildDrawingCache(true);
14429                    Bitmap cache = getDrawingCache(true);
14430                    if (cache != null) {
14431                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
14432                    }
14433                } else {
14434                    computeScroll();
14435
14436                    canvas.translate(-mScrollX, -mScrollY);
14437                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14438                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14439
14440                    // Fast path for layouts with no backgrounds
14441                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14442                        dispatchDraw(canvas);
14443                        if (mOverlay != null && !mOverlay.isEmpty()) {
14444                            mOverlay.getOverlayView().draw(canvas);
14445                        }
14446                    } else {
14447                        draw(canvas);
14448                    }
14449                }
14450            } finally {
14451                renderNode.end(canvas);
14452                setDisplayListProperties(renderNode);
14453            }
14454        } else {
14455            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
14456            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14457        }
14458    }
14459
14460    /**
14461     * Returns a RenderNode with View draw content recorded, which can be
14462     * used to draw this view again without executing its draw method.
14463     *
14464     * @return A RenderNode ready to replay, or null if caching is not enabled.
14465     *
14466     * @hide
14467     */
14468    public RenderNode getDisplayList() {
14469        updateDisplayListIfDirty();
14470        return mRenderNode;
14471    }
14472
14473    private void resetDisplayList() {
14474        if (mRenderNode.isValid()) {
14475            mRenderNode.destroyDisplayListData();
14476        }
14477
14478        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
14479            mBackgroundRenderNode.destroyDisplayListData();
14480        }
14481    }
14482
14483    /**
14484     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
14485     *
14486     * @return A non-scaled bitmap representing this view or null if cache is disabled.
14487     *
14488     * @see #getDrawingCache(boolean)
14489     */
14490    public Bitmap getDrawingCache() {
14491        return getDrawingCache(false);
14492    }
14493
14494    /**
14495     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
14496     * is null when caching is disabled. If caching is enabled and the cache is not ready,
14497     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
14498     * draw from the cache when the cache is enabled. To benefit from the cache, you must
14499     * request the drawing cache by calling this method and draw it on screen if the
14500     * returned bitmap is not null.</p>
14501     *
14502     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14503     * this method will create a bitmap of the same size as this view. Because this bitmap
14504     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14505     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14506     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14507     * size than the view. This implies that your application must be able to handle this
14508     * size.</p>
14509     *
14510     * @param autoScale Indicates whether the generated bitmap should be scaled based on
14511     *        the current density of the screen when the application is in compatibility
14512     *        mode.
14513     *
14514     * @return A bitmap representing this view or null if cache is disabled.
14515     *
14516     * @see #setDrawingCacheEnabled(boolean)
14517     * @see #isDrawingCacheEnabled()
14518     * @see #buildDrawingCache(boolean)
14519     * @see #destroyDrawingCache()
14520     */
14521    public Bitmap getDrawingCache(boolean autoScale) {
14522        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
14523            return null;
14524        }
14525        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
14526            buildDrawingCache(autoScale);
14527        }
14528        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
14529    }
14530
14531    /**
14532     * <p>Frees the resources used by the drawing cache. If you call
14533     * {@link #buildDrawingCache()} manually without calling
14534     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14535     * should cleanup the cache with this method afterwards.</p>
14536     *
14537     * @see #setDrawingCacheEnabled(boolean)
14538     * @see #buildDrawingCache()
14539     * @see #getDrawingCache()
14540     */
14541    public void destroyDrawingCache() {
14542        if (mDrawingCache != null) {
14543            mDrawingCache.recycle();
14544            mDrawingCache = null;
14545        }
14546        if (mUnscaledDrawingCache != null) {
14547            mUnscaledDrawingCache.recycle();
14548            mUnscaledDrawingCache = null;
14549        }
14550    }
14551
14552    /**
14553     * Setting a solid background color for the drawing cache's bitmaps will improve
14554     * performance and memory usage. Note, though that this should only be used if this
14555     * view will always be drawn on top of a solid color.
14556     *
14557     * @param color The background color to use for the drawing cache's bitmap
14558     *
14559     * @see #setDrawingCacheEnabled(boolean)
14560     * @see #buildDrawingCache()
14561     * @see #getDrawingCache()
14562     */
14563    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
14564        if (color != mDrawingCacheBackgroundColor) {
14565            mDrawingCacheBackgroundColor = color;
14566            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
14567        }
14568    }
14569
14570    /**
14571     * @see #setDrawingCacheBackgroundColor(int)
14572     *
14573     * @return The background color to used for the drawing cache's bitmap
14574     */
14575    @ColorInt
14576    public int getDrawingCacheBackgroundColor() {
14577        return mDrawingCacheBackgroundColor;
14578    }
14579
14580    /**
14581     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
14582     *
14583     * @see #buildDrawingCache(boolean)
14584     */
14585    public void buildDrawingCache() {
14586        buildDrawingCache(false);
14587    }
14588
14589    /**
14590     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
14591     *
14592     * <p>If you call {@link #buildDrawingCache()} manually without calling
14593     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
14594     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
14595     *
14596     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
14597     * this method will create a bitmap of the same size as this view. Because this bitmap
14598     * will be drawn scaled by the parent ViewGroup, the result on screen might show
14599     * scaling artifacts. To avoid such artifacts, you should call this method by setting
14600     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
14601     * size than the view. This implies that your application must be able to handle this
14602     * size.</p>
14603     *
14604     * <p>You should avoid calling this method when hardware acceleration is enabled. If
14605     * you do not need the drawing cache bitmap, calling this method will increase memory
14606     * usage and cause the view to be rendered in software once, thus negatively impacting
14607     * performance.</p>
14608     *
14609     * @see #getDrawingCache()
14610     * @see #destroyDrawingCache()
14611     */
14612    public void buildDrawingCache(boolean autoScale) {
14613        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
14614                mDrawingCache == null : mUnscaledDrawingCache == null)) {
14615            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
14616                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
14617                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
14618            }
14619            try {
14620                buildDrawingCacheImpl(autoScale);
14621            } finally {
14622                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
14623            }
14624        }
14625    }
14626
14627    /**
14628     * private, internal implementation of buildDrawingCache, used to enable tracing
14629     */
14630    private void buildDrawingCacheImpl(boolean autoScale) {
14631        mCachingFailed = false;
14632
14633        int width = mRight - mLeft;
14634        int height = mBottom - mTop;
14635
14636        final AttachInfo attachInfo = mAttachInfo;
14637        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
14638
14639        if (autoScale && scalingRequired) {
14640            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
14641            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
14642        }
14643
14644        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
14645        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
14646        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
14647
14648        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
14649        final long drawingCacheSize =
14650                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
14651        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
14652            if (width > 0 && height > 0) {
14653                Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
14654                        + projectedBitmapSize + " bytes, only "
14655                        + drawingCacheSize + " available");
14656            }
14657            destroyDrawingCache();
14658            mCachingFailed = true;
14659            return;
14660        }
14661
14662        boolean clear = true;
14663        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
14664
14665        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
14666            Bitmap.Config quality;
14667            if (!opaque) {
14668                // Never pick ARGB_4444 because it looks awful
14669                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
14670                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
14671                    case DRAWING_CACHE_QUALITY_AUTO:
14672                    case DRAWING_CACHE_QUALITY_LOW:
14673                    case DRAWING_CACHE_QUALITY_HIGH:
14674                    default:
14675                        quality = Bitmap.Config.ARGB_8888;
14676                        break;
14677                }
14678            } else {
14679                // Optimization for translucent windows
14680                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
14681                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
14682            }
14683
14684            // Try to cleanup memory
14685            if (bitmap != null) bitmap.recycle();
14686
14687            try {
14688                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14689                        width, height, quality);
14690                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
14691                if (autoScale) {
14692                    mDrawingCache = bitmap;
14693                } else {
14694                    mUnscaledDrawingCache = bitmap;
14695                }
14696                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
14697            } catch (OutOfMemoryError e) {
14698                // If there is not enough memory to create the bitmap cache, just
14699                // ignore the issue as bitmap caches are not required to draw the
14700                // view hierarchy
14701                if (autoScale) {
14702                    mDrawingCache = null;
14703                } else {
14704                    mUnscaledDrawingCache = null;
14705                }
14706                mCachingFailed = true;
14707                return;
14708            }
14709
14710            clear = drawingCacheBackgroundColor != 0;
14711        }
14712
14713        Canvas canvas;
14714        if (attachInfo != null) {
14715            canvas = attachInfo.mCanvas;
14716            if (canvas == null) {
14717                canvas = new Canvas();
14718            }
14719            canvas.setBitmap(bitmap);
14720            // Temporarily clobber the cached Canvas in case one of our children
14721            // is also using a drawing cache. Without this, the children would
14722            // steal the canvas by attaching their own bitmap to it and bad, bad
14723            // thing would happen (invisible views, corrupted drawings, etc.)
14724            attachInfo.mCanvas = null;
14725        } else {
14726            // This case should hopefully never or seldom happen
14727            canvas = new Canvas(bitmap);
14728        }
14729
14730        if (clear) {
14731            bitmap.eraseColor(drawingCacheBackgroundColor);
14732        }
14733
14734        computeScroll();
14735        final int restoreCount = canvas.save();
14736
14737        if (autoScale && scalingRequired) {
14738            final float scale = attachInfo.mApplicationScale;
14739            canvas.scale(scale, scale);
14740        }
14741
14742        canvas.translate(-mScrollX, -mScrollY);
14743
14744        mPrivateFlags |= PFLAG_DRAWN;
14745        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
14746                mLayerType != LAYER_TYPE_NONE) {
14747            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
14748        }
14749
14750        // Fast path for layouts with no backgrounds
14751        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14752            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14753            dispatchDraw(canvas);
14754            if (mOverlay != null && !mOverlay.isEmpty()) {
14755                mOverlay.getOverlayView().draw(canvas);
14756            }
14757        } else {
14758            draw(canvas);
14759        }
14760
14761        canvas.restoreToCount(restoreCount);
14762        canvas.setBitmap(null);
14763
14764        if (attachInfo != null) {
14765            // Restore the cached Canvas for our siblings
14766            attachInfo.mCanvas = canvas;
14767        }
14768    }
14769
14770    /**
14771     * Create a snapshot of the view into a bitmap.  We should probably make
14772     * some form of this public, but should think about the API.
14773     */
14774    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
14775        int width = mRight - mLeft;
14776        int height = mBottom - mTop;
14777
14778        final AttachInfo attachInfo = mAttachInfo;
14779        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
14780        width = (int) ((width * scale) + 0.5f);
14781        height = (int) ((height * scale) + 0.5f);
14782
14783        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
14784                width > 0 ? width : 1, height > 0 ? height : 1, quality);
14785        if (bitmap == null) {
14786            throw new OutOfMemoryError();
14787        }
14788
14789        Resources resources = getResources();
14790        if (resources != null) {
14791            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
14792        }
14793
14794        Canvas canvas;
14795        if (attachInfo != null) {
14796            canvas = attachInfo.mCanvas;
14797            if (canvas == null) {
14798                canvas = new Canvas();
14799            }
14800            canvas.setBitmap(bitmap);
14801            // Temporarily clobber the cached Canvas in case one of our children
14802            // is also using a drawing cache. Without this, the children would
14803            // steal the canvas by attaching their own bitmap to it and bad, bad
14804            // things would happen (invisible views, corrupted drawings, etc.)
14805            attachInfo.mCanvas = null;
14806        } else {
14807            // This case should hopefully never or seldom happen
14808            canvas = new Canvas(bitmap);
14809        }
14810
14811        if ((backgroundColor & 0xff000000) != 0) {
14812            bitmap.eraseColor(backgroundColor);
14813        }
14814
14815        computeScroll();
14816        final int restoreCount = canvas.save();
14817        canvas.scale(scale, scale);
14818        canvas.translate(-mScrollX, -mScrollY);
14819
14820        // Temporarily remove the dirty mask
14821        int flags = mPrivateFlags;
14822        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
14823
14824        // Fast path for layouts with no backgrounds
14825        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
14826            dispatchDraw(canvas);
14827            if (mOverlay != null && !mOverlay.isEmpty()) {
14828                mOverlay.getOverlayView().draw(canvas);
14829            }
14830        } else {
14831            draw(canvas);
14832        }
14833
14834        mPrivateFlags = flags;
14835
14836        canvas.restoreToCount(restoreCount);
14837        canvas.setBitmap(null);
14838
14839        if (attachInfo != null) {
14840            // Restore the cached Canvas for our siblings
14841            attachInfo.mCanvas = canvas;
14842        }
14843
14844        return bitmap;
14845    }
14846
14847    /**
14848     * Indicates whether this View is currently in edit mode. A View is usually
14849     * in edit mode when displayed within a developer tool. For instance, if
14850     * this View is being drawn by a visual user interface builder, this method
14851     * should return true.
14852     *
14853     * Subclasses should check the return value of this method to provide
14854     * different behaviors if their normal behavior might interfere with the
14855     * host environment. For instance: the class spawns a thread in its
14856     * constructor, the drawing code relies on device-specific features, etc.
14857     *
14858     * This method is usually checked in the drawing code of custom widgets.
14859     *
14860     * @return True if this View is in edit mode, false otherwise.
14861     */
14862    public boolean isInEditMode() {
14863        return false;
14864    }
14865
14866    /**
14867     * If the View draws content inside its padding and enables fading edges,
14868     * it needs to support padding offsets. Padding offsets are added to the
14869     * fading edges to extend the length of the fade so that it covers pixels
14870     * drawn inside the padding.
14871     *
14872     * Subclasses of this class should override this method if they need
14873     * to draw content inside the padding.
14874     *
14875     * @return True if padding offset must be applied, false otherwise.
14876     *
14877     * @see #getLeftPaddingOffset()
14878     * @see #getRightPaddingOffset()
14879     * @see #getTopPaddingOffset()
14880     * @see #getBottomPaddingOffset()
14881     *
14882     * @since CURRENT
14883     */
14884    protected boolean isPaddingOffsetRequired() {
14885        return false;
14886    }
14887
14888    /**
14889     * Amount by which to extend the left fading region. Called only when
14890     * {@link #isPaddingOffsetRequired()} returns true.
14891     *
14892     * @return The left padding offset in pixels.
14893     *
14894     * @see #isPaddingOffsetRequired()
14895     *
14896     * @since CURRENT
14897     */
14898    protected int getLeftPaddingOffset() {
14899        return 0;
14900    }
14901
14902    /**
14903     * Amount by which to extend the right fading region. Called only when
14904     * {@link #isPaddingOffsetRequired()} returns true.
14905     *
14906     * @return The right padding offset in pixels.
14907     *
14908     * @see #isPaddingOffsetRequired()
14909     *
14910     * @since CURRENT
14911     */
14912    protected int getRightPaddingOffset() {
14913        return 0;
14914    }
14915
14916    /**
14917     * Amount by which to extend the top fading region. Called only when
14918     * {@link #isPaddingOffsetRequired()} returns true.
14919     *
14920     * @return The top padding offset in pixels.
14921     *
14922     * @see #isPaddingOffsetRequired()
14923     *
14924     * @since CURRENT
14925     */
14926    protected int getTopPaddingOffset() {
14927        return 0;
14928    }
14929
14930    /**
14931     * Amount by which to extend the bottom fading region. Called only when
14932     * {@link #isPaddingOffsetRequired()} returns true.
14933     *
14934     * @return The bottom padding offset in pixels.
14935     *
14936     * @see #isPaddingOffsetRequired()
14937     *
14938     * @since CURRENT
14939     */
14940    protected int getBottomPaddingOffset() {
14941        return 0;
14942    }
14943
14944    /**
14945     * @hide
14946     * @param offsetRequired
14947     */
14948    protected int getFadeTop(boolean offsetRequired) {
14949        int top = mPaddingTop;
14950        if (offsetRequired) top += getTopPaddingOffset();
14951        return top;
14952    }
14953
14954    /**
14955     * @hide
14956     * @param offsetRequired
14957     */
14958    protected int getFadeHeight(boolean offsetRequired) {
14959        int padding = mPaddingTop;
14960        if (offsetRequired) padding += getTopPaddingOffset();
14961        return mBottom - mTop - mPaddingBottom - padding;
14962    }
14963
14964    /**
14965     * <p>Indicates whether this view is attached to a hardware accelerated
14966     * window or not.</p>
14967     *
14968     * <p>Even if this method returns true, it does not mean that every call
14969     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
14970     * accelerated {@link android.graphics.Canvas}. For instance, if this view
14971     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
14972     * window is hardware accelerated,
14973     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
14974     * return false, and this method will return true.</p>
14975     *
14976     * @return True if the view is attached to a window and the window is
14977     *         hardware accelerated; false in any other case.
14978     */
14979    @ViewDebug.ExportedProperty(category = "drawing")
14980    public boolean isHardwareAccelerated() {
14981        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
14982    }
14983
14984    /**
14985     * Sets a rectangular area on this view to which the view will be clipped
14986     * when it is drawn. Setting the value to null will remove the clip bounds
14987     * and the view will draw normally, using its full bounds.
14988     *
14989     * @param clipBounds The rectangular area, in the local coordinates of
14990     * this view, to which future drawing operations will be clipped.
14991     */
14992    public void setClipBounds(Rect clipBounds) {
14993        if (clipBounds == mClipBounds
14994                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
14995            return;
14996        }
14997        if (clipBounds != null) {
14998            if (mClipBounds == null) {
14999                mClipBounds = new Rect(clipBounds);
15000            } else {
15001                mClipBounds.set(clipBounds);
15002            }
15003        } else {
15004            mClipBounds = null;
15005        }
15006        mRenderNode.setClipBounds(mClipBounds);
15007        invalidateViewProperty(false, false);
15008    }
15009
15010    /**
15011     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15012     *
15013     * @return A copy of the current clip bounds if clip bounds are set,
15014     * otherwise null.
15015     */
15016    public Rect getClipBounds() {
15017        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15018    }
15019
15020    /**
15021     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15022     * case of an active Animation being run on the view.
15023     */
15024    private boolean drawAnimation(ViewGroup parent, long drawingTime,
15025            Animation a, boolean scalingRequired) {
15026        Transformation invalidationTransform;
15027        final int flags = parent.mGroupFlags;
15028        final boolean initialized = a.isInitialized();
15029        if (!initialized) {
15030            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15031            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15032            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15033            onAnimationStart();
15034        }
15035
15036        final Transformation t = parent.getChildTransformation();
15037        boolean more = a.getTransformation(drawingTime, t, 1f);
15038        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15039            if (parent.mInvalidationTransformation == null) {
15040                parent.mInvalidationTransformation = new Transformation();
15041            }
15042            invalidationTransform = parent.mInvalidationTransformation;
15043            a.getTransformation(drawingTime, invalidationTransform, 1f);
15044        } else {
15045            invalidationTransform = t;
15046        }
15047
15048        if (more) {
15049            if (!a.willChangeBounds()) {
15050                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15051                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15052                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15053                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15054                    // The child need to draw an animation, potentially offscreen, so
15055                    // make sure we do not cancel invalidate requests
15056                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15057                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15058                }
15059            } else {
15060                if (parent.mInvalidateRegion == null) {
15061                    parent.mInvalidateRegion = new RectF();
15062                }
15063                final RectF region = parent.mInvalidateRegion;
15064                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15065                        invalidationTransform);
15066
15067                // The child need to draw an animation, potentially offscreen, so
15068                // make sure we do not cancel invalidate requests
15069                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15070
15071                final int left = mLeft + (int) region.left;
15072                final int top = mTop + (int) region.top;
15073                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15074                        top + (int) (region.height() + .5f));
15075            }
15076        }
15077        return more;
15078    }
15079
15080    /**
15081     * This method is called by getDisplayList() when a display list is recorded for a View.
15082     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15083     */
15084    void setDisplayListProperties(RenderNode renderNode) {
15085        if (renderNode != null) {
15086            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15087            renderNode.setClipToBounds(mParent instanceof ViewGroup
15088                    && ((ViewGroup) mParent).getClipChildren());
15089
15090            float alpha = 1;
15091            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15092                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15093                ViewGroup parentVG = (ViewGroup) mParent;
15094                final Transformation t = parentVG.getChildTransformation();
15095                if (parentVG.getChildStaticTransformation(this, t)) {
15096                    final int transformType = t.getTransformationType();
15097                    if (transformType != Transformation.TYPE_IDENTITY) {
15098                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15099                            alpha = t.getAlpha();
15100                        }
15101                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15102                            renderNode.setStaticMatrix(t.getMatrix());
15103                        }
15104                    }
15105                }
15106            }
15107            if (mTransformationInfo != null) {
15108                alpha *= getFinalAlpha();
15109                if (alpha < 1) {
15110                    final int multipliedAlpha = (int) (255 * alpha);
15111                    if (onSetAlpha(multipliedAlpha)) {
15112                        alpha = 1;
15113                    }
15114                }
15115                renderNode.setAlpha(alpha);
15116            } else if (alpha < 1) {
15117                renderNode.setAlpha(alpha);
15118            }
15119        }
15120    }
15121
15122    /**
15123     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15124     * This draw() method is an implementation detail and is not intended to be overridden or
15125     * to be called from anywhere else other than ViewGroup.drawChild().
15126     */
15127    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15128        boolean usingRenderNodeProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15129        boolean more = false;
15130        final boolean childHasIdentityMatrix = hasIdentityMatrix();
15131        final int flags = parent.mGroupFlags;
15132
15133        if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
15134            parent.getChildTransformation().clear();
15135            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15136        }
15137
15138        Transformation transformToApply = null;
15139        boolean concatMatrix = false;
15140
15141        boolean scalingRequired = false;
15142        boolean caching;
15143        int layerType = getLayerType();
15144
15145        final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
15146        if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
15147                (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
15148            caching = true;
15149            // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
15150            if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
15151        } else {
15152            caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
15153        }
15154
15155        final Animation a = getAnimation();
15156        if (a != null) {
15157            more = drawAnimation(parent, drawingTime, a, scalingRequired);
15158            concatMatrix = a.willChangeTransformationMatrix();
15159            if (concatMatrix) {
15160                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15161            }
15162            transformToApply = parent.getChildTransformation();
15163        } else {
15164            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15165                // No longer animating: clear out old animation matrix
15166                mRenderNode.setAnimationMatrix(null);
15167                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15168            }
15169            if (!usingRenderNodeProperties &&
15170                    (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15171                final Transformation t = parent.getChildTransformation();
15172                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15173                if (hasTransform) {
15174                    final int transformType = t.getTransformationType();
15175                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15176                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15177                }
15178            }
15179        }
15180
15181        concatMatrix |= !childHasIdentityMatrix;
15182
15183        // Sets the flag as early as possible to allow draw() implementations
15184        // to call invalidate() successfully when doing animations
15185        mPrivateFlags |= PFLAG_DRAWN;
15186
15187        if (!concatMatrix &&
15188                (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15189                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15190                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15191                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15192            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15193            return more;
15194        }
15195        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15196
15197        if (hardwareAccelerated) {
15198            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15199            // retain the flag's value temporarily in the mRecreateDisplayList flag
15200            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
15201            mPrivateFlags &= ~PFLAG_INVALIDATED;
15202        }
15203
15204        RenderNode renderNode = null;
15205        Bitmap cache = null;
15206        boolean hasDisplayList = false;
15207        if (caching) {
15208            if (!hardwareAccelerated) {
15209                if (layerType != LAYER_TYPE_NONE) {
15210                    layerType = LAYER_TYPE_SOFTWARE;
15211                    buildDrawingCache(true);
15212                }
15213                cache = getDrawingCache(true);
15214            } else {
15215                switch (layerType) {
15216                    case LAYER_TYPE_SOFTWARE:
15217                        if (usingRenderNodeProperties) {
15218                            hasDisplayList = canHaveDisplayList();
15219                        } else {
15220                            buildDrawingCache(true);
15221                            cache = getDrawingCache(true);
15222                        }
15223                        break;
15224                    case LAYER_TYPE_HARDWARE:
15225                        if (usingRenderNodeProperties) {
15226                            hasDisplayList = canHaveDisplayList();
15227                        }
15228                        break;
15229                    case LAYER_TYPE_NONE:
15230                        // Delay getting the display list until animation-driven alpha values are
15231                        // set up and possibly passed on to the view
15232                        hasDisplayList = canHaveDisplayList();
15233                        break;
15234                }
15235            }
15236        }
15237        usingRenderNodeProperties &= hasDisplayList;
15238        if (usingRenderNodeProperties) {
15239            renderNode = getDisplayList();
15240            if (!renderNode.isValid()) {
15241                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15242                // to getDisplayList(), the display list will be marked invalid and we should not
15243                // try to use it again.
15244                renderNode = null;
15245                hasDisplayList = false;
15246                usingRenderNodeProperties = false;
15247            }
15248        }
15249
15250        int sx = 0;
15251        int sy = 0;
15252        if (!hasDisplayList) {
15253            computeScroll();
15254            sx = mScrollX;
15255            sy = mScrollY;
15256        }
15257
15258        final boolean hasNoCache = cache == null || hasDisplayList;
15259        final boolean offsetForScroll = cache == null && !hasDisplayList &&
15260                layerType != LAYER_TYPE_HARDWARE;
15261
15262        int restoreTo = -1;
15263        if (!usingRenderNodeProperties || transformToApply != null) {
15264            restoreTo = canvas.save();
15265        }
15266        if (offsetForScroll) {
15267            canvas.translate(mLeft - sx, mTop - sy);
15268        } else {
15269            if (!usingRenderNodeProperties) {
15270                canvas.translate(mLeft, mTop);
15271            }
15272            if (scalingRequired) {
15273                if (usingRenderNodeProperties) {
15274                    // TODO: Might not need this if we put everything inside the DL
15275                    restoreTo = canvas.save();
15276                }
15277                // mAttachInfo cannot be null, otherwise scalingRequired == false
15278                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15279                canvas.scale(scale, scale);
15280            }
15281        }
15282
15283        float alpha = usingRenderNodeProperties ? 1 : (getAlpha() * getTransitionAlpha());
15284        if (transformToApply != null || alpha < 1 ||  !hasIdentityMatrix() ||
15285                (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15286            if (transformToApply != null || !childHasIdentityMatrix) {
15287                int transX = 0;
15288                int transY = 0;
15289
15290                if (offsetForScroll) {
15291                    transX = -sx;
15292                    transY = -sy;
15293                }
15294
15295                if (transformToApply != null) {
15296                    if (concatMatrix) {
15297                        if (usingRenderNodeProperties) {
15298                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
15299                        } else {
15300                            // Undo the scroll translation, apply the transformation matrix,
15301                            // then redo the scroll translate to get the correct result.
15302                            canvas.translate(-transX, -transY);
15303                            canvas.concat(transformToApply.getMatrix());
15304                            canvas.translate(transX, transY);
15305                        }
15306                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15307                    }
15308
15309                    float transformAlpha = transformToApply.getAlpha();
15310                    if (transformAlpha < 1) {
15311                        alpha *= transformAlpha;
15312                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15313                    }
15314                }
15315
15316                if (!childHasIdentityMatrix && !usingRenderNodeProperties) {
15317                    canvas.translate(-transX, -transY);
15318                    canvas.concat(getMatrix());
15319                    canvas.translate(transX, transY);
15320                }
15321            }
15322
15323            // Deal with alpha if it is or used to be <1
15324            if (alpha < 1 ||
15325                    (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
15326                if (alpha < 1) {
15327                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15328                } else {
15329                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
15330                }
15331                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15332                if (hasNoCache) {
15333                    final int multipliedAlpha = (int) (255 * alpha);
15334                    if (!onSetAlpha(multipliedAlpha)) {
15335                        int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15336                        if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
15337                                layerType != LAYER_TYPE_NONE) {
15338                            layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
15339                        }
15340                        if (usingRenderNodeProperties) {
15341                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
15342                        } else  if (layerType == LAYER_TYPE_NONE) {
15343                            final int scrollX = hasDisplayList ? 0 : sx;
15344                            final int scrollY = hasDisplayList ? 0 : sy;
15345                            canvas.saveLayerAlpha(scrollX, scrollY,
15346                                    scrollX + (mRight - mLeft), scrollY + (mBottom - mTop),
15347                                    multipliedAlpha, layerFlags);
15348                        }
15349                    } else {
15350                        // Alpha is handled by the child directly, clobber the layer's alpha
15351                        mPrivateFlags |= PFLAG_ALPHA_SET;
15352                    }
15353                }
15354            }
15355        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15356            onSetAlpha(255);
15357            mPrivateFlags &= ~PFLAG_ALPHA_SET;
15358        }
15359
15360        if (!usingRenderNodeProperties) {
15361            // apply clips directly, since RenderNode won't do it for this draw
15362            if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN
15363                    && cache == null) {
15364                if (offsetForScroll) {
15365                    canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
15366                } else {
15367                    if (!scalingRequired || cache == null) {
15368                        canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
15369                    } else {
15370                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
15371                    }
15372                }
15373            }
15374
15375            if (mClipBounds != null) {
15376                // clip bounds ignore scroll
15377                canvas.clipRect(mClipBounds);
15378            }
15379        }
15380
15381
15382
15383        if (!usingRenderNodeProperties && hasDisplayList) {
15384            renderNode = getDisplayList();
15385            if (!renderNode.isValid()) {
15386                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15387                // to getDisplayList(), the display list will be marked invalid and we should not
15388                // try to use it again.
15389                renderNode = null;
15390                hasDisplayList = false;
15391            }
15392        }
15393
15394        if (hasNoCache) {
15395            boolean layerRendered = false;
15396            if (layerType == LAYER_TYPE_HARDWARE && !usingRenderNodeProperties) {
15397                final HardwareLayer layer = getHardwareLayer();
15398                if (layer != null && layer.isValid()) {
15399                    int restoreAlpha = mLayerPaint.getAlpha();
15400                    mLayerPaint.setAlpha((int) (alpha * 255));
15401                    ((DisplayListCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
15402                    mLayerPaint.setAlpha(restoreAlpha);
15403                    layerRendered = true;
15404                } else {
15405                    final int scrollX = hasDisplayList ? 0 : sx;
15406                    final int scrollY = hasDisplayList ? 0 : sy;
15407                    canvas.saveLayer(scrollX, scrollY,
15408                            scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
15409                            Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
15410                }
15411            }
15412
15413            if (!layerRendered) {
15414                if (!hasDisplayList) {
15415                    // Fast path for layouts with no backgrounds
15416                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15417                        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15418                        dispatchDraw(canvas);
15419                    } else {
15420                        draw(canvas);
15421                    }
15422                } else {
15423                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15424                    ((DisplayListCanvas) canvas).drawRenderNode(renderNode, flags);
15425                }
15426            }
15427        } else if (cache != null) {
15428            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15429            Paint cachePaint;
15430            int restoreAlpha = 0;
15431
15432            if (layerType == LAYER_TYPE_NONE) {
15433                cachePaint = parent.mCachePaint;
15434                if (cachePaint == null) {
15435                    cachePaint = new Paint();
15436                    cachePaint.setDither(false);
15437                    parent.mCachePaint = cachePaint;
15438                }
15439            } else {
15440                cachePaint = mLayerPaint;
15441                restoreAlpha = mLayerPaint.getAlpha();
15442            }
15443            cachePaint.setAlpha((int) (alpha * 255));
15444            canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
15445            cachePaint.setAlpha(restoreAlpha);
15446        }
15447
15448        if (restoreTo >= 0) {
15449            canvas.restoreToCount(restoreTo);
15450        }
15451
15452        if (a != null && !more) {
15453            if (!hardwareAccelerated && !a.getFillAfter()) {
15454                onSetAlpha(255);
15455            }
15456            parent.finishAnimatingView(this, a);
15457        }
15458
15459        if (more && hardwareAccelerated) {
15460            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
15461                // alpha animations should cause the child to recreate its display list
15462                invalidate(true);
15463            }
15464        }
15465
15466        mRecreateDisplayList = false;
15467
15468        return more;
15469    }
15470
15471    /**
15472     * Manually render this view (and all of its children) to the given Canvas.
15473     * The view must have already done a full layout before this function is
15474     * called.  When implementing a view, implement
15475     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
15476     * If you do need to override this method, call the superclass version.
15477     *
15478     * @param canvas The Canvas to which the View is rendered.
15479     */
15480    @CallSuper
15481    public void draw(Canvas canvas) {
15482        final int privateFlags = mPrivateFlags;
15483        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
15484                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
15485        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
15486
15487        /*
15488         * Draw traversal performs several drawing steps which must be executed
15489         * in the appropriate order:
15490         *
15491         *      1. Draw the background
15492         *      2. If necessary, save the canvas' layers to prepare for fading
15493         *      3. Draw view's content
15494         *      4. Draw children
15495         *      5. If necessary, draw the fading edges and restore layers
15496         *      6. Draw decorations (scrollbars for instance)
15497         */
15498
15499        // Step 1, draw the background, if needed
15500        int saveCount;
15501
15502        if (!dirtyOpaque) {
15503            drawBackground(canvas);
15504        }
15505
15506        // skip step 2 & 5 if possible (common case)
15507        final int viewFlags = mViewFlags;
15508        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
15509        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
15510        if (!verticalEdges && !horizontalEdges) {
15511            // Step 3, draw the content
15512            if (!dirtyOpaque) onDraw(canvas);
15513
15514            // Step 4, draw the children
15515            dispatchDraw(canvas);
15516
15517            // Overlay is part of the content and draws beneath Foreground
15518            if (mOverlay != null && !mOverlay.isEmpty()) {
15519                mOverlay.getOverlayView().dispatchDraw(canvas);
15520            }
15521
15522            // Step 6, draw decorations (foreground, scrollbars)
15523            onDrawForeground(canvas);
15524
15525            // we're done...
15526            return;
15527        }
15528
15529        /*
15530         * Here we do the full fledged routine...
15531         * (this is an uncommon case where speed matters less,
15532         * this is why we repeat some of the tests that have been
15533         * done above)
15534         */
15535
15536        boolean drawTop = false;
15537        boolean drawBottom = false;
15538        boolean drawLeft = false;
15539        boolean drawRight = false;
15540
15541        float topFadeStrength = 0.0f;
15542        float bottomFadeStrength = 0.0f;
15543        float leftFadeStrength = 0.0f;
15544        float rightFadeStrength = 0.0f;
15545
15546        // Step 2, save the canvas' layers
15547        int paddingLeft = mPaddingLeft;
15548
15549        final boolean offsetRequired = isPaddingOffsetRequired();
15550        if (offsetRequired) {
15551            paddingLeft += getLeftPaddingOffset();
15552        }
15553
15554        int left = mScrollX + paddingLeft;
15555        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
15556        int top = mScrollY + getFadeTop(offsetRequired);
15557        int bottom = top + getFadeHeight(offsetRequired);
15558
15559        if (offsetRequired) {
15560            right += getRightPaddingOffset();
15561            bottom += getBottomPaddingOffset();
15562        }
15563
15564        final ScrollabilityCache scrollabilityCache = mScrollCache;
15565        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
15566        int length = (int) fadeHeight;
15567
15568        // clip the fade length if top and bottom fades overlap
15569        // overlapping fades produce odd-looking artifacts
15570        if (verticalEdges && (top + length > bottom - length)) {
15571            length = (bottom - top) / 2;
15572        }
15573
15574        // also clip horizontal fades if necessary
15575        if (horizontalEdges && (left + length > right - length)) {
15576            length = (right - left) / 2;
15577        }
15578
15579        if (verticalEdges) {
15580            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
15581            drawTop = topFadeStrength * fadeHeight > 1.0f;
15582            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
15583            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
15584        }
15585
15586        if (horizontalEdges) {
15587            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
15588            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
15589            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
15590            drawRight = rightFadeStrength * fadeHeight > 1.0f;
15591        }
15592
15593        saveCount = canvas.getSaveCount();
15594
15595        int solidColor = getSolidColor();
15596        if (solidColor == 0) {
15597            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
15598
15599            if (drawTop) {
15600                canvas.saveLayer(left, top, right, top + length, null, flags);
15601            }
15602
15603            if (drawBottom) {
15604                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
15605            }
15606
15607            if (drawLeft) {
15608                canvas.saveLayer(left, top, left + length, bottom, null, flags);
15609            }
15610
15611            if (drawRight) {
15612                canvas.saveLayer(right - length, top, right, bottom, null, flags);
15613            }
15614        } else {
15615            scrollabilityCache.setFadeColor(solidColor);
15616        }
15617
15618        // Step 3, draw the content
15619        if (!dirtyOpaque) onDraw(canvas);
15620
15621        // Step 4, draw the children
15622        dispatchDraw(canvas);
15623
15624        // Step 5, draw the fade effect and restore layers
15625        final Paint p = scrollabilityCache.paint;
15626        final Matrix matrix = scrollabilityCache.matrix;
15627        final Shader fade = scrollabilityCache.shader;
15628
15629        if (drawTop) {
15630            matrix.setScale(1, fadeHeight * topFadeStrength);
15631            matrix.postTranslate(left, top);
15632            fade.setLocalMatrix(matrix);
15633            p.setShader(fade);
15634            canvas.drawRect(left, top, right, top + length, p);
15635        }
15636
15637        if (drawBottom) {
15638            matrix.setScale(1, fadeHeight * bottomFadeStrength);
15639            matrix.postRotate(180);
15640            matrix.postTranslate(left, bottom);
15641            fade.setLocalMatrix(matrix);
15642            p.setShader(fade);
15643            canvas.drawRect(left, bottom - length, right, bottom, p);
15644        }
15645
15646        if (drawLeft) {
15647            matrix.setScale(1, fadeHeight * leftFadeStrength);
15648            matrix.postRotate(-90);
15649            matrix.postTranslate(left, top);
15650            fade.setLocalMatrix(matrix);
15651            p.setShader(fade);
15652            canvas.drawRect(left, top, left + length, bottom, p);
15653        }
15654
15655        if (drawRight) {
15656            matrix.setScale(1, fadeHeight * rightFadeStrength);
15657            matrix.postRotate(90);
15658            matrix.postTranslate(right, top);
15659            fade.setLocalMatrix(matrix);
15660            p.setShader(fade);
15661            canvas.drawRect(right - length, top, right, bottom, p);
15662        }
15663
15664        canvas.restoreToCount(saveCount);
15665
15666        // Overlay is part of the content and draws beneath Foreground
15667        if (mOverlay != null && !mOverlay.isEmpty()) {
15668            mOverlay.getOverlayView().dispatchDraw(canvas);
15669        }
15670
15671        // Step 6, draw decorations (foreground, scrollbars)
15672        onDrawForeground(canvas);
15673    }
15674
15675    /**
15676     * Draws the background onto the specified canvas.
15677     *
15678     * @param canvas Canvas on which to draw the background
15679     */
15680    private void drawBackground(Canvas canvas) {
15681        final Drawable background = mBackground;
15682        if (background == null) {
15683            return;
15684        }
15685
15686        if (mBackgroundSizeChanged) {
15687            background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
15688            mBackgroundSizeChanged = false;
15689            rebuildOutline();
15690        }
15691
15692        // Attempt to use a display list if requested.
15693        if (canvas.isHardwareAccelerated() && mAttachInfo != null
15694                && mAttachInfo.mHardwareRenderer != null) {
15695            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
15696
15697            final RenderNode renderNode = mBackgroundRenderNode;
15698            if (renderNode != null && renderNode.isValid()) {
15699                setBackgroundRenderNodeProperties(renderNode);
15700                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
15701                return;
15702            }
15703        }
15704
15705        final int scrollX = mScrollX;
15706        final int scrollY = mScrollY;
15707        if ((scrollX | scrollY) == 0) {
15708            background.draw(canvas);
15709        } else {
15710            canvas.translate(scrollX, scrollY);
15711            background.draw(canvas);
15712            canvas.translate(-scrollX, -scrollY);
15713        }
15714    }
15715
15716    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
15717        renderNode.setTranslationX(mScrollX);
15718        renderNode.setTranslationY(mScrollY);
15719    }
15720
15721    /**
15722     * Creates a new display list or updates the existing display list for the
15723     * specified Drawable.
15724     *
15725     * @param drawable Drawable for which to create a display list
15726     * @param renderNode Existing RenderNode, or {@code null}
15727     * @return A valid display list for the specified drawable
15728     */
15729    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
15730        if (renderNode == null) {
15731            renderNode = RenderNode.create(drawable.getClass().getName(), this);
15732        }
15733
15734        final Rect bounds = drawable.getBounds();
15735        final int width = bounds.width();
15736        final int height = bounds.height();
15737        final DisplayListCanvas canvas = renderNode.start(width, height);
15738
15739        // Reverse left/top translation done by drawable canvas, which will
15740        // instead be applied by rendernode's LTRB bounds below. This way, the
15741        // drawable's bounds match with its rendernode bounds and its content
15742        // will lie within those bounds in the rendernode tree.
15743        canvas.translate(-bounds.left, -bounds.top);
15744
15745        try {
15746            drawable.draw(canvas);
15747        } finally {
15748            renderNode.end(canvas);
15749        }
15750
15751        // Set up drawable properties that are view-independent.
15752        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
15753        renderNode.setProjectBackwards(drawable.isProjected());
15754        renderNode.setProjectionReceiver(true);
15755        renderNode.setClipToBounds(false);
15756        return renderNode;
15757    }
15758
15759    /**
15760     * Returns the overlay for this view, creating it if it does not yet exist.
15761     * Adding drawables to the overlay will cause them to be displayed whenever
15762     * the view itself is redrawn. Objects in the overlay should be actively
15763     * managed: remove them when they should not be displayed anymore. The
15764     * overlay will always have the same size as its host view.
15765     *
15766     * <p>Note: Overlays do not currently work correctly with {@link
15767     * SurfaceView} or {@link TextureView}; contents in overlays for these
15768     * types of views may not display correctly.</p>
15769     *
15770     * @return The ViewOverlay object for this view.
15771     * @see ViewOverlay
15772     */
15773    public ViewOverlay getOverlay() {
15774        if (mOverlay == null) {
15775            mOverlay = new ViewOverlay(mContext, this);
15776        }
15777        return mOverlay;
15778    }
15779
15780    /**
15781     * Override this if your view is known to always be drawn on top of a solid color background,
15782     * and needs to draw fading edges. Returning a non-zero color enables the view system to
15783     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
15784     * should be set to 0xFF.
15785     *
15786     * @see #setVerticalFadingEdgeEnabled(boolean)
15787     * @see #setHorizontalFadingEdgeEnabled(boolean)
15788     *
15789     * @return The known solid color background for this view, or 0 if the color may vary
15790     */
15791    @ViewDebug.ExportedProperty(category = "drawing")
15792    @ColorInt
15793    public int getSolidColor() {
15794        return 0;
15795    }
15796
15797    /**
15798     * Build a human readable string representation of the specified view flags.
15799     *
15800     * @param flags the view flags to convert to a string
15801     * @return a String representing the supplied flags
15802     */
15803    private static String printFlags(int flags) {
15804        String output = "";
15805        int numFlags = 0;
15806        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
15807            output += "TAKES_FOCUS";
15808            numFlags++;
15809        }
15810
15811        switch (flags & VISIBILITY_MASK) {
15812        case INVISIBLE:
15813            if (numFlags > 0) {
15814                output += " ";
15815            }
15816            output += "INVISIBLE";
15817            // USELESS HERE numFlags++;
15818            break;
15819        case GONE:
15820            if (numFlags > 0) {
15821                output += " ";
15822            }
15823            output += "GONE";
15824            // USELESS HERE numFlags++;
15825            break;
15826        default:
15827            break;
15828        }
15829        return output;
15830    }
15831
15832    /**
15833     * Build a human readable string representation of the specified private
15834     * view flags.
15835     *
15836     * @param privateFlags the private view flags to convert to a string
15837     * @return a String representing the supplied flags
15838     */
15839    private static String printPrivateFlags(int privateFlags) {
15840        String output = "";
15841        int numFlags = 0;
15842
15843        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
15844            output += "WANTS_FOCUS";
15845            numFlags++;
15846        }
15847
15848        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
15849            if (numFlags > 0) {
15850                output += " ";
15851            }
15852            output += "FOCUSED";
15853            numFlags++;
15854        }
15855
15856        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
15857            if (numFlags > 0) {
15858                output += " ";
15859            }
15860            output += "SELECTED";
15861            numFlags++;
15862        }
15863
15864        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
15865            if (numFlags > 0) {
15866                output += " ";
15867            }
15868            output += "IS_ROOT_NAMESPACE";
15869            numFlags++;
15870        }
15871
15872        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
15873            if (numFlags > 0) {
15874                output += " ";
15875            }
15876            output += "HAS_BOUNDS";
15877            numFlags++;
15878        }
15879
15880        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
15881            if (numFlags > 0) {
15882                output += " ";
15883            }
15884            output += "DRAWN";
15885            // USELESS HERE numFlags++;
15886        }
15887        return output;
15888    }
15889
15890    /**
15891     * <p>Indicates whether or not this view's layout will be requested during
15892     * the next hierarchy layout pass.</p>
15893     *
15894     * @return true if the layout will be forced during next layout pass
15895     */
15896    public boolean isLayoutRequested() {
15897        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
15898    }
15899
15900    /**
15901     * Return true if o is a ViewGroup that is laying out using optical bounds.
15902     * @hide
15903     */
15904    public static boolean isLayoutModeOptical(Object o) {
15905        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
15906    }
15907
15908    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
15909        Insets parentInsets = mParent instanceof View ?
15910                ((View) mParent).getOpticalInsets() : Insets.NONE;
15911        Insets childInsets = getOpticalInsets();
15912        return setFrame(
15913                left   + parentInsets.left - childInsets.left,
15914                top    + parentInsets.top  - childInsets.top,
15915                right  + parentInsets.left + childInsets.right,
15916                bottom + parentInsets.top  + childInsets.bottom);
15917    }
15918
15919    /**
15920     * Assign a size and position to a view and all of its
15921     * descendants
15922     *
15923     * <p>This is the second phase of the layout mechanism.
15924     * (The first is measuring). In this phase, each parent calls
15925     * layout on all of its children to position them.
15926     * This is typically done using the child measurements
15927     * that were stored in the measure pass().</p>
15928     *
15929     * <p>Derived classes should not override this method.
15930     * Derived classes with children should override
15931     * onLayout. In that method, they should
15932     * call layout on each of their children.</p>
15933     *
15934     * @param l Left position, relative to parent
15935     * @param t Top position, relative to parent
15936     * @param r Right position, relative to parent
15937     * @param b Bottom position, relative to parent
15938     */
15939    @SuppressWarnings({"unchecked"})
15940    public void layout(int l, int t, int r, int b) {
15941        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
15942            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
15943            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
15944        }
15945
15946        int oldL = mLeft;
15947        int oldT = mTop;
15948        int oldB = mBottom;
15949        int oldR = mRight;
15950
15951        boolean changed = isLayoutModeOptical(mParent) ?
15952                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
15953
15954        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
15955            onLayout(changed, l, t, r, b);
15956            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
15957
15958            ListenerInfo li = mListenerInfo;
15959            if (li != null && li.mOnLayoutChangeListeners != null) {
15960                ArrayList<OnLayoutChangeListener> listenersCopy =
15961                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
15962                int numListeners = listenersCopy.size();
15963                for (int i = 0; i < numListeners; ++i) {
15964                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
15965                }
15966            }
15967        }
15968
15969        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
15970        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
15971    }
15972
15973    /**
15974     * Called from layout when this view should
15975     * assign a size and position to each of its children.
15976     *
15977     * Derived classes with children should override
15978     * this method and call layout on each of
15979     * their children.
15980     * @param changed This is a new size or position for this view
15981     * @param left Left position, relative to parent
15982     * @param top Top position, relative to parent
15983     * @param right Right position, relative to parent
15984     * @param bottom Bottom position, relative to parent
15985     */
15986    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
15987    }
15988
15989    /**
15990     * Assign a size and position to this view.
15991     *
15992     * This is called from layout.
15993     *
15994     * @param left Left position, relative to parent
15995     * @param top Top position, relative to parent
15996     * @param right Right position, relative to parent
15997     * @param bottom Bottom position, relative to parent
15998     * @return true if the new size and position are different than the
15999     *         previous ones
16000     * {@hide}
16001     */
16002    protected boolean setFrame(int left, int top, int right, int bottom) {
16003        boolean changed = false;
16004
16005        if (DBG) {
16006            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16007                    + right + "," + bottom + ")");
16008        }
16009
16010        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16011            changed = true;
16012
16013            // Remember our drawn bit
16014            int drawn = mPrivateFlags & PFLAG_DRAWN;
16015
16016            int oldWidth = mRight - mLeft;
16017            int oldHeight = mBottom - mTop;
16018            int newWidth = right - left;
16019            int newHeight = bottom - top;
16020            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16021
16022            // Invalidate our old position
16023            invalidate(sizeChanged);
16024
16025            mLeft = left;
16026            mTop = top;
16027            mRight = right;
16028            mBottom = bottom;
16029            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16030
16031            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16032
16033
16034            if (sizeChanged) {
16035                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16036            }
16037
16038            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16039                // If we are visible, force the DRAWN bit to on so that
16040                // this invalidate will go through (at least to our parent).
16041                // This is because someone may have invalidated this view
16042                // before this call to setFrame came in, thereby clearing
16043                // the DRAWN bit.
16044                mPrivateFlags |= PFLAG_DRAWN;
16045                invalidate(sizeChanged);
16046                // parent display list may need to be recreated based on a change in the bounds
16047                // of any child
16048                invalidateParentCaches();
16049            }
16050
16051            // Reset drawn bit to original value (invalidate turns it off)
16052            mPrivateFlags |= drawn;
16053
16054            mBackgroundSizeChanged = true;
16055            if (mForegroundInfo != null) {
16056                mForegroundInfo.mBoundsChanged = true;
16057            }
16058
16059            notifySubtreeAccessibilityStateChangedIfNeeded();
16060        }
16061        return changed;
16062    }
16063
16064    /**
16065     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16066     * @hide
16067     */
16068    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16069        setFrame(left, top, right, bottom);
16070    }
16071
16072    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16073        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16074        if (mOverlay != null) {
16075            mOverlay.getOverlayView().setRight(newWidth);
16076            mOverlay.getOverlayView().setBottom(newHeight);
16077        }
16078        rebuildOutline();
16079    }
16080
16081    /**
16082     * Finalize inflating a view from XML.  This is called as the last phase
16083     * of inflation, after all child views have been added.
16084     *
16085     * <p>Even if the subclass overrides onFinishInflate, they should always be
16086     * sure to call the super method, so that we get called.
16087     */
16088    @CallSuper
16089    protected void onFinishInflate() {
16090    }
16091
16092    /**
16093     * Returns the resources associated with this view.
16094     *
16095     * @return Resources object.
16096     */
16097    public Resources getResources() {
16098        return mResources;
16099    }
16100
16101    /**
16102     * Invalidates the specified Drawable.
16103     *
16104     * @param drawable the drawable to invalidate
16105     */
16106    @Override
16107    public void invalidateDrawable(@NonNull Drawable drawable) {
16108        if (verifyDrawable(drawable)) {
16109            final Rect dirty = drawable.getDirtyBounds();
16110            final int scrollX = mScrollX;
16111            final int scrollY = mScrollY;
16112
16113            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16114                    dirty.right + scrollX, dirty.bottom + scrollY);
16115            rebuildOutline();
16116        }
16117    }
16118
16119    /**
16120     * Schedules an action on a drawable to occur at a specified time.
16121     *
16122     * @param who the recipient of the action
16123     * @param what the action to run on the drawable
16124     * @param when the time at which the action must occur. Uses the
16125     *        {@link SystemClock#uptimeMillis} timebase.
16126     */
16127    @Override
16128    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16129        if (verifyDrawable(who) && what != null) {
16130            final long delay = when - SystemClock.uptimeMillis();
16131            if (mAttachInfo != null) {
16132                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16133                        Choreographer.CALLBACK_ANIMATION, what, who,
16134                        Choreographer.subtractFrameDelay(delay));
16135            } else {
16136                ViewRootImpl.getRunQueue().postDelayed(what, delay);
16137            }
16138        }
16139    }
16140
16141    /**
16142     * Cancels a scheduled action on a drawable.
16143     *
16144     * @param who the recipient of the action
16145     * @param what the action to cancel
16146     */
16147    @Override
16148    public void unscheduleDrawable(Drawable who, Runnable what) {
16149        if (verifyDrawable(who) && what != null) {
16150            if (mAttachInfo != null) {
16151                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16152                        Choreographer.CALLBACK_ANIMATION, what, who);
16153            }
16154            ViewRootImpl.getRunQueue().removeCallbacks(what);
16155        }
16156    }
16157
16158    /**
16159     * Unschedule any events associated with the given Drawable.  This can be
16160     * used when selecting a new Drawable into a view, so that the previous
16161     * one is completely unscheduled.
16162     *
16163     * @param who The Drawable to unschedule.
16164     *
16165     * @see #drawableStateChanged
16166     */
16167    public void unscheduleDrawable(Drawable who) {
16168        if (mAttachInfo != null && who != null) {
16169            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16170                    Choreographer.CALLBACK_ANIMATION, null, who);
16171        }
16172    }
16173
16174    /**
16175     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16176     * that the View directionality can and will be resolved before its Drawables.
16177     *
16178     * Will call {@link View#onResolveDrawables} when resolution is done.
16179     *
16180     * @hide
16181     */
16182    protected void resolveDrawables() {
16183        // Drawables resolution may need to happen before resolving the layout direction (which is
16184        // done only during the measure() call).
16185        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16186        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16187        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16188        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16189        // direction to be resolved as its resolved value will be the same as its raw value.
16190        if (!isLayoutDirectionResolved() &&
16191                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16192            return;
16193        }
16194
16195        final int layoutDirection = isLayoutDirectionResolved() ?
16196                getLayoutDirection() : getRawLayoutDirection();
16197
16198        if (mBackground != null) {
16199            mBackground.setLayoutDirection(layoutDirection);
16200        }
16201        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16202            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16203        }
16204        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16205        onResolveDrawables(layoutDirection);
16206    }
16207
16208    boolean areDrawablesResolved() {
16209        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16210    }
16211
16212    /**
16213     * Called when layout direction has been resolved.
16214     *
16215     * The default implementation does nothing.
16216     *
16217     * @param layoutDirection The resolved layout direction.
16218     *
16219     * @see #LAYOUT_DIRECTION_LTR
16220     * @see #LAYOUT_DIRECTION_RTL
16221     *
16222     * @hide
16223     */
16224    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16225    }
16226
16227    /**
16228     * @hide
16229     */
16230    protected void resetResolvedDrawables() {
16231        resetResolvedDrawablesInternal();
16232    }
16233
16234    void resetResolvedDrawablesInternal() {
16235        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16236    }
16237
16238    /**
16239     * If your view subclass is displaying its own Drawable objects, it should
16240     * override this function and return true for any Drawable it is
16241     * displaying.  This allows animations for those drawables to be
16242     * scheduled.
16243     *
16244     * <p>Be sure to call through to the super class when overriding this
16245     * function.
16246     *
16247     * @param who The Drawable to verify.  Return true if it is one you are
16248     *            displaying, else return the result of calling through to the
16249     *            super class.
16250     *
16251     * @return boolean If true than the Drawable is being displayed in the
16252     *         view; else false and it is not allowed to animate.
16253     *
16254     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16255     * @see #drawableStateChanged()
16256     */
16257    @CallSuper
16258    protected boolean verifyDrawable(Drawable who) {
16259        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16260                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16261    }
16262
16263    /**
16264     * This function is called whenever the state of the view changes in such
16265     * a way that it impacts the state of drawables being shown.
16266     * <p>
16267     * If the View has a StateListAnimator, it will also be called to run necessary state
16268     * change animations.
16269     * <p>
16270     * Be sure to call through to the superclass when overriding this function.
16271     *
16272     * @see Drawable#setState(int[])
16273     */
16274    @CallSuper
16275    protected void drawableStateChanged() {
16276        final int[] state = getDrawableState();
16277
16278        final Drawable bg = mBackground;
16279        if (bg != null && bg.isStateful()) {
16280            bg.setState(state);
16281        }
16282
16283        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16284        if (fg != null && fg.isStateful()) {
16285            fg.setState(state);
16286        }
16287
16288        if (mScrollCache != null) {
16289            final Drawable scrollBar = mScrollCache.scrollBar;
16290            if (scrollBar != null && scrollBar.isStateful()) {
16291                scrollBar.setState(state);
16292            }
16293        }
16294
16295        if (mStateListAnimator != null) {
16296            mStateListAnimator.setState(state);
16297        }
16298    }
16299
16300    /**
16301     * This function is called whenever the view hotspot changes and needs to
16302     * be propagated to drawables or child views managed by the view.
16303     * <p>
16304     * Dispatching to child views is handled by
16305     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16306     * <p>
16307     * Be sure to call through to the superclass when overriding this function.
16308     *
16309     * @param x hotspot x coordinate
16310     * @param y hotspot y coordinate
16311     */
16312    @CallSuper
16313    public void drawableHotspotChanged(float x, float y) {
16314        if (mBackground != null) {
16315            mBackground.setHotspot(x, y);
16316        }
16317        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16318            mForegroundInfo.mDrawable.setHotspot(x, y);
16319        }
16320
16321        dispatchDrawableHotspotChanged(x, y);
16322    }
16323
16324    /**
16325     * Dispatches drawableHotspotChanged to all of this View's children.
16326     *
16327     * @param x hotspot x coordinate
16328     * @param y hotspot y coordinate
16329     * @see #drawableHotspotChanged(float, float)
16330     */
16331    public void dispatchDrawableHotspotChanged(float x, float y) {
16332    }
16333
16334    /**
16335     * Call this to force a view to update its drawable state. This will cause
16336     * drawableStateChanged to be called on this view. Views that are interested
16337     * in the new state should call getDrawableState.
16338     *
16339     * @see #drawableStateChanged
16340     * @see #getDrawableState
16341     */
16342    public void refreshDrawableState() {
16343        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
16344        drawableStateChanged();
16345
16346        ViewParent parent = mParent;
16347        if (parent != null) {
16348            parent.childDrawableStateChanged(this);
16349        }
16350    }
16351
16352    /**
16353     * Return an array of resource IDs of the drawable states representing the
16354     * current state of the view.
16355     *
16356     * @return The current drawable state
16357     *
16358     * @see Drawable#setState(int[])
16359     * @see #drawableStateChanged()
16360     * @see #onCreateDrawableState(int)
16361     */
16362    public final int[] getDrawableState() {
16363        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
16364            return mDrawableState;
16365        } else {
16366            mDrawableState = onCreateDrawableState(0);
16367            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
16368            return mDrawableState;
16369        }
16370    }
16371
16372    /**
16373     * Generate the new {@link android.graphics.drawable.Drawable} state for
16374     * this view. This is called by the view
16375     * system when the cached Drawable state is determined to be invalid.  To
16376     * retrieve the current state, you should use {@link #getDrawableState}.
16377     *
16378     * @param extraSpace if non-zero, this is the number of extra entries you
16379     * would like in the returned array in which you can place your own
16380     * states.
16381     *
16382     * @return Returns an array holding the current {@link Drawable} state of
16383     * the view.
16384     *
16385     * @see #mergeDrawableStates(int[], int[])
16386     */
16387    protected int[] onCreateDrawableState(int extraSpace) {
16388        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
16389                mParent instanceof View) {
16390            return ((View) mParent).onCreateDrawableState(extraSpace);
16391        }
16392
16393        int[] drawableState;
16394
16395        int privateFlags = mPrivateFlags;
16396
16397        int viewStateIndex = 0;
16398        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
16399        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
16400        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
16401        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
16402        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
16403        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
16404        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
16405                HardwareRenderer.isAvailable()) {
16406            // This is set if HW acceleration is requested, even if the current
16407            // process doesn't allow it.  This is just to allow app preview
16408            // windows to better match their app.
16409            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
16410        }
16411        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
16412
16413        final int privateFlags2 = mPrivateFlags2;
16414        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
16415            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
16416        }
16417        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
16418            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
16419        }
16420
16421        drawableState = StateSet.get(viewStateIndex);
16422
16423        //noinspection ConstantIfStatement
16424        if (false) {
16425            Log.i("View", "drawableStateIndex=" + viewStateIndex);
16426            Log.i("View", toString()
16427                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
16428                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
16429                    + " fo=" + hasFocus()
16430                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
16431                    + " wf=" + hasWindowFocus()
16432                    + ": " + Arrays.toString(drawableState));
16433        }
16434
16435        if (extraSpace == 0) {
16436            return drawableState;
16437        }
16438
16439        final int[] fullState;
16440        if (drawableState != null) {
16441            fullState = new int[drawableState.length + extraSpace];
16442            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
16443        } else {
16444            fullState = new int[extraSpace];
16445        }
16446
16447        return fullState;
16448    }
16449
16450    /**
16451     * Merge your own state values in <var>additionalState</var> into the base
16452     * state values <var>baseState</var> that were returned by
16453     * {@link #onCreateDrawableState(int)}.
16454     *
16455     * @param baseState The base state values returned by
16456     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
16457     * own additional state values.
16458     *
16459     * @param additionalState The additional state values you would like
16460     * added to <var>baseState</var>; this array is not modified.
16461     *
16462     * @return As a convenience, the <var>baseState</var> array you originally
16463     * passed into the function is returned.
16464     *
16465     * @see #onCreateDrawableState(int)
16466     */
16467    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
16468        final int N = baseState.length;
16469        int i = N - 1;
16470        while (i >= 0 && baseState[i] == 0) {
16471            i--;
16472        }
16473        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
16474        return baseState;
16475    }
16476
16477    /**
16478     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
16479     * on all Drawable objects associated with this view.
16480     * <p>
16481     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
16482     * attached to this view.
16483     */
16484    public void jumpDrawablesToCurrentState() {
16485        if (mBackground != null) {
16486            mBackground.jumpToCurrentState();
16487        }
16488        if (mStateListAnimator != null) {
16489            mStateListAnimator.jumpToCurrentState();
16490        }
16491        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16492            mForegroundInfo.mDrawable.jumpToCurrentState();
16493        }
16494    }
16495
16496    /**
16497     * Sets the background color for this view.
16498     * @param color the color of the background
16499     */
16500    @RemotableViewMethod
16501    public void setBackgroundColor(@ColorInt int color) {
16502        if (mBackground instanceof ColorDrawable) {
16503            ((ColorDrawable) mBackground.mutate()).setColor(color);
16504            computeOpaqueFlags();
16505            mBackgroundResource = 0;
16506        } else {
16507            setBackground(new ColorDrawable(color));
16508        }
16509    }
16510
16511    /**
16512     * If the view has a ColorDrawable background, returns the color of that
16513     * drawable.
16514     *
16515     * @return The color of the ColorDrawable background, if set, otherwise 0.
16516     */
16517    @ColorInt
16518    public int getBackgroundColor() {
16519        if (mBackground instanceof ColorDrawable) {
16520            return ((ColorDrawable) mBackground).getColor();
16521        }
16522        return 0;
16523    }
16524
16525    /**
16526     * Set the background to a given resource. The resource should refer to
16527     * a Drawable object or 0 to remove the background.
16528     * @param resid The identifier of the resource.
16529     *
16530     * @attr ref android.R.styleable#View_background
16531     */
16532    @RemotableViewMethod
16533    public void setBackgroundResource(@DrawableRes int resid) {
16534        if (resid != 0 && resid == mBackgroundResource) {
16535            return;
16536        }
16537
16538        Drawable d = null;
16539        if (resid != 0) {
16540            d = mContext.getDrawable(resid);
16541        }
16542        setBackground(d);
16543
16544        mBackgroundResource = resid;
16545    }
16546
16547    /**
16548     * Set the background to a given Drawable, or remove the background. If the
16549     * background has padding, this View's padding is set to the background's
16550     * padding. However, when a background is removed, this View's padding isn't
16551     * touched. If setting the padding is desired, please use
16552     * {@link #setPadding(int, int, int, int)}.
16553     *
16554     * @param background The Drawable to use as the background, or null to remove the
16555     *        background
16556     */
16557    public void setBackground(Drawable background) {
16558        //noinspection deprecation
16559        setBackgroundDrawable(background);
16560    }
16561
16562    /**
16563     * @deprecated use {@link #setBackground(Drawable)} instead
16564     */
16565    @Deprecated
16566    public void setBackgroundDrawable(Drawable background) {
16567        computeOpaqueFlags();
16568
16569        if (background == mBackground) {
16570            return;
16571        }
16572
16573        boolean requestLayout = false;
16574
16575        mBackgroundResource = 0;
16576
16577        /*
16578         * Regardless of whether we're setting a new background or not, we want
16579         * to clear the previous drawable.
16580         */
16581        if (mBackground != null) {
16582            mBackground.setCallback(null);
16583            unscheduleDrawable(mBackground);
16584        }
16585
16586        if (background != null) {
16587            Rect padding = sThreadLocal.get();
16588            if (padding == null) {
16589                padding = new Rect();
16590                sThreadLocal.set(padding);
16591            }
16592            resetResolvedDrawablesInternal();
16593            background.setLayoutDirection(getLayoutDirection());
16594            if (background.getPadding(padding)) {
16595                resetResolvedPaddingInternal();
16596                switch (background.getLayoutDirection()) {
16597                    case LAYOUT_DIRECTION_RTL:
16598                        mUserPaddingLeftInitial = padding.right;
16599                        mUserPaddingRightInitial = padding.left;
16600                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
16601                        break;
16602                    case LAYOUT_DIRECTION_LTR:
16603                    default:
16604                        mUserPaddingLeftInitial = padding.left;
16605                        mUserPaddingRightInitial = padding.right;
16606                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
16607                }
16608                mLeftPaddingDefined = false;
16609                mRightPaddingDefined = false;
16610            }
16611
16612            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
16613            // if it has a different minimum size, we should layout again
16614            if (mBackground == null
16615                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
16616                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
16617                requestLayout = true;
16618            }
16619
16620            background.setCallback(this);
16621            if (background.isStateful()) {
16622                background.setState(getDrawableState());
16623            }
16624            background.setVisible(getVisibility() == VISIBLE, false);
16625            mBackground = background;
16626
16627            applyBackgroundTint();
16628
16629            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
16630                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
16631                mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
16632                requestLayout = true;
16633            }
16634        } else {
16635            /* Remove the background */
16636            mBackground = null;
16637
16638            if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
16639                /*
16640                 * This view ONLY drew the background before and we're removing
16641                 * the background, so now it won't draw anything
16642                 * (hence we SKIP_DRAW)
16643                 */
16644                mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
16645                mPrivateFlags |= PFLAG_SKIP_DRAW;
16646            }
16647
16648            /*
16649             * When the background is set, we try to apply its padding to this
16650             * View. When the background is removed, we don't touch this View's
16651             * padding. This is noted in the Javadocs. Hence, we don't need to
16652             * requestLayout(), the invalidate() below is sufficient.
16653             */
16654
16655            // The old background's minimum size could have affected this
16656            // View's layout, so let's requestLayout
16657            requestLayout = true;
16658        }
16659
16660        computeOpaqueFlags();
16661
16662        if (requestLayout) {
16663            requestLayout();
16664        }
16665
16666        mBackgroundSizeChanged = true;
16667        invalidate(true);
16668    }
16669
16670    /**
16671     * Gets the background drawable
16672     *
16673     * @return The drawable used as the background for this view, if any.
16674     *
16675     * @see #setBackground(Drawable)
16676     *
16677     * @attr ref android.R.styleable#View_background
16678     */
16679    public Drawable getBackground() {
16680        return mBackground;
16681    }
16682
16683    /**
16684     * Applies a tint to the background drawable. Does not modify the current tint
16685     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16686     * <p>
16687     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
16688     * mutate the drawable and apply the specified tint and tint mode using
16689     * {@link Drawable#setTintList(ColorStateList)}.
16690     *
16691     * @param tint the tint to apply, may be {@code null} to clear tint
16692     *
16693     * @attr ref android.R.styleable#View_backgroundTint
16694     * @see #getBackgroundTintList()
16695     * @see Drawable#setTintList(ColorStateList)
16696     */
16697    public void setBackgroundTintList(@Nullable ColorStateList tint) {
16698        if (mBackgroundTint == null) {
16699            mBackgroundTint = new TintInfo();
16700        }
16701        mBackgroundTint.mTintList = tint;
16702        mBackgroundTint.mHasTintList = true;
16703
16704        applyBackgroundTint();
16705    }
16706
16707    /**
16708     * Return the tint applied to the background drawable, if specified.
16709     *
16710     * @return the tint applied to the background drawable
16711     * @attr ref android.R.styleable#View_backgroundTint
16712     * @see #setBackgroundTintList(ColorStateList)
16713     */
16714    @Nullable
16715    public ColorStateList getBackgroundTintList() {
16716        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
16717    }
16718
16719    /**
16720     * Specifies the blending mode used to apply the tint specified by
16721     * {@link #setBackgroundTintList(ColorStateList)}} to the background
16722     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16723     *
16724     * @param tintMode the blending mode used to apply the tint, may be
16725     *                 {@code null} to clear tint
16726     * @attr ref android.R.styleable#View_backgroundTintMode
16727     * @see #getBackgroundTintMode()
16728     * @see Drawable#setTintMode(PorterDuff.Mode)
16729     */
16730    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16731        if (mBackgroundTint == null) {
16732            mBackgroundTint = new TintInfo();
16733        }
16734        mBackgroundTint.mTintMode = tintMode;
16735        mBackgroundTint.mHasTintMode = true;
16736
16737        applyBackgroundTint();
16738    }
16739
16740    /**
16741     * Return the blending mode used to apply the tint to the background
16742     * drawable, if specified.
16743     *
16744     * @return the blending mode used to apply the tint to the background
16745     *         drawable
16746     * @attr ref android.R.styleable#View_backgroundTintMode
16747     * @see #setBackgroundTintMode(PorterDuff.Mode)
16748     */
16749    @Nullable
16750    public PorterDuff.Mode getBackgroundTintMode() {
16751        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
16752    }
16753
16754    private void applyBackgroundTint() {
16755        if (mBackground != null && mBackgroundTint != null) {
16756            final TintInfo tintInfo = mBackgroundTint;
16757            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16758                mBackground = mBackground.mutate();
16759
16760                if (tintInfo.mHasTintList) {
16761                    mBackground.setTintList(tintInfo.mTintList);
16762                }
16763
16764                if (tintInfo.mHasTintMode) {
16765                    mBackground.setTintMode(tintInfo.mTintMode);
16766                }
16767
16768                // The drawable (or one of its children) may not have been
16769                // stateful before applying the tint, so let's try again.
16770                if (mBackground.isStateful()) {
16771                    mBackground.setState(getDrawableState());
16772                }
16773            }
16774        }
16775    }
16776
16777    /**
16778     * Returns the drawable used as the foreground of this View. The
16779     * foreground drawable, if non-null, is always drawn on top of the view's content.
16780     *
16781     * @return a Drawable or null if no foreground was set
16782     *
16783     * @see #onDrawForeground(Canvas)
16784     */
16785    public Drawable getForeground() {
16786        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16787    }
16788
16789    /**
16790     * Supply a Drawable that is to be rendered on top of all of the content in the view.
16791     *
16792     * @param foreground the Drawable to be drawn on top of the children
16793     *
16794     * @attr ref android.R.styleable#View_foreground
16795     */
16796    public void setForeground(Drawable foreground) {
16797        if (mForegroundInfo == null) {
16798            if (foreground == null) {
16799                // Nothing to do.
16800                return;
16801            }
16802            mForegroundInfo = new ForegroundInfo();
16803        }
16804
16805        if (foreground == mForegroundInfo.mDrawable) {
16806            // Nothing to do
16807            return;
16808        }
16809
16810        if (mForegroundInfo.mDrawable != null) {
16811            mForegroundInfo.mDrawable.setCallback(null);
16812            unscheduleDrawable(mForegroundInfo.mDrawable);
16813        }
16814
16815        mForegroundInfo.mDrawable = foreground;
16816        mForegroundInfo.mBoundsChanged = true;
16817        if (foreground != null) {
16818            setWillNotDraw(false);
16819            foreground.setCallback(this);
16820            foreground.setLayoutDirection(getLayoutDirection());
16821            if (foreground.isStateful()) {
16822                foreground.setState(getDrawableState());
16823            }
16824            applyForegroundTint();
16825        }
16826        requestLayout();
16827        invalidate();
16828    }
16829
16830    /**
16831     * Magic bit used to support features of framework-internal window decor implementation details.
16832     * This used to live exclusively in FrameLayout.
16833     *
16834     * @return true if the foreground should draw inside the padding region or false
16835     *         if it should draw inset by the view's padding
16836     * @hide internal use only; only used by FrameLayout and internal screen layouts.
16837     */
16838    public boolean isForegroundInsidePadding() {
16839        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
16840    }
16841
16842    /**
16843     * Describes how the foreground is positioned.
16844     *
16845     * @return foreground gravity.
16846     *
16847     * @see #setForegroundGravity(int)
16848     *
16849     * @attr ref android.R.styleable#View_foregroundGravity
16850     */
16851    public int getForegroundGravity() {
16852        return mForegroundInfo != null ? mForegroundInfo.mGravity
16853                : Gravity.START | Gravity.TOP;
16854    }
16855
16856    /**
16857     * Describes how the foreground is positioned. Defaults to START and TOP.
16858     *
16859     * @param gravity see {@link android.view.Gravity}
16860     *
16861     * @see #getForegroundGravity()
16862     *
16863     * @attr ref android.R.styleable#View_foregroundGravity
16864     */
16865    public void setForegroundGravity(int gravity) {
16866        if (mForegroundInfo == null) {
16867            mForegroundInfo = new ForegroundInfo();
16868        }
16869
16870        if (mForegroundInfo.mGravity != gravity) {
16871            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
16872                gravity |= Gravity.START;
16873            }
16874
16875            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
16876                gravity |= Gravity.TOP;
16877            }
16878
16879            mForegroundInfo.mGravity = gravity;
16880            requestLayout();
16881        }
16882    }
16883
16884    /**
16885     * Applies a tint to the foreground drawable. Does not modify the current tint
16886     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
16887     * <p>
16888     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
16889     * mutate the drawable and apply the specified tint and tint mode using
16890     * {@link Drawable#setTintList(ColorStateList)}.
16891     *
16892     * @param tint the tint to apply, may be {@code null} to clear tint
16893     *
16894     * @attr ref android.R.styleable#View_foregroundTint
16895     * @see #getForegroundTintList()
16896     * @see Drawable#setTintList(ColorStateList)
16897     */
16898    public void setForegroundTintList(@Nullable ColorStateList tint) {
16899        if (mForegroundInfo == null) {
16900            mForegroundInfo = new ForegroundInfo();
16901        }
16902        if (mForegroundInfo.mTintInfo == null) {
16903            mForegroundInfo.mTintInfo = new TintInfo();
16904        }
16905        mForegroundInfo.mTintInfo.mTintList = tint;
16906        mForegroundInfo.mTintInfo.mHasTintList = true;
16907
16908        applyForegroundTint();
16909    }
16910
16911    /**
16912     * Return the tint applied to the foreground drawable, if specified.
16913     *
16914     * @return the tint applied to the foreground drawable
16915     * @attr ref android.R.styleable#View_foregroundTint
16916     * @see #setForegroundTintList(ColorStateList)
16917     */
16918    @Nullable
16919    public ColorStateList getForegroundTintList() {
16920        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
16921                ? mForegroundInfo.mTintInfo.mTintList : null;
16922    }
16923
16924    /**
16925     * Specifies the blending mode used to apply the tint specified by
16926     * {@link #setForegroundTintList(ColorStateList)}} to the background
16927     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
16928     *
16929     * @param tintMode the blending mode used to apply the tint, may be
16930     *                 {@code null} to clear tint
16931     * @attr ref android.R.styleable#View_foregroundTintMode
16932     * @see #getForegroundTintMode()
16933     * @see Drawable#setTintMode(PorterDuff.Mode)
16934     */
16935    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
16936        if (mBackgroundTint == null) {
16937            mBackgroundTint = new TintInfo();
16938        }
16939        mBackgroundTint.mTintMode = tintMode;
16940        mBackgroundTint.mHasTintMode = true;
16941
16942        applyBackgroundTint();
16943    }
16944
16945    /**
16946     * Return the blending mode used to apply the tint to the foreground
16947     * drawable, if specified.
16948     *
16949     * @return the blending mode used to apply the tint to the foreground
16950     *         drawable
16951     * @attr ref android.R.styleable#View_foregroundTintMode
16952     * @see #setBackgroundTintMode(PorterDuff.Mode)
16953     */
16954    @Nullable
16955    public PorterDuff.Mode getForegroundTintMode() {
16956        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
16957                ? mForegroundInfo.mTintInfo.mTintMode : null;
16958    }
16959
16960    private void applyForegroundTint() {
16961        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
16962                && mForegroundInfo.mTintInfo != null) {
16963            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
16964            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
16965                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
16966
16967                if (tintInfo.mHasTintList) {
16968                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
16969                }
16970
16971                if (tintInfo.mHasTintMode) {
16972                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
16973                }
16974
16975                // The drawable (or one of its children) may not have been
16976                // stateful before applying the tint, so let's try again.
16977                if (mForegroundInfo.mDrawable.isStateful()) {
16978                    mForegroundInfo.mDrawable.setState(getDrawableState());
16979                }
16980            }
16981        }
16982    }
16983
16984    /**
16985     * Draw any foreground content for this view.
16986     *
16987     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
16988     * drawable or other view-specific decorations. The foreground is drawn on top of the
16989     * primary view content.</p>
16990     *
16991     * @param canvas canvas to draw into
16992     */
16993    public void onDrawForeground(Canvas canvas) {
16994        onDrawScrollBars(canvas);
16995
16996        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16997        if (foreground != null) {
16998            if (mForegroundInfo.mBoundsChanged) {
16999                mForegroundInfo.mBoundsChanged = false;
17000                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17001                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17002
17003                if (mForegroundInfo.mInsidePadding) {
17004                    selfBounds.set(0, 0, getWidth(), getHeight());
17005                } else {
17006                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17007                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17008                }
17009
17010                final int ld = getLayoutDirection();
17011                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17012                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17013                foreground.setBounds(overlayBounds);
17014            }
17015
17016            foreground.draw(canvas);
17017        }
17018    }
17019
17020    /**
17021     * Sets the padding. The view may add on the space required to display
17022     * the scrollbars, depending on the style and visibility of the scrollbars.
17023     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17024     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17025     * from the values set in this call.
17026     *
17027     * @attr ref android.R.styleable#View_padding
17028     * @attr ref android.R.styleable#View_paddingBottom
17029     * @attr ref android.R.styleable#View_paddingLeft
17030     * @attr ref android.R.styleable#View_paddingRight
17031     * @attr ref android.R.styleable#View_paddingTop
17032     * @param left the left padding in pixels
17033     * @param top the top padding in pixels
17034     * @param right the right padding in pixels
17035     * @param bottom the bottom padding in pixels
17036     */
17037    public void setPadding(int left, int top, int right, int bottom) {
17038        resetResolvedPaddingInternal();
17039
17040        mUserPaddingStart = UNDEFINED_PADDING;
17041        mUserPaddingEnd = UNDEFINED_PADDING;
17042
17043        mUserPaddingLeftInitial = left;
17044        mUserPaddingRightInitial = right;
17045
17046        mLeftPaddingDefined = true;
17047        mRightPaddingDefined = true;
17048
17049        internalSetPadding(left, top, right, bottom);
17050    }
17051
17052    /**
17053     * @hide
17054     */
17055    protected void internalSetPadding(int left, int top, int right, int bottom) {
17056        mUserPaddingLeft = left;
17057        mUserPaddingRight = right;
17058        mUserPaddingBottom = bottom;
17059
17060        final int viewFlags = mViewFlags;
17061        boolean changed = false;
17062
17063        // Common case is there are no scroll bars.
17064        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17065            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17066                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17067                        ? 0 : getVerticalScrollbarWidth();
17068                switch (mVerticalScrollbarPosition) {
17069                    case SCROLLBAR_POSITION_DEFAULT:
17070                        if (isLayoutRtl()) {
17071                            left += offset;
17072                        } else {
17073                            right += offset;
17074                        }
17075                        break;
17076                    case SCROLLBAR_POSITION_RIGHT:
17077                        right += offset;
17078                        break;
17079                    case SCROLLBAR_POSITION_LEFT:
17080                        left += offset;
17081                        break;
17082                }
17083            }
17084            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17085                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17086                        ? 0 : getHorizontalScrollbarHeight();
17087            }
17088        }
17089
17090        if (mPaddingLeft != left) {
17091            changed = true;
17092            mPaddingLeft = left;
17093        }
17094        if (mPaddingTop != top) {
17095            changed = true;
17096            mPaddingTop = top;
17097        }
17098        if (mPaddingRight != right) {
17099            changed = true;
17100            mPaddingRight = right;
17101        }
17102        if (mPaddingBottom != bottom) {
17103            changed = true;
17104            mPaddingBottom = bottom;
17105        }
17106
17107        if (changed) {
17108            requestLayout();
17109            invalidateOutline();
17110        }
17111    }
17112
17113    /**
17114     * Sets the relative padding. The view may add on the space required to display
17115     * the scrollbars, depending on the style and visibility of the scrollbars.
17116     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17117     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17118     * from the values set in this call.
17119     *
17120     * @attr ref android.R.styleable#View_padding
17121     * @attr ref android.R.styleable#View_paddingBottom
17122     * @attr ref android.R.styleable#View_paddingStart
17123     * @attr ref android.R.styleable#View_paddingEnd
17124     * @attr ref android.R.styleable#View_paddingTop
17125     * @param start the start padding in pixels
17126     * @param top the top padding in pixels
17127     * @param end the end padding in pixels
17128     * @param bottom the bottom padding in pixels
17129     */
17130    public void setPaddingRelative(int start, int top, int end, int bottom) {
17131        resetResolvedPaddingInternal();
17132
17133        mUserPaddingStart = start;
17134        mUserPaddingEnd = end;
17135        mLeftPaddingDefined = true;
17136        mRightPaddingDefined = true;
17137
17138        switch(getLayoutDirection()) {
17139            case LAYOUT_DIRECTION_RTL:
17140                mUserPaddingLeftInitial = end;
17141                mUserPaddingRightInitial = start;
17142                internalSetPadding(end, top, start, bottom);
17143                break;
17144            case LAYOUT_DIRECTION_LTR:
17145            default:
17146                mUserPaddingLeftInitial = start;
17147                mUserPaddingRightInitial = end;
17148                internalSetPadding(start, top, end, bottom);
17149        }
17150    }
17151
17152    /**
17153     * Returns the top padding of this view.
17154     *
17155     * @return the top padding in pixels
17156     */
17157    public int getPaddingTop() {
17158        return mPaddingTop;
17159    }
17160
17161    /**
17162     * Returns the bottom padding of this view. If there are inset and enabled
17163     * scrollbars, this value may include the space required to display the
17164     * scrollbars as well.
17165     *
17166     * @return the bottom padding in pixels
17167     */
17168    public int getPaddingBottom() {
17169        return mPaddingBottom;
17170    }
17171
17172    /**
17173     * Returns the left padding of this view. If there are inset and enabled
17174     * scrollbars, this value may include the space required to display the
17175     * scrollbars as well.
17176     *
17177     * @return the left padding in pixels
17178     */
17179    public int getPaddingLeft() {
17180        if (!isPaddingResolved()) {
17181            resolvePadding();
17182        }
17183        return mPaddingLeft;
17184    }
17185
17186    /**
17187     * Returns the start padding of this view depending on its resolved layout direction.
17188     * If there are inset and enabled scrollbars, this value may include the space
17189     * required to display the scrollbars as well.
17190     *
17191     * @return the start padding in pixels
17192     */
17193    public int getPaddingStart() {
17194        if (!isPaddingResolved()) {
17195            resolvePadding();
17196        }
17197        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17198                mPaddingRight : mPaddingLeft;
17199    }
17200
17201    /**
17202     * Returns the right padding of this view. If there are inset and enabled
17203     * scrollbars, this value may include the space required to display the
17204     * scrollbars as well.
17205     *
17206     * @return the right padding in pixels
17207     */
17208    public int getPaddingRight() {
17209        if (!isPaddingResolved()) {
17210            resolvePadding();
17211        }
17212        return mPaddingRight;
17213    }
17214
17215    /**
17216     * Returns the end padding of this view depending on its resolved layout direction.
17217     * If there are inset and enabled scrollbars, this value may include the space
17218     * required to display the scrollbars as well.
17219     *
17220     * @return the end padding in pixels
17221     */
17222    public int getPaddingEnd() {
17223        if (!isPaddingResolved()) {
17224            resolvePadding();
17225        }
17226        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17227                mPaddingLeft : mPaddingRight;
17228    }
17229
17230    /**
17231     * Return if the padding has been set through relative values
17232     * {@link #setPaddingRelative(int, int, int, int)} or through
17233     * @attr ref android.R.styleable#View_paddingStart or
17234     * @attr ref android.R.styleable#View_paddingEnd
17235     *
17236     * @return true if the padding is relative or false if it is not.
17237     */
17238    public boolean isPaddingRelative() {
17239        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17240    }
17241
17242    Insets computeOpticalInsets() {
17243        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17244    }
17245
17246    /**
17247     * @hide
17248     */
17249    public void resetPaddingToInitialValues() {
17250        if (isRtlCompatibilityMode()) {
17251            mPaddingLeft = mUserPaddingLeftInitial;
17252            mPaddingRight = mUserPaddingRightInitial;
17253            return;
17254        }
17255        if (isLayoutRtl()) {
17256            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17257            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17258        } else {
17259            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17260            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17261        }
17262    }
17263
17264    /**
17265     * @hide
17266     */
17267    public Insets getOpticalInsets() {
17268        if (mLayoutInsets == null) {
17269            mLayoutInsets = computeOpticalInsets();
17270        }
17271        return mLayoutInsets;
17272    }
17273
17274    /**
17275     * Set this view's optical insets.
17276     *
17277     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17278     * property. Views that compute their own optical insets should call it as part of measurement.
17279     * This method does not request layout. If you are setting optical insets outside of
17280     * measure/layout itself you will want to call requestLayout() yourself.
17281     * </p>
17282     * @hide
17283     */
17284    public void setOpticalInsets(Insets insets) {
17285        mLayoutInsets = insets;
17286    }
17287
17288    /**
17289     * Changes the selection state of this view. A view can be selected or not.
17290     * Note that selection is not the same as focus. Views are typically
17291     * selected in the context of an AdapterView like ListView or GridView;
17292     * the selected view is the view that is highlighted.
17293     *
17294     * @param selected true if the view must be selected, false otherwise
17295     */
17296    public void setSelected(boolean selected) {
17297        //noinspection DoubleNegation
17298        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17299            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17300            if (!selected) resetPressedState();
17301            invalidate(true);
17302            refreshDrawableState();
17303            dispatchSetSelected(selected);
17304            if (selected) {
17305                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17306            } else {
17307                notifyViewAccessibilityStateChangedIfNeeded(
17308                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17309            }
17310        }
17311    }
17312
17313    /**
17314     * Dispatch setSelected to all of this View's children.
17315     *
17316     * @see #setSelected(boolean)
17317     *
17318     * @param selected The new selected state
17319     */
17320    protected void dispatchSetSelected(boolean selected) {
17321    }
17322
17323    /**
17324     * Indicates the selection state of this view.
17325     *
17326     * @return true if the view is selected, false otherwise
17327     */
17328    @ViewDebug.ExportedProperty
17329    public boolean isSelected() {
17330        return (mPrivateFlags & PFLAG_SELECTED) != 0;
17331    }
17332
17333    /**
17334     * Changes the activated state of this view. A view can be activated or not.
17335     * Note that activation is not the same as selection.  Selection is
17336     * a transient property, representing the view (hierarchy) the user is
17337     * currently interacting with.  Activation is a longer-term state that the
17338     * user can move views in and out of.  For example, in a list view with
17339     * single or multiple selection enabled, the views in the current selection
17340     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
17341     * here.)  The activated state is propagated down to children of the view it
17342     * is set on.
17343     *
17344     * @param activated true if the view must be activated, false otherwise
17345     */
17346    public void setActivated(boolean activated) {
17347        //noinspection DoubleNegation
17348        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
17349            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
17350            invalidate(true);
17351            refreshDrawableState();
17352            dispatchSetActivated(activated);
17353        }
17354    }
17355
17356    /**
17357     * Dispatch setActivated to all of this View's children.
17358     *
17359     * @see #setActivated(boolean)
17360     *
17361     * @param activated The new activated state
17362     */
17363    protected void dispatchSetActivated(boolean activated) {
17364    }
17365
17366    /**
17367     * Indicates the activation state of this view.
17368     *
17369     * @return true if the view is activated, false otherwise
17370     */
17371    @ViewDebug.ExportedProperty
17372    public boolean isActivated() {
17373        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
17374    }
17375
17376    /**
17377     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
17378     * observer can be used to get notifications when global events, like
17379     * layout, happen.
17380     *
17381     * The returned ViewTreeObserver observer is not guaranteed to remain
17382     * valid for the lifetime of this View. If the caller of this method keeps
17383     * a long-lived reference to ViewTreeObserver, it should always check for
17384     * the return value of {@link ViewTreeObserver#isAlive()}.
17385     *
17386     * @return The ViewTreeObserver for this view's hierarchy.
17387     */
17388    public ViewTreeObserver getViewTreeObserver() {
17389        if (mAttachInfo != null) {
17390            return mAttachInfo.mTreeObserver;
17391        }
17392        if (mFloatingTreeObserver == null) {
17393            mFloatingTreeObserver = new ViewTreeObserver();
17394        }
17395        return mFloatingTreeObserver;
17396    }
17397
17398    /**
17399     * <p>Finds the topmost view in the current view hierarchy.</p>
17400     *
17401     * @return the topmost view containing this view
17402     */
17403    public View getRootView() {
17404        if (mAttachInfo != null) {
17405            final View v = mAttachInfo.mRootView;
17406            if (v != null) {
17407                return v;
17408            }
17409        }
17410
17411        View parent = this;
17412
17413        while (parent.mParent != null && parent.mParent instanceof View) {
17414            parent = (View) parent.mParent;
17415        }
17416
17417        return parent;
17418    }
17419
17420    /**
17421     * Transforms a motion event from view-local coordinates to on-screen
17422     * coordinates.
17423     *
17424     * @param ev the view-local motion event
17425     * @return false if the transformation could not be applied
17426     * @hide
17427     */
17428    public boolean toGlobalMotionEvent(MotionEvent ev) {
17429        final AttachInfo info = mAttachInfo;
17430        if (info == null) {
17431            return false;
17432        }
17433
17434        final Matrix m = info.mTmpMatrix;
17435        m.set(Matrix.IDENTITY_MATRIX);
17436        transformMatrixToGlobal(m);
17437        ev.transform(m);
17438        return true;
17439    }
17440
17441    /**
17442     * Transforms a motion event from on-screen coordinates to view-local
17443     * coordinates.
17444     *
17445     * @param ev the on-screen motion event
17446     * @return false if the transformation could not be applied
17447     * @hide
17448     */
17449    public boolean toLocalMotionEvent(MotionEvent ev) {
17450        final AttachInfo info = mAttachInfo;
17451        if (info == null) {
17452            return false;
17453        }
17454
17455        final Matrix m = info.mTmpMatrix;
17456        m.set(Matrix.IDENTITY_MATRIX);
17457        transformMatrixToLocal(m);
17458        ev.transform(m);
17459        return true;
17460    }
17461
17462    /**
17463     * Modifies the input matrix such that it maps view-local coordinates to
17464     * on-screen coordinates.
17465     *
17466     * @param m input matrix to modify
17467     * @hide
17468     */
17469    public void transformMatrixToGlobal(Matrix m) {
17470        final ViewParent parent = mParent;
17471        if (parent instanceof View) {
17472            final View vp = (View) parent;
17473            vp.transformMatrixToGlobal(m);
17474            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
17475        } else if (parent instanceof ViewRootImpl) {
17476            final ViewRootImpl vr = (ViewRootImpl) parent;
17477            vr.transformMatrixToGlobal(m);
17478            m.preTranslate(0, -vr.mCurScrollY);
17479        }
17480
17481        m.preTranslate(mLeft, mTop);
17482
17483        if (!hasIdentityMatrix()) {
17484            m.preConcat(getMatrix());
17485        }
17486    }
17487
17488    /**
17489     * Modifies the input matrix such that it maps on-screen coordinates to
17490     * view-local coordinates.
17491     *
17492     * @param m input matrix to modify
17493     * @hide
17494     */
17495    public void transformMatrixToLocal(Matrix m) {
17496        final ViewParent parent = mParent;
17497        if (parent instanceof View) {
17498            final View vp = (View) parent;
17499            vp.transformMatrixToLocal(m);
17500            m.postTranslate(vp.mScrollX, vp.mScrollY);
17501        } else if (parent instanceof ViewRootImpl) {
17502            final ViewRootImpl vr = (ViewRootImpl) parent;
17503            vr.transformMatrixToLocal(m);
17504            m.postTranslate(0, vr.mCurScrollY);
17505        }
17506
17507        m.postTranslate(-mLeft, -mTop);
17508
17509        if (!hasIdentityMatrix()) {
17510            m.postConcat(getInverseMatrix());
17511        }
17512    }
17513
17514    /**
17515     * @hide
17516     */
17517    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
17518            @ViewDebug.IntToString(from = 0, to = "x"),
17519            @ViewDebug.IntToString(from = 1, to = "y")
17520    })
17521    public int[] getLocationOnScreen() {
17522        int[] location = new int[2];
17523        getLocationOnScreen(location);
17524        return location;
17525    }
17526
17527    /**
17528     * <p>Computes the coordinates of this view on the screen. The argument
17529     * must be an array of two integers. After the method returns, the array
17530     * contains the x and y location in that order.</p>
17531     *
17532     * @param location an array of two integers in which to hold the coordinates
17533     */
17534    public void getLocationOnScreen(@Size(2) int[] location) {
17535        getLocationInWindow(location);
17536
17537        final AttachInfo info = mAttachInfo;
17538        if (info != null) {
17539            location[0] += info.mWindowLeft;
17540            location[1] += info.mWindowTop;
17541        }
17542    }
17543
17544    /**
17545     * <p>Computes the coordinates of this view in its window. The argument
17546     * must be an array of two integers. After the method returns, the array
17547     * contains the x and y location in that order.</p>
17548     *
17549     * @param location an array of two integers in which to hold the coordinates
17550     */
17551    public void getLocationInWindow(@Size(2) int[] location) {
17552        if (location == null || location.length < 2) {
17553            throw new IllegalArgumentException("location must be an array of two integers");
17554        }
17555
17556        if (mAttachInfo == null) {
17557            // When the view is not attached to a window, this method does not make sense
17558            location[0] = location[1] = 0;
17559            return;
17560        }
17561
17562        float[] position = mAttachInfo.mTmpTransformLocation;
17563        position[0] = position[1] = 0.0f;
17564
17565        if (!hasIdentityMatrix()) {
17566            getMatrix().mapPoints(position);
17567        }
17568
17569        position[0] += mLeft;
17570        position[1] += mTop;
17571
17572        ViewParent viewParent = mParent;
17573        while (viewParent instanceof View) {
17574            final View view = (View) viewParent;
17575
17576            position[0] -= view.mScrollX;
17577            position[1] -= view.mScrollY;
17578
17579            if (!view.hasIdentityMatrix()) {
17580                view.getMatrix().mapPoints(position);
17581            }
17582
17583            position[0] += view.mLeft;
17584            position[1] += view.mTop;
17585
17586            viewParent = view.mParent;
17587         }
17588
17589        if (viewParent instanceof ViewRootImpl) {
17590            // *cough*
17591            final ViewRootImpl vr = (ViewRootImpl) viewParent;
17592            position[1] -= vr.mCurScrollY;
17593        }
17594
17595        location[0] = (int) (position[0] + 0.5f);
17596        location[1] = (int) (position[1] + 0.5f);
17597    }
17598
17599    /**
17600     * {@hide}
17601     * @param id the id of the view to be found
17602     * @return the view of the specified id, null if cannot be found
17603     */
17604    protected View findViewTraversal(@IdRes int id) {
17605        if (id == mID) {
17606            return this;
17607        }
17608        return null;
17609    }
17610
17611    /**
17612     * {@hide}
17613     * @param tag the tag of the view to be found
17614     * @return the view of specified tag, null if cannot be found
17615     */
17616    protected View findViewWithTagTraversal(Object tag) {
17617        if (tag != null && tag.equals(mTag)) {
17618            return this;
17619        }
17620        return null;
17621    }
17622
17623    /**
17624     * {@hide}
17625     * @param predicate The predicate to evaluate.
17626     * @param childToSkip If not null, ignores this child during the recursive traversal.
17627     * @return The first view that matches the predicate or null.
17628     */
17629    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
17630        if (predicate.apply(this)) {
17631            return this;
17632        }
17633        return null;
17634    }
17635
17636    /**
17637     * Look for a child view with the given id.  If this view has the given
17638     * id, return this view.
17639     *
17640     * @param id The id to search for.
17641     * @return The view that has the given id in the hierarchy or null
17642     */
17643    @Nullable
17644    public final View findViewById(@IdRes int id) {
17645        if (id < 0) {
17646            return null;
17647        }
17648        return findViewTraversal(id);
17649    }
17650
17651    /**
17652     * Finds a view by its unuque and stable accessibility id.
17653     *
17654     * @param accessibilityId The searched accessibility id.
17655     * @return The found view.
17656     */
17657    final View findViewByAccessibilityId(int accessibilityId) {
17658        if (accessibilityId < 0) {
17659            return null;
17660        }
17661        return findViewByAccessibilityIdTraversal(accessibilityId);
17662    }
17663
17664    /**
17665     * Performs the traversal to find a view by its unuque and stable accessibility id.
17666     *
17667     * <strong>Note:</strong>This method does not stop at the root namespace
17668     * boundary since the user can touch the screen at an arbitrary location
17669     * potentially crossing the root namespace bounday which will send an
17670     * accessibility event to accessibility services and they should be able
17671     * to obtain the event source. Also accessibility ids are guaranteed to be
17672     * unique in the window.
17673     *
17674     * @param accessibilityId The accessibility id.
17675     * @return The found view.
17676     *
17677     * @hide
17678     */
17679    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
17680        if (getAccessibilityViewId() == accessibilityId) {
17681            return this;
17682        }
17683        return null;
17684    }
17685
17686    /**
17687     * Look for a child view with the given tag.  If this view has the given
17688     * tag, return this view.
17689     *
17690     * @param tag The tag to search for, using "tag.equals(getTag())".
17691     * @return The View that has the given tag in the hierarchy or null
17692     */
17693    public final View findViewWithTag(Object tag) {
17694        if (tag == null) {
17695            return null;
17696        }
17697        return findViewWithTagTraversal(tag);
17698    }
17699
17700    /**
17701     * {@hide}
17702     * Look for a child view that matches the specified predicate.
17703     * If this view matches the predicate, return this view.
17704     *
17705     * @param predicate The predicate to evaluate.
17706     * @return The first view that matches the predicate or null.
17707     */
17708    public final View findViewByPredicate(Predicate<View> predicate) {
17709        return findViewByPredicateTraversal(predicate, null);
17710    }
17711
17712    /**
17713     * {@hide}
17714     * Look for a child view that matches the specified predicate,
17715     * starting with the specified view and its descendents and then
17716     * recusively searching the ancestors and siblings of that view
17717     * until this view is reached.
17718     *
17719     * This method is useful in cases where the predicate does not match
17720     * a single unique view (perhaps multiple views use the same id)
17721     * and we are trying to find the view that is "closest" in scope to the
17722     * starting view.
17723     *
17724     * @param start The view to start from.
17725     * @param predicate The predicate to evaluate.
17726     * @return The first view that matches the predicate or null.
17727     */
17728    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
17729        View childToSkip = null;
17730        for (;;) {
17731            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
17732            if (view != null || start == this) {
17733                return view;
17734            }
17735
17736            ViewParent parent = start.getParent();
17737            if (parent == null || !(parent instanceof View)) {
17738                return null;
17739            }
17740
17741            childToSkip = start;
17742            start = (View) parent;
17743        }
17744    }
17745
17746    /**
17747     * Sets the identifier for this view. The identifier does not have to be
17748     * unique in this view's hierarchy. The identifier should be a positive
17749     * number.
17750     *
17751     * @see #NO_ID
17752     * @see #getId()
17753     * @see #findViewById(int)
17754     *
17755     * @param id a number used to identify the view
17756     *
17757     * @attr ref android.R.styleable#View_id
17758     */
17759    public void setId(@IdRes int id) {
17760        mID = id;
17761        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
17762            mID = generateViewId();
17763        }
17764    }
17765
17766    /**
17767     * {@hide}
17768     *
17769     * @param isRoot true if the view belongs to the root namespace, false
17770     *        otherwise
17771     */
17772    public void setIsRootNamespace(boolean isRoot) {
17773        if (isRoot) {
17774            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
17775        } else {
17776            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
17777        }
17778    }
17779
17780    /**
17781     * {@hide}
17782     *
17783     * @return true if the view belongs to the root namespace, false otherwise
17784     */
17785    public boolean isRootNamespace() {
17786        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
17787    }
17788
17789    /**
17790     * Returns this view's identifier.
17791     *
17792     * @return a positive integer used to identify the view or {@link #NO_ID}
17793     *         if the view has no ID
17794     *
17795     * @see #setId(int)
17796     * @see #findViewById(int)
17797     * @attr ref android.R.styleable#View_id
17798     */
17799    @IdRes
17800    @ViewDebug.CapturedViewProperty
17801    public int getId() {
17802        return mID;
17803    }
17804
17805    /**
17806     * Returns this view's tag.
17807     *
17808     * @return the Object stored in this view as a tag, or {@code null} if not
17809     *         set
17810     *
17811     * @see #setTag(Object)
17812     * @see #getTag(int)
17813     */
17814    @ViewDebug.ExportedProperty
17815    public Object getTag() {
17816        return mTag;
17817    }
17818
17819    /**
17820     * Sets the tag associated with this view. A tag can be used to mark
17821     * a view in its hierarchy and does not have to be unique within the
17822     * hierarchy. Tags can also be used to store data within a view without
17823     * resorting to another data structure.
17824     *
17825     * @param tag an Object to tag the view with
17826     *
17827     * @see #getTag()
17828     * @see #setTag(int, Object)
17829     */
17830    public void setTag(final Object tag) {
17831        mTag = tag;
17832    }
17833
17834    /**
17835     * Returns the tag associated with this view and the specified key.
17836     *
17837     * @param key The key identifying the tag
17838     *
17839     * @return the Object stored in this view as a tag, or {@code null} if not
17840     *         set
17841     *
17842     * @see #setTag(int, Object)
17843     * @see #getTag()
17844     */
17845    public Object getTag(int key) {
17846        if (mKeyedTags != null) return mKeyedTags.get(key);
17847        return null;
17848    }
17849
17850    /**
17851     * Sets a tag associated with this view and a key. A tag can be used
17852     * to mark a view in its hierarchy and does not have to be unique within
17853     * the hierarchy. Tags can also be used to store data within a view
17854     * without resorting to another data structure.
17855     *
17856     * The specified key should be an id declared in the resources of the
17857     * application to ensure it is unique (see the <a
17858     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
17859     * Keys identified as belonging to
17860     * the Android framework or not associated with any package will cause
17861     * an {@link IllegalArgumentException} to be thrown.
17862     *
17863     * @param key The key identifying the tag
17864     * @param tag An Object to tag the view with
17865     *
17866     * @throws IllegalArgumentException If they specified key is not valid
17867     *
17868     * @see #setTag(Object)
17869     * @see #getTag(int)
17870     */
17871    public void setTag(int key, final Object tag) {
17872        // If the package id is 0x00 or 0x01, it's either an undefined package
17873        // or a framework id
17874        if ((key >>> 24) < 2) {
17875            throw new IllegalArgumentException("The key must be an application-specific "
17876                    + "resource id.");
17877        }
17878
17879        setKeyedTag(key, tag);
17880    }
17881
17882    /**
17883     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
17884     * framework id.
17885     *
17886     * @hide
17887     */
17888    public void setTagInternal(int key, Object tag) {
17889        if ((key >>> 24) != 0x1) {
17890            throw new IllegalArgumentException("The key must be a framework-specific "
17891                    + "resource id.");
17892        }
17893
17894        setKeyedTag(key, tag);
17895    }
17896
17897    private void setKeyedTag(int key, Object tag) {
17898        if (mKeyedTags == null) {
17899            mKeyedTags = new SparseArray<Object>(2);
17900        }
17901
17902        mKeyedTags.put(key, tag);
17903    }
17904
17905    /**
17906     * Prints information about this view in the log output, with the tag
17907     * {@link #VIEW_LOG_TAG}.
17908     *
17909     * @hide
17910     */
17911    public void debug() {
17912        debug(0);
17913    }
17914
17915    /**
17916     * Prints information about this view in the log output, with the tag
17917     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
17918     * indentation defined by the <code>depth</code>.
17919     *
17920     * @param depth the indentation level
17921     *
17922     * @hide
17923     */
17924    protected void debug(int depth) {
17925        String output = debugIndent(depth - 1);
17926
17927        output += "+ " + this;
17928        int id = getId();
17929        if (id != -1) {
17930            output += " (id=" + id + ")";
17931        }
17932        Object tag = getTag();
17933        if (tag != null) {
17934            output += " (tag=" + tag + ")";
17935        }
17936        Log.d(VIEW_LOG_TAG, output);
17937
17938        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
17939            output = debugIndent(depth) + " FOCUSED";
17940            Log.d(VIEW_LOG_TAG, output);
17941        }
17942
17943        output = debugIndent(depth);
17944        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
17945                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
17946                + "} ";
17947        Log.d(VIEW_LOG_TAG, output);
17948
17949        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
17950                || mPaddingBottom != 0) {
17951            output = debugIndent(depth);
17952            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
17953                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
17954            Log.d(VIEW_LOG_TAG, output);
17955        }
17956
17957        output = debugIndent(depth);
17958        output += "mMeasureWidth=" + mMeasuredWidth +
17959                " mMeasureHeight=" + mMeasuredHeight;
17960        Log.d(VIEW_LOG_TAG, output);
17961
17962        output = debugIndent(depth);
17963        if (mLayoutParams == null) {
17964            output += "BAD! no layout params";
17965        } else {
17966            output = mLayoutParams.debug(output);
17967        }
17968        Log.d(VIEW_LOG_TAG, output);
17969
17970        output = debugIndent(depth);
17971        output += "flags={";
17972        output += View.printFlags(mViewFlags);
17973        output += "}";
17974        Log.d(VIEW_LOG_TAG, output);
17975
17976        output = debugIndent(depth);
17977        output += "privateFlags={";
17978        output += View.printPrivateFlags(mPrivateFlags);
17979        output += "}";
17980        Log.d(VIEW_LOG_TAG, output);
17981    }
17982
17983    /**
17984     * Creates a string of whitespaces used for indentation.
17985     *
17986     * @param depth the indentation level
17987     * @return a String containing (depth * 2 + 3) * 2 white spaces
17988     *
17989     * @hide
17990     */
17991    protected static String debugIndent(int depth) {
17992        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
17993        for (int i = 0; i < (depth * 2) + 3; i++) {
17994            spaces.append(' ').append(' ');
17995        }
17996        return spaces.toString();
17997    }
17998
17999    /**
18000     * <p>Return the offset of the widget's text baseline from the widget's top
18001     * boundary. If this widget does not support baseline alignment, this
18002     * method returns -1. </p>
18003     *
18004     * @return the offset of the baseline within the widget's bounds or -1
18005     *         if baseline alignment is not supported
18006     */
18007    @ViewDebug.ExportedProperty(category = "layout")
18008    public int getBaseline() {
18009        return -1;
18010    }
18011
18012    /**
18013     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18014     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18015     * a layout pass.
18016     *
18017     * @return whether the view hierarchy is currently undergoing a layout pass
18018     */
18019    public boolean isInLayout() {
18020        ViewRootImpl viewRoot = getViewRootImpl();
18021        return (viewRoot != null && viewRoot.isInLayout());
18022    }
18023
18024    /**
18025     * Call this when something has changed which has invalidated the
18026     * layout of this view. This will schedule a layout pass of the view
18027     * tree. This should not be called while the view hierarchy is currently in a layout
18028     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18029     * end of the current layout pass (and then layout will run again) or after the current
18030     * frame is drawn and the next layout occurs.
18031     *
18032     * <p>Subclasses which override this method should call the superclass method to
18033     * handle possible request-during-layout errors correctly.</p>
18034     */
18035    @CallSuper
18036    public void requestLayout() {
18037        if (mMeasureCache != null) mMeasureCache.clear();
18038
18039        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18040            // Only trigger request-during-layout logic if this is the view requesting it,
18041            // not the views in its parent hierarchy
18042            ViewRootImpl viewRoot = getViewRootImpl();
18043            if (viewRoot != null && viewRoot.isInLayout()) {
18044                if (!viewRoot.requestLayoutDuringLayout(this)) {
18045                    return;
18046                }
18047            }
18048            mAttachInfo.mViewRequestingLayout = this;
18049        }
18050
18051        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18052        mPrivateFlags |= PFLAG_INVALIDATED;
18053
18054        if (mParent != null && !mParent.isLayoutRequested()) {
18055            mParent.requestLayout();
18056        }
18057        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18058            mAttachInfo.mViewRequestingLayout = null;
18059        }
18060    }
18061
18062    /**
18063     * Forces this view to be laid out during the next layout pass.
18064     * This method does not call requestLayout() or forceLayout()
18065     * on the parent.
18066     */
18067    public void forceLayout() {
18068        if (mMeasureCache != null) mMeasureCache.clear();
18069
18070        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18071        mPrivateFlags |= PFLAG_INVALIDATED;
18072    }
18073
18074    /**
18075     * <p>
18076     * This is called to find out how big a view should be. The parent
18077     * supplies constraint information in the width and height parameters.
18078     * </p>
18079     *
18080     * <p>
18081     * The actual measurement work of a view is performed in
18082     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18083     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18084     * </p>
18085     *
18086     *
18087     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18088     *        parent
18089     * @param heightMeasureSpec Vertical space requirements as imposed by the
18090     *        parent
18091     *
18092     * @see #onMeasure(int, int)
18093     */
18094    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18095        boolean optical = isLayoutModeOptical(this);
18096        if (optical != isLayoutModeOptical(mParent)) {
18097            Insets insets = getOpticalInsets();
18098            int oWidth  = insets.left + insets.right;
18099            int oHeight = insets.top  + insets.bottom;
18100            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18101            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18102        }
18103
18104        // Suppress sign extension for the low bytes
18105        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18106        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18107
18108        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18109        final boolean isExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY &&
18110                MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
18111        final boolean matchingSize = isExactly &&
18112                getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec) &&
18113                getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
18114        if (forceLayout || !matchingSize &&
18115                (widthMeasureSpec != mOldWidthMeasureSpec ||
18116                        heightMeasureSpec != mOldHeightMeasureSpec)) {
18117
18118            // first clears the measured dimension flag
18119            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18120
18121            resolveRtlPropertiesIfNeeded();
18122
18123            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
18124            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18125                // measure ourselves, this should set the measured dimension flag back
18126                onMeasure(widthMeasureSpec, heightMeasureSpec);
18127                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18128            } else {
18129                long value = mMeasureCache.valueAt(cacheIndex);
18130                // Casting a long to int drops the high 32 bits, no mask needed
18131                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18132                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18133            }
18134
18135            // flag not set, setMeasuredDimension() was not invoked, we raise
18136            // an exception to warn the developer
18137            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18138                throw new IllegalStateException("onMeasure() did not set the"
18139                        + " measured dimension by calling"
18140                        + " setMeasuredDimension()");
18141            }
18142
18143            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18144        }
18145
18146        mOldWidthMeasureSpec = widthMeasureSpec;
18147        mOldHeightMeasureSpec = heightMeasureSpec;
18148
18149        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18150                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18151    }
18152
18153    /**
18154     * <p>
18155     * Measure the view and its content to determine the measured width and the
18156     * measured height. This method is invoked by {@link #measure(int, int)} and
18157     * should be overridden by subclasses to provide accurate and efficient
18158     * measurement of their contents.
18159     * </p>
18160     *
18161     * <p>
18162     * <strong>CONTRACT:</strong> When overriding this method, you
18163     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18164     * measured width and height of this view. Failure to do so will trigger an
18165     * <code>IllegalStateException</code>, thrown by
18166     * {@link #measure(int, int)}. Calling the superclass'
18167     * {@link #onMeasure(int, int)} is a valid use.
18168     * </p>
18169     *
18170     * <p>
18171     * The base class implementation of measure defaults to the background size,
18172     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18173     * override {@link #onMeasure(int, int)} to provide better measurements of
18174     * their content.
18175     * </p>
18176     *
18177     * <p>
18178     * If this method is overridden, it is the subclass's responsibility to make
18179     * sure the measured height and width are at least the view's minimum height
18180     * and width ({@link #getSuggestedMinimumHeight()} and
18181     * {@link #getSuggestedMinimumWidth()}).
18182     * </p>
18183     *
18184     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18185     *                         The requirements are encoded with
18186     *                         {@link android.view.View.MeasureSpec}.
18187     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18188     *                         The requirements are encoded with
18189     *                         {@link android.view.View.MeasureSpec}.
18190     *
18191     * @see #getMeasuredWidth()
18192     * @see #getMeasuredHeight()
18193     * @see #setMeasuredDimension(int, int)
18194     * @see #getSuggestedMinimumHeight()
18195     * @see #getSuggestedMinimumWidth()
18196     * @see android.view.View.MeasureSpec#getMode(int)
18197     * @see android.view.View.MeasureSpec#getSize(int)
18198     */
18199    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18200        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18201                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18202    }
18203
18204    /**
18205     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18206     * measured width and measured height. Failing to do so will trigger an
18207     * exception at measurement time.</p>
18208     *
18209     * @param measuredWidth The measured width of this view.  May be a complex
18210     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18211     * {@link #MEASURED_STATE_TOO_SMALL}.
18212     * @param measuredHeight The measured height of this view.  May be a complex
18213     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18214     * {@link #MEASURED_STATE_TOO_SMALL}.
18215     */
18216    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18217        boolean optical = isLayoutModeOptical(this);
18218        if (optical != isLayoutModeOptical(mParent)) {
18219            Insets insets = getOpticalInsets();
18220            int opticalWidth  = insets.left + insets.right;
18221            int opticalHeight = insets.top  + insets.bottom;
18222
18223            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18224            measuredHeight += optical ? opticalHeight : -opticalHeight;
18225        }
18226        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18227    }
18228
18229    /**
18230     * Sets the measured dimension without extra processing for things like optical bounds.
18231     * Useful for reapplying consistent values that have already been cooked with adjustments
18232     * for optical bounds, etc. such as those from the measurement cache.
18233     *
18234     * @param measuredWidth The measured width of this view.  May be a complex
18235     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18236     * {@link #MEASURED_STATE_TOO_SMALL}.
18237     * @param measuredHeight The measured height of this view.  May be a complex
18238     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18239     * {@link #MEASURED_STATE_TOO_SMALL}.
18240     */
18241    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18242        mMeasuredWidth = measuredWidth;
18243        mMeasuredHeight = measuredHeight;
18244
18245        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18246    }
18247
18248    /**
18249     * Merge two states as returned by {@link #getMeasuredState()}.
18250     * @param curState The current state as returned from a view or the result
18251     * of combining multiple views.
18252     * @param newState The new view state to combine.
18253     * @return Returns a new integer reflecting the combination of the two
18254     * states.
18255     */
18256    public static int combineMeasuredStates(int curState, int newState) {
18257        return curState | newState;
18258    }
18259
18260    /**
18261     * Version of {@link #resolveSizeAndState(int, int, int)}
18262     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18263     */
18264    public static int resolveSize(int size, int measureSpec) {
18265        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18266    }
18267
18268    /**
18269     * Utility to reconcile a desired size and state, with constraints imposed
18270     * by a MeasureSpec. Will take the desired size, unless a different size
18271     * is imposed by the constraints. The returned value is a compound integer,
18272     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18273     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18274     * resulting size is smaller than the size the view wants to be.
18275     *
18276     * @param size How big the view wants to be.
18277     * @param measureSpec Constraints imposed by the parent.
18278     * @param childMeasuredState Size information bit mask for the view's
18279     *                           children.
18280     * @return Size information bit mask as defined by
18281     *         {@link #MEASURED_SIZE_MASK} and
18282     *         {@link #MEASURED_STATE_TOO_SMALL}.
18283     */
18284    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18285        final int specMode = MeasureSpec.getMode(measureSpec);
18286        final int specSize = MeasureSpec.getSize(measureSpec);
18287        final int result;
18288        switch (specMode) {
18289            case MeasureSpec.AT_MOST:
18290                if (specSize < size) {
18291                    result = specSize | MEASURED_STATE_TOO_SMALL;
18292                } else {
18293                    result = size;
18294                }
18295                break;
18296            case MeasureSpec.EXACTLY:
18297                result = specSize;
18298                break;
18299            case MeasureSpec.UNSPECIFIED:
18300            default:
18301                result = size;
18302        }
18303        return result | (childMeasuredState & MEASURED_STATE_MASK);
18304    }
18305
18306    /**
18307     * Utility to return a default size. Uses the supplied size if the
18308     * MeasureSpec imposed no constraints. Will get larger if allowed
18309     * by the MeasureSpec.
18310     *
18311     * @param size Default size for this view
18312     * @param measureSpec Constraints imposed by the parent
18313     * @return The size this view should be.
18314     */
18315    public static int getDefaultSize(int size, int measureSpec) {
18316        int result = size;
18317        int specMode = MeasureSpec.getMode(measureSpec);
18318        int specSize = MeasureSpec.getSize(measureSpec);
18319
18320        switch (specMode) {
18321        case MeasureSpec.UNSPECIFIED:
18322            result = size;
18323            break;
18324        case MeasureSpec.AT_MOST:
18325        case MeasureSpec.EXACTLY:
18326            result = specSize;
18327            break;
18328        }
18329        return result;
18330    }
18331
18332    /**
18333     * Returns the suggested minimum height that the view should use. This
18334     * returns the maximum of the view's minimum height
18335     * and the background's minimum height
18336     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
18337     * <p>
18338     * When being used in {@link #onMeasure(int, int)}, the caller should still
18339     * ensure the returned height is within the requirements of the parent.
18340     *
18341     * @return The suggested minimum height of the view.
18342     */
18343    protected int getSuggestedMinimumHeight() {
18344        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
18345
18346    }
18347
18348    /**
18349     * Returns the suggested minimum width that the view should use. This
18350     * returns the maximum of the view's minimum width)
18351     * and the background's minimum width
18352     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
18353     * <p>
18354     * When being used in {@link #onMeasure(int, int)}, the caller should still
18355     * ensure the returned width is within the requirements of the parent.
18356     *
18357     * @return The suggested minimum width of the view.
18358     */
18359    protected int getSuggestedMinimumWidth() {
18360        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
18361    }
18362
18363    /**
18364     * Returns the minimum height of the view.
18365     *
18366     * @return the minimum height the view will try to be.
18367     *
18368     * @see #setMinimumHeight(int)
18369     *
18370     * @attr ref android.R.styleable#View_minHeight
18371     */
18372    public int getMinimumHeight() {
18373        return mMinHeight;
18374    }
18375
18376    /**
18377     * Sets the minimum height of the view. It is not guaranteed the view will
18378     * be able to achieve this minimum height (for example, if its parent layout
18379     * constrains it with less available height).
18380     *
18381     * @param minHeight The minimum height the view will try to be.
18382     *
18383     * @see #getMinimumHeight()
18384     *
18385     * @attr ref android.R.styleable#View_minHeight
18386     */
18387    public void setMinimumHeight(int minHeight) {
18388        mMinHeight = minHeight;
18389        requestLayout();
18390    }
18391
18392    /**
18393     * Returns the minimum width of the view.
18394     *
18395     * @return the minimum width the view will try to be.
18396     *
18397     * @see #setMinimumWidth(int)
18398     *
18399     * @attr ref android.R.styleable#View_minWidth
18400     */
18401    public int getMinimumWidth() {
18402        return mMinWidth;
18403    }
18404
18405    /**
18406     * Sets the minimum width of the view. It is not guaranteed the view will
18407     * be able to achieve this minimum width (for example, if its parent layout
18408     * constrains it with less available width).
18409     *
18410     * @param minWidth The minimum width the view will try to be.
18411     *
18412     * @see #getMinimumWidth()
18413     *
18414     * @attr ref android.R.styleable#View_minWidth
18415     */
18416    public void setMinimumWidth(int minWidth) {
18417        mMinWidth = minWidth;
18418        requestLayout();
18419
18420    }
18421
18422    /**
18423     * Get the animation currently associated with this view.
18424     *
18425     * @return The animation that is currently playing or
18426     *         scheduled to play for this view.
18427     */
18428    public Animation getAnimation() {
18429        return mCurrentAnimation;
18430    }
18431
18432    /**
18433     * Start the specified animation now.
18434     *
18435     * @param animation the animation to start now
18436     */
18437    public void startAnimation(Animation animation) {
18438        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
18439        setAnimation(animation);
18440        invalidateParentCaches();
18441        invalidate(true);
18442    }
18443
18444    /**
18445     * Cancels any animations for this view.
18446     */
18447    public void clearAnimation() {
18448        if (mCurrentAnimation != null) {
18449            mCurrentAnimation.detach();
18450        }
18451        mCurrentAnimation = null;
18452        invalidateParentIfNeeded();
18453    }
18454
18455    /**
18456     * Sets the next animation to play for this view.
18457     * If you want the animation to play immediately, use
18458     * {@link #startAnimation(android.view.animation.Animation)} instead.
18459     * This method provides allows fine-grained
18460     * control over the start time and invalidation, but you
18461     * must make sure that 1) the animation has a start time set, and
18462     * 2) the view's parent (which controls animations on its children)
18463     * will be invalidated when the animation is supposed to
18464     * start.
18465     *
18466     * @param animation The next animation, or null.
18467     */
18468    public void setAnimation(Animation animation) {
18469        mCurrentAnimation = animation;
18470
18471        if (animation != null) {
18472            // If the screen is off assume the animation start time is now instead of
18473            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
18474            // would cause the animation to start when the screen turns back on
18475            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
18476                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
18477                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
18478            }
18479            animation.reset();
18480        }
18481    }
18482
18483    /**
18484     * Invoked by a parent ViewGroup to notify the start of the animation
18485     * currently associated with this view. If you override this method,
18486     * always call super.onAnimationStart();
18487     *
18488     * @see #setAnimation(android.view.animation.Animation)
18489     * @see #getAnimation()
18490     */
18491    @CallSuper
18492    protected void onAnimationStart() {
18493        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
18494    }
18495
18496    /**
18497     * Invoked by a parent ViewGroup to notify the end of the animation
18498     * currently associated with this view. If you override this method,
18499     * always call super.onAnimationEnd();
18500     *
18501     * @see #setAnimation(android.view.animation.Animation)
18502     * @see #getAnimation()
18503     */
18504    @CallSuper
18505    protected void onAnimationEnd() {
18506        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
18507    }
18508
18509    /**
18510     * Invoked if there is a Transform that involves alpha. Subclass that can
18511     * draw themselves with the specified alpha should return true, and then
18512     * respect that alpha when their onDraw() is called. If this returns false
18513     * then the view may be redirected to draw into an offscreen buffer to
18514     * fulfill the request, which will look fine, but may be slower than if the
18515     * subclass handles it internally. The default implementation returns false.
18516     *
18517     * @param alpha The alpha (0..255) to apply to the view's drawing
18518     * @return true if the view can draw with the specified alpha.
18519     */
18520    protected boolean onSetAlpha(int alpha) {
18521        return false;
18522    }
18523
18524    /**
18525     * This is used by the RootView to perform an optimization when
18526     * the view hierarchy contains one or several SurfaceView.
18527     * SurfaceView is always considered transparent, but its children are not,
18528     * therefore all View objects remove themselves from the global transparent
18529     * region (passed as a parameter to this function).
18530     *
18531     * @param region The transparent region for this ViewAncestor (window).
18532     *
18533     * @return Returns true if the effective visibility of the view at this
18534     * point is opaque, regardless of the transparent region; returns false
18535     * if it is possible for underlying windows to be seen behind the view.
18536     *
18537     * {@hide}
18538     */
18539    public boolean gatherTransparentRegion(Region region) {
18540        final AttachInfo attachInfo = mAttachInfo;
18541        if (region != null && attachInfo != null) {
18542            final int pflags = mPrivateFlags;
18543            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
18544                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
18545                // remove it from the transparent region.
18546                final int[] location = attachInfo.mTransparentLocation;
18547                getLocationInWindow(location);
18548                region.op(location[0], location[1], location[0] + mRight - mLeft,
18549                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
18550            } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null &&
18551                    mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
18552                // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
18553                // exists, so we remove the background drawable's non-transparent
18554                // parts from this transparent region.
18555                applyDrawableToTransparentRegion(mBackground, region);
18556            }
18557            final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
18558            if (foreground != null) {
18559                applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
18560            }
18561        }
18562        return true;
18563    }
18564
18565    /**
18566     * Play a sound effect for this view.
18567     *
18568     * <p>The framework will play sound effects for some built in actions, such as
18569     * clicking, but you may wish to play these effects in your widget,
18570     * for instance, for internal navigation.
18571     *
18572     * <p>The sound effect will only be played if sound effects are enabled by the user, and
18573     * {@link #isSoundEffectsEnabled()} is true.
18574     *
18575     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
18576     */
18577    public void playSoundEffect(int soundConstant) {
18578        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
18579            return;
18580        }
18581        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
18582    }
18583
18584    /**
18585     * BZZZTT!!1!
18586     *
18587     * <p>Provide haptic feedback to the user for this view.
18588     *
18589     * <p>The framework will provide haptic feedback for some built in actions,
18590     * such as long presses, but you may wish to provide feedback for your
18591     * own widget.
18592     *
18593     * <p>The feedback will only be performed if
18594     * {@link #isHapticFeedbackEnabled()} is true.
18595     *
18596     * @param feedbackConstant One of the constants defined in
18597     * {@link HapticFeedbackConstants}
18598     */
18599    public boolean performHapticFeedback(int feedbackConstant) {
18600        return performHapticFeedback(feedbackConstant, 0);
18601    }
18602
18603    /**
18604     * BZZZTT!!1!
18605     *
18606     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
18607     *
18608     * @param feedbackConstant One of the constants defined in
18609     * {@link HapticFeedbackConstants}
18610     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
18611     */
18612    public boolean performHapticFeedback(int feedbackConstant, int flags) {
18613        if (mAttachInfo == null) {
18614            return false;
18615        }
18616        //noinspection SimplifiableIfStatement
18617        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
18618                && !isHapticFeedbackEnabled()) {
18619            return false;
18620        }
18621        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
18622                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
18623    }
18624
18625    /**
18626     * Request that the visibility of the status bar or other screen/window
18627     * decorations be changed.
18628     *
18629     * <p>This method is used to put the over device UI into temporary modes
18630     * where the user's attention is focused more on the application content,
18631     * by dimming or hiding surrounding system affordances.  This is typically
18632     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
18633     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
18634     * to be placed behind the action bar (and with these flags other system
18635     * affordances) so that smooth transitions between hiding and showing them
18636     * can be done.
18637     *
18638     * <p>Two representative examples of the use of system UI visibility is
18639     * implementing a content browsing application (like a magazine reader)
18640     * and a video playing application.
18641     *
18642     * <p>The first code shows a typical implementation of a View in a content
18643     * browsing application.  In this implementation, the application goes
18644     * into a content-oriented mode by hiding the status bar and action bar,
18645     * and putting the navigation elements into lights out mode.  The user can
18646     * then interact with content while in this mode.  Such an application should
18647     * provide an easy way for the user to toggle out of the mode (such as to
18648     * check information in the status bar or access notifications).  In the
18649     * implementation here, this is done simply by tapping on the content.
18650     *
18651     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
18652     *      content}
18653     *
18654     * <p>This second code sample shows a typical implementation of a View
18655     * in a video playing application.  In this situation, while the video is
18656     * playing the application would like to go into a complete full-screen mode,
18657     * to use as much of the display as possible for the video.  When in this state
18658     * the user can not interact with the application; the system intercepts
18659     * touching on the screen to pop the UI out of full screen mode.  See
18660     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
18661     *
18662     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
18663     *      content}
18664     *
18665     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18666     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18667     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18668     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18669     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18670     */
18671    public void setSystemUiVisibility(int visibility) {
18672        if (visibility != mSystemUiVisibility) {
18673            mSystemUiVisibility = visibility;
18674            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18675                mParent.recomputeViewAttributes(this);
18676            }
18677        }
18678    }
18679
18680    /**
18681     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
18682     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
18683     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
18684     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
18685     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
18686     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
18687     */
18688    public int getSystemUiVisibility() {
18689        return mSystemUiVisibility;
18690    }
18691
18692    /**
18693     * Returns the current system UI visibility that is currently set for
18694     * the entire window.  This is the combination of the
18695     * {@link #setSystemUiVisibility(int)} values supplied by all of the
18696     * views in the window.
18697     */
18698    public int getWindowSystemUiVisibility() {
18699        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
18700    }
18701
18702    /**
18703     * Override to find out when the window's requested system UI visibility
18704     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
18705     * This is different from the callbacks received through
18706     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
18707     * in that this is only telling you about the local request of the window,
18708     * not the actual values applied by the system.
18709     */
18710    public void onWindowSystemUiVisibilityChanged(int visible) {
18711    }
18712
18713    /**
18714     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
18715     * the view hierarchy.
18716     */
18717    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
18718        onWindowSystemUiVisibilityChanged(visible);
18719    }
18720
18721    /**
18722     * Set a listener to receive callbacks when the visibility of the system bar changes.
18723     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
18724     */
18725    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
18726        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
18727        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
18728            mParent.recomputeViewAttributes(this);
18729        }
18730    }
18731
18732    /**
18733     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
18734     * the view hierarchy.
18735     */
18736    public void dispatchSystemUiVisibilityChanged(int visibility) {
18737        ListenerInfo li = mListenerInfo;
18738        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
18739            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
18740                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
18741        }
18742    }
18743
18744    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
18745        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
18746        if (val != mSystemUiVisibility) {
18747            setSystemUiVisibility(val);
18748            return true;
18749        }
18750        return false;
18751    }
18752
18753    /** @hide */
18754    public void setDisabledSystemUiVisibility(int flags) {
18755        if (mAttachInfo != null) {
18756            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
18757                mAttachInfo.mDisabledSystemUiVisibility = flags;
18758                if (mParent != null) {
18759                    mParent.recomputeViewAttributes(this);
18760                }
18761            }
18762        }
18763    }
18764
18765    /**
18766     * Creates an image that the system displays during the drag and drop
18767     * operation. This is called a &quot;drag shadow&quot;. The default implementation
18768     * for a DragShadowBuilder based on a View returns an image that has exactly the same
18769     * appearance as the given View. The default also positions the center of the drag shadow
18770     * directly under the touch point. If no View is provided (the constructor with no parameters
18771     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
18772     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
18773     * default is an invisible drag shadow.
18774     * <p>
18775     * You are not required to use the View you provide to the constructor as the basis of the
18776     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
18777     * anything you want as the drag shadow.
18778     * </p>
18779     * <p>
18780     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
18781     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
18782     *  size and position of the drag shadow. It uses this data to construct a
18783     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
18784     *  so that your application can draw the shadow image in the Canvas.
18785     * </p>
18786     *
18787     * <div class="special reference">
18788     * <h3>Developer Guides</h3>
18789     * <p>For a guide to implementing drag and drop features, read the
18790     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
18791     * </div>
18792     */
18793    public static class DragShadowBuilder {
18794        private final WeakReference<View> mView;
18795
18796        /**
18797         * Constructs a shadow image builder based on a View. By default, the resulting drag
18798         * shadow will have the same appearance and dimensions as the View, with the touch point
18799         * over the center of the View.
18800         * @param view A View. Any View in scope can be used.
18801         */
18802        public DragShadowBuilder(View view) {
18803            mView = new WeakReference<View>(view);
18804        }
18805
18806        /**
18807         * Construct a shadow builder object with no associated View.  This
18808         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
18809         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
18810         * to supply the drag shadow's dimensions and appearance without
18811         * reference to any View object. If they are not overridden, then the result is an
18812         * invisible drag shadow.
18813         */
18814        public DragShadowBuilder() {
18815            mView = new WeakReference<View>(null);
18816        }
18817
18818        /**
18819         * Returns the View object that had been passed to the
18820         * {@link #View.DragShadowBuilder(View)}
18821         * constructor.  If that View parameter was {@code null} or if the
18822         * {@link #View.DragShadowBuilder()}
18823         * constructor was used to instantiate the builder object, this method will return
18824         * null.
18825         *
18826         * @return The View object associate with this builder object.
18827         */
18828        @SuppressWarnings({"JavadocReference"})
18829        final public View getView() {
18830            return mView.get();
18831        }
18832
18833        /**
18834         * Provides the metrics for the shadow image. These include the dimensions of
18835         * the shadow image, and the point within that shadow that should
18836         * be centered under the touch location while dragging.
18837         * <p>
18838         * The default implementation sets the dimensions of the shadow to be the
18839         * same as the dimensions of the View itself and centers the shadow under
18840         * the touch point.
18841         * </p>
18842         *
18843         * @param shadowSize A {@link android.graphics.Point} containing the width and height
18844         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
18845         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
18846         * image.
18847         *
18848         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
18849         * shadow image that should be underneath the touch point during the drag and drop
18850         * operation. Your application must set {@link android.graphics.Point#x} to the
18851         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
18852         */
18853        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
18854            final View view = mView.get();
18855            if (view != null) {
18856                shadowSize.set(view.getWidth(), view.getHeight());
18857                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
18858            } else {
18859                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
18860            }
18861        }
18862
18863        /**
18864         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
18865         * based on the dimensions it received from the
18866         * {@link #onProvideShadowMetrics(Point, Point)} callback.
18867         *
18868         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
18869         */
18870        public void onDrawShadow(Canvas canvas) {
18871            final View view = mView.get();
18872            if (view != null) {
18873                view.draw(canvas);
18874            } else {
18875                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
18876            }
18877        }
18878    }
18879
18880    /**
18881     * Starts a drag and drop operation. When your application calls this method, it passes a
18882     * {@link android.view.View.DragShadowBuilder} object to the system. The
18883     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
18884     * to get metrics for the drag shadow, and then calls the object's
18885     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
18886     * <p>
18887     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
18888     *  drag events to all the View objects in your application that are currently visible. It does
18889     *  this either by calling the View object's drag listener (an implementation of
18890     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
18891     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
18892     *  Both are passed a {@link android.view.DragEvent} object that has a
18893     *  {@link android.view.DragEvent#getAction()} value of
18894     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
18895     * </p>
18896     * <p>
18897     * Your application can invoke startDrag() on any attached View object. The View object does not
18898     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
18899     * be related to the View the user selected for dragging.
18900     * </p>
18901     * @param data A {@link android.content.ClipData} object pointing to the data to be
18902     * transferred by the drag and drop operation.
18903     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
18904     * drag shadow.
18905     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
18906     * drop operation. This Object is put into every DragEvent object sent by the system during the
18907     * current drag.
18908     * <p>
18909     * myLocalState is a lightweight mechanism for the sending information from the dragged View
18910     * to the target Views. For example, it can contain flags that differentiate between a
18911     * a copy operation and a move operation.
18912     * </p>
18913     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
18914     * so the parameter should be set to 0.
18915     * @return {@code true} if the method completes successfully, or
18916     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
18917     * do a drag, and so no drag operation is in progress.
18918     */
18919    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
18920            Object myLocalState, int flags) {
18921        if (ViewDebug.DEBUG_DRAG) {
18922            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
18923        }
18924        boolean okay = false;
18925
18926        Point shadowSize = new Point();
18927        Point shadowTouchPoint = new Point();
18928        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
18929
18930        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
18931                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
18932            throw new IllegalStateException("Drag shadow dimensions must not be negative");
18933        }
18934
18935        if (ViewDebug.DEBUG_DRAG) {
18936            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
18937                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
18938        }
18939        Surface surface = new Surface();
18940        try {
18941            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
18942                    flags, shadowSize.x, shadowSize.y, surface);
18943            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
18944                    + " surface=" + surface);
18945            if (token != null) {
18946                Canvas canvas = surface.lockCanvas(null);
18947                try {
18948                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
18949                    shadowBuilder.onDrawShadow(canvas);
18950                } finally {
18951                    surface.unlockCanvasAndPost(canvas);
18952                }
18953
18954                final ViewRootImpl root = getViewRootImpl();
18955
18956                // Cache the local state object for delivery with DragEvents
18957                root.setLocalDragState(myLocalState);
18958
18959                // repurpose 'shadowSize' for the last touch point
18960                root.getLastTouchPoint(shadowSize);
18961
18962                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
18963                        shadowSize.x, shadowSize.y,
18964                        shadowTouchPoint.x, shadowTouchPoint.y, data);
18965                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
18966
18967                // Off and running!  Release our local surface instance; the drag
18968                // shadow surface is now managed by the system process.
18969                surface.release();
18970            }
18971        } catch (Exception e) {
18972            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
18973            surface.destroy();
18974        }
18975
18976        return okay;
18977    }
18978
18979    /**
18980     * Handles drag events sent by the system following a call to
18981     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
18982     *<p>
18983     * When the system calls this method, it passes a
18984     * {@link android.view.DragEvent} object. A call to
18985     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
18986     * in DragEvent. The method uses these to determine what is happening in the drag and drop
18987     * operation.
18988     * @param event The {@link android.view.DragEvent} sent by the system.
18989     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
18990     * in DragEvent, indicating the type of drag event represented by this object.
18991     * @return {@code true} if the method was successful, otherwise {@code false}.
18992     * <p>
18993     *  The method should return {@code true} in response to an action type of
18994     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
18995     *  operation.
18996     * </p>
18997     * <p>
18998     *  The method should also return {@code true} in response to an action type of
18999     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19000     *  {@code false} if it didn't.
19001     * </p>
19002     */
19003    public boolean onDragEvent(DragEvent event) {
19004        return false;
19005    }
19006
19007    /**
19008     * Detects if this View is enabled and has a drag event listener.
19009     * If both are true, then it calls the drag event listener with the
19010     * {@link android.view.DragEvent} it received. If the drag event listener returns
19011     * {@code true}, then dispatchDragEvent() returns {@code true}.
19012     * <p>
19013     * For all other cases, the method calls the
19014     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19015     * method and returns its result.
19016     * </p>
19017     * <p>
19018     * This ensures that a drag event is always consumed, even if the View does not have a drag
19019     * event listener. However, if the View has a listener and the listener returns true, then
19020     * onDragEvent() is not called.
19021     * </p>
19022     */
19023    public boolean dispatchDragEvent(DragEvent event) {
19024        ListenerInfo li = mListenerInfo;
19025        //noinspection SimplifiableIfStatement
19026        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19027                && li.mOnDragListener.onDrag(this, event)) {
19028            return true;
19029        }
19030        return onDragEvent(event);
19031    }
19032
19033    boolean canAcceptDrag() {
19034        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19035    }
19036
19037    /**
19038     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19039     * it is ever exposed at all.
19040     * @hide
19041     */
19042    public void onCloseSystemDialogs(String reason) {
19043    }
19044
19045    /**
19046     * Given a Drawable whose bounds have been set to draw into this view,
19047     * update a Region being computed for
19048     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19049     * that any non-transparent parts of the Drawable are removed from the
19050     * given transparent region.
19051     *
19052     * @param dr The Drawable whose transparency is to be applied to the region.
19053     * @param region A Region holding the current transparency information,
19054     * where any parts of the region that are set are considered to be
19055     * transparent.  On return, this region will be modified to have the
19056     * transparency information reduced by the corresponding parts of the
19057     * Drawable that are not transparent.
19058     * {@hide}
19059     */
19060    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19061        if (DBG) {
19062            Log.i("View", "Getting transparent region for: " + this);
19063        }
19064        final Region r = dr.getTransparentRegion();
19065        final Rect db = dr.getBounds();
19066        final AttachInfo attachInfo = mAttachInfo;
19067        if (r != null && attachInfo != null) {
19068            final int w = getRight()-getLeft();
19069            final int h = getBottom()-getTop();
19070            if (db.left > 0) {
19071                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19072                r.op(0, 0, db.left, h, Region.Op.UNION);
19073            }
19074            if (db.right < w) {
19075                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19076                r.op(db.right, 0, w, h, Region.Op.UNION);
19077            }
19078            if (db.top > 0) {
19079                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19080                r.op(0, 0, w, db.top, Region.Op.UNION);
19081            }
19082            if (db.bottom < h) {
19083                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19084                r.op(0, db.bottom, w, h, Region.Op.UNION);
19085            }
19086            final int[] location = attachInfo.mTransparentLocation;
19087            getLocationInWindow(location);
19088            r.translate(location[0], location[1]);
19089            region.op(r, Region.Op.INTERSECT);
19090        } else {
19091            region.op(db, Region.Op.DIFFERENCE);
19092        }
19093    }
19094
19095    private void checkForLongClick(int delayOffset) {
19096        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19097            mHasPerformedLongPress = false;
19098
19099            if (mPendingCheckForLongPress == null) {
19100                mPendingCheckForLongPress = new CheckForLongPress();
19101            }
19102            mPendingCheckForLongPress.rememberWindowAttachCount();
19103            postDelayed(mPendingCheckForLongPress,
19104                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19105        }
19106    }
19107
19108    /**
19109     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19110     * LayoutInflater} class, which provides a full range of options for view inflation.
19111     *
19112     * @param context The Context object for your activity or application.
19113     * @param resource The resource ID to inflate
19114     * @param root A view group that will be the parent.  Used to properly inflate the
19115     * layout_* parameters.
19116     * @see LayoutInflater
19117     */
19118    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19119        LayoutInflater factory = LayoutInflater.from(context);
19120        return factory.inflate(resource, root);
19121    }
19122
19123    /**
19124     * Scroll the view with standard behavior for scrolling beyond the normal
19125     * content boundaries. Views that call this method should override
19126     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19127     * results of an over-scroll operation.
19128     *
19129     * Views can use this method to handle any touch or fling-based scrolling.
19130     *
19131     * @param deltaX Change in X in pixels
19132     * @param deltaY Change in Y in pixels
19133     * @param scrollX Current X scroll value in pixels before applying deltaX
19134     * @param scrollY Current Y scroll value in pixels before applying deltaY
19135     * @param scrollRangeX Maximum content scroll range along the X axis
19136     * @param scrollRangeY Maximum content scroll range along the Y axis
19137     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19138     *          along the X axis.
19139     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19140     *          along the Y axis.
19141     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19142     * @return true if scrolling was clamped to an over-scroll boundary along either
19143     *          axis, false otherwise.
19144     */
19145    @SuppressWarnings({"UnusedParameters"})
19146    protected boolean overScrollBy(int deltaX, int deltaY,
19147            int scrollX, int scrollY,
19148            int scrollRangeX, int scrollRangeY,
19149            int maxOverScrollX, int maxOverScrollY,
19150            boolean isTouchEvent) {
19151        final int overScrollMode = mOverScrollMode;
19152        final boolean canScrollHorizontal =
19153                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19154        final boolean canScrollVertical =
19155                computeVerticalScrollRange() > computeVerticalScrollExtent();
19156        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19157                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19158        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19159                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19160
19161        int newScrollX = scrollX + deltaX;
19162        if (!overScrollHorizontal) {
19163            maxOverScrollX = 0;
19164        }
19165
19166        int newScrollY = scrollY + deltaY;
19167        if (!overScrollVertical) {
19168            maxOverScrollY = 0;
19169        }
19170
19171        // Clamp values if at the limits and record
19172        final int left = -maxOverScrollX;
19173        final int right = maxOverScrollX + scrollRangeX;
19174        final int top = -maxOverScrollY;
19175        final int bottom = maxOverScrollY + scrollRangeY;
19176
19177        boolean clampedX = false;
19178        if (newScrollX > right) {
19179            newScrollX = right;
19180            clampedX = true;
19181        } else if (newScrollX < left) {
19182            newScrollX = left;
19183            clampedX = true;
19184        }
19185
19186        boolean clampedY = false;
19187        if (newScrollY > bottom) {
19188            newScrollY = bottom;
19189            clampedY = true;
19190        } else if (newScrollY < top) {
19191            newScrollY = top;
19192            clampedY = true;
19193        }
19194
19195        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19196
19197        return clampedX || clampedY;
19198    }
19199
19200    /**
19201     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19202     * respond to the results of an over-scroll operation.
19203     *
19204     * @param scrollX New X scroll value in pixels
19205     * @param scrollY New Y scroll value in pixels
19206     * @param clampedX True if scrollX was clamped to an over-scroll boundary
19207     * @param clampedY True if scrollY was clamped to an over-scroll boundary
19208     */
19209    protected void onOverScrolled(int scrollX, int scrollY,
19210            boolean clampedX, boolean clampedY) {
19211        // Intentionally empty.
19212    }
19213
19214    /**
19215     * Returns the over-scroll mode for this view. The result will be
19216     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19217     * (allow over-scrolling only if the view content is larger than the container),
19218     * or {@link #OVER_SCROLL_NEVER}.
19219     *
19220     * @return This view's over-scroll mode.
19221     */
19222    public int getOverScrollMode() {
19223        return mOverScrollMode;
19224    }
19225
19226    /**
19227     * Set the over-scroll mode for this view. Valid over-scroll modes are
19228     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19229     * (allow over-scrolling only if the view content is larger than the container),
19230     * or {@link #OVER_SCROLL_NEVER}.
19231     *
19232     * Setting the over-scroll mode of a view will have an effect only if the
19233     * view is capable of scrolling.
19234     *
19235     * @param overScrollMode The new over-scroll mode for this view.
19236     */
19237    public void setOverScrollMode(int overScrollMode) {
19238        if (overScrollMode != OVER_SCROLL_ALWAYS &&
19239                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19240                overScrollMode != OVER_SCROLL_NEVER) {
19241            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19242        }
19243        mOverScrollMode = overScrollMode;
19244    }
19245
19246    /**
19247     * Enable or disable nested scrolling for this view.
19248     *
19249     * <p>If this property is set to true the view will be permitted to initiate nested
19250     * scrolling operations with a compatible parent view in the current hierarchy. If this
19251     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19252     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19253     * the nested scroll.</p>
19254     *
19255     * @param enabled true to enable nested scrolling, false to disable
19256     *
19257     * @see #isNestedScrollingEnabled()
19258     */
19259    public void setNestedScrollingEnabled(boolean enabled) {
19260        if (enabled) {
19261            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19262        } else {
19263            stopNestedScroll();
19264            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19265        }
19266    }
19267
19268    /**
19269     * Returns true if nested scrolling is enabled for this view.
19270     *
19271     * <p>If nested scrolling is enabled and this View class implementation supports it,
19272     * this view will act as a nested scrolling child view when applicable, forwarding data
19273     * about the scroll operation in progress to a compatible and cooperating nested scrolling
19274     * parent.</p>
19275     *
19276     * @return true if nested scrolling is enabled
19277     *
19278     * @see #setNestedScrollingEnabled(boolean)
19279     */
19280    public boolean isNestedScrollingEnabled() {
19281        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19282                PFLAG3_NESTED_SCROLLING_ENABLED;
19283    }
19284
19285    /**
19286     * Begin a nestable scroll operation along the given axes.
19287     *
19288     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19289     *
19290     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19291     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19292     * In the case of touch scrolling the nested scroll will be terminated automatically in
19293     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19294     * In the event of programmatic scrolling the caller must explicitly call
19295     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19296     *
19297     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19298     * If it returns false the caller may ignore the rest of this contract until the next scroll.
19299     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19300     *
19301     * <p>At each incremental step of the scroll the caller should invoke
19302     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19303     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19304     * parent at least partially consumed the scroll and the caller should adjust the amount it
19305     * scrolls by.</p>
19306     *
19307     * <p>After applying the remainder of the scroll delta the caller should invoke
19308     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19309     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19310     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19311     * </p>
19312     *
19313     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19314     *             {@link #SCROLL_AXIS_VERTICAL}.
19315     * @return true if a cooperative parent was found and nested scrolling has been enabled for
19316     *         the current gesture.
19317     *
19318     * @see #stopNestedScroll()
19319     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19320     * @see #dispatchNestedScroll(int, int, int, int, int[])
19321     */
19322    public boolean startNestedScroll(int axes) {
19323        if (hasNestedScrollingParent()) {
19324            // Already in progress
19325            return true;
19326        }
19327        if (isNestedScrollingEnabled()) {
19328            ViewParent p = getParent();
19329            View child = this;
19330            while (p != null) {
19331                try {
19332                    if (p.onStartNestedScroll(child, this, axes)) {
19333                        mNestedScrollingParent = p;
19334                        p.onNestedScrollAccepted(child, this, axes);
19335                        return true;
19336                    }
19337                } catch (AbstractMethodError e) {
19338                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
19339                            "method onStartNestedScroll", e);
19340                    // Allow the search upward to continue
19341                }
19342                if (p instanceof View) {
19343                    child = (View) p;
19344                }
19345                p = p.getParent();
19346            }
19347        }
19348        return false;
19349    }
19350
19351    /**
19352     * Stop a nested scroll in progress.
19353     *
19354     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
19355     *
19356     * @see #startNestedScroll(int)
19357     */
19358    public void stopNestedScroll() {
19359        if (mNestedScrollingParent != null) {
19360            mNestedScrollingParent.onStopNestedScroll(this);
19361            mNestedScrollingParent = null;
19362        }
19363    }
19364
19365    /**
19366     * Returns true if this view has a nested scrolling parent.
19367     *
19368     * <p>The presence of a nested scrolling parent indicates that this view has initiated
19369     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
19370     *
19371     * @return whether this view has a nested scrolling parent
19372     */
19373    public boolean hasNestedScrollingParent() {
19374        return mNestedScrollingParent != null;
19375    }
19376
19377    /**
19378     * Dispatch one step of a nested scroll in progress.
19379     *
19380     * <p>Implementations of views that support nested scrolling should call this to report
19381     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
19382     * is not currently in progress or nested scrolling is not
19383     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
19384     *
19385     * <p>Compatible View implementations should also call
19386     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
19387     * consuming a component of the scroll event themselves.</p>
19388     *
19389     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
19390     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
19391     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
19392     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
19393     * @param offsetInWindow Optional. If not null, on return this will contain the offset
19394     *                       in local view coordinates of this view from before this operation
19395     *                       to after it completes. View implementations may use this to adjust
19396     *                       expected input coordinate tracking.
19397     * @return true if the event was dispatched, false if it could not be dispatched.
19398     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19399     */
19400    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
19401            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
19402        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19403            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
19404                int startX = 0;
19405                int startY = 0;
19406                if (offsetInWindow != null) {
19407                    getLocationInWindow(offsetInWindow);
19408                    startX = offsetInWindow[0];
19409                    startY = offsetInWindow[1];
19410                }
19411
19412                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
19413                        dxUnconsumed, dyUnconsumed);
19414
19415                if (offsetInWindow != null) {
19416                    getLocationInWindow(offsetInWindow);
19417                    offsetInWindow[0] -= startX;
19418                    offsetInWindow[1] -= startY;
19419                }
19420                return true;
19421            } else if (offsetInWindow != null) {
19422                // No motion, no dispatch. Keep offsetInWindow up to date.
19423                offsetInWindow[0] = 0;
19424                offsetInWindow[1] = 0;
19425            }
19426        }
19427        return false;
19428    }
19429
19430    /**
19431     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
19432     *
19433     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
19434     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
19435     * scrolling operation to consume some or all of the scroll operation before the child view
19436     * consumes it.</p>
19437     *
19438     * @param dx Horizontal scroll distance in pixels
19439     * @param dy Vertical scroll distance in pixels
19440     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
19441     *                 and consumed[1] the consumed dy.
19442     * @param offsetInWindow Optional. If not null, on return this will contain the offset
19443     *                       in local view coordinates of this view from before this operation
19444     *                       to after it completes. View implementations may use this to adjust
19445     *                       expected input coordinate tracking.
19446     * @return true if the parent consumed some or all of the scroll delta
19447     * @see #dispatchNestedScroll(int, int, int, int, int[])
19448     */
19449    public boolean dispatchNestedPreScroll(int dx, int dy,
19450            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
19451        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19452            if (dx != 0 || dy != 0) {
19453                int startX = 0;
19454                int startY = 0;
19455                if (offsetInWindow != null) {
19456                    getLocationInWindow(offsetInWindow);
19457                    startX = offsetInWindow[0];
19458                    startY = offsetInWindow[1];
19459                }
19460
19461                if (consumed == null) {
19462                    if (mTempNestedScrollConsumed == null) {
19463                        mTempNestedScrollConsumed = new int[2];
19464                    }
19465                    consumed = mTempNestedScrollConsumed;
19466                }
19467                consumed[0] = 0;
19468                consumed[1] = 0;
19469                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
19470
19471                if (offsetInWindow != null) {
19472                    getLocationInWindow(offsetInWindow);
19473                    offsetInWindow[0] -= startX;
19474                    offsetInWindow[1] -= startY;
19475                }
19476                return consumed[0] != 0 || consumed[1] != 0;
19477            } else if (offsetInWindow != null) {
19478                offsetInWindow[0] = 0;
19479                offsetInWindow[1] = 0;
19480            }
19481        }
19482        return false;
19483    }
19484
19485    /**
19486     * Dispatch a fling to a nested scrolling parent.
19487     *
19488     * <p>This method should be used to indicate that a nested scrolling child has detected
19489     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
19490     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
19491     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
19492     * along a scrollable axis.</p>
19493     *
19494     * <p>If a nested scrolling child view would normally fling but it is at the edge of
19495     * its own content, it can use this method to delegate the fling to its nested scrolling
19496     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
19497     *
19498     * @param velocityX Horizontal fling velocity in pixels per second
19499     * @param velocityY Vertical fling velocity in pixels per second
19500     * @param consumed true if the child consumed the fling, false otherwise
19501     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
19502     */
19503    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
19504        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19505            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
19506        }
19507        return false;
19508    }
19509
19510    /**
19511     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
19512     *
19513     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
19514     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
19515     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
19516     * before the child view consumes it. If this method returns <code>true</code>, a nested
19517     * parent view consumed the fling and this view should not scroll as a result.</p>
19518     *
19519     * <p>For a better user experience, only one view in a nested scrolling chain should consume
19520     * the fling at a time. If a parent view consumed the fling this method will return false.
19521     * Custom view implementations should account for this in two ways:</p>
19522     *
19523     * <ul>
19524     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
19525     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
19526     *     position regardless.</li>
19527     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
19528     *     even to settle back to a valid idle position.</li>
19529     * </ul>
19530     *
19531     * <p>Views should also not offer fling velocities to nested parent views along an axis
19532     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
19533     * should not offer a horizontal fling velocity to its parents since scrolling along that
19534     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
19535     *
19536     * @param velocityX Horizontal fling velocity in pixels per second
19537     * @param velocityY Vertical fling velocity in pixels per second
19538     * @return true if a nested scrolling parent consumed the fling
19539     */
19540    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
19541        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
19542            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
19543        }
19544        return false;
19545    }
19546
19547    /**
19548     * Gets a scale factor that determines the distance the view should scroll
19549     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
19550     * @return The vertical scroll scale factor.
19551     * @hide
19552     */
19553    protected float getVerticalScrollFactor() {
19554        if (mVerticalScrollFactor == 0) {
19555            TypedValue outValue = new TypedValue();
19556            if (!mContext.getTheme().resolveAttribute(
19557                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
19558                throw new IllegalStateException(
19559                        "Expected theme to define listPreferredItemHeight.");
19560            }
19561            mVerticalScrollFactor = outValue.getDimension(
19562                    mContext.getResources().getDisplayMetrics());
19563        }
19564        return mVerticalScrollFactor;
19565    }
19566
19567    /**
19568     * Gets a scale factor that determines the distance the view should scroll
19569     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
19570     * @return The horizontal scroll scale factor.
19571     * @hide
19572     */
19573    protected float getHorizontalScrollFactor() {
19574        // TODO: Should use something else.
19575        return getVerticalScrollFactor();
19576    }
19577
19578    /**
19579     * Return the value specifying the text direction or policy that was set with
19580     * {@link #setTextDirection(int)}.
19581     *
19582     * @return the defined text direction. It can be one of:
19583     *
19584     * {@link #TEXT_DIRECTION_INHERIT},
19585     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19586     * {@link #TEXT_DIRECTION_ANY_RTL},
19587     * {@link #TEXT_DIRECTION_LTR},
19588     * {@link #TEXT_DIRECTION_RTL},
19589     * {@link #TEXT_DIRECTION_LOCALE}
19590     *
19591     * @attr ref android.R.styleable#View_textDirection
19592     *
19593     * @hide
19594     */
19595    @ViewDebug.ExportedProperty(category = "text", mapping = {
19596            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19597            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19598            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19599            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19600            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19601            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19602    })
19603    public int getRawTextDirection() {
19604        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
19605    }
19606
19607    /**
19608     * Set the text direction.
19609     *
19610     * @param textDirection the direction to set. Should be one of:
19611     *
19612     * {@link #TEXT_DIRECTION_INHERIT},
19613     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19614     * {@link #TEXT_DIRECTION_ANY_RTL},
19615     * {@link #TEXT_DIRECTION_LTR},
19616     * {@link #TEXT_DIRECTION_RTL},
19617     * {@link #TEXT_DIRECTION_LOCALE}
19618     *
19619     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
19620     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
19621     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
19622     *
19623     * @attr ref android.R.styleable#View_textDirection
19624     */
19625    public void setTextDirection(int textDirection) {
19626        if (getRawTextDirection() != textDirection) {
19627            // Reset the current text direction and the resolved one
19628            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
19629            resetResolvedTextDirection();
19630            // Set the new text direction
19631            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
19632            // Do resolution
19633            resolveTextDirection();
19634            // Notify change
19635            onRtlPropertiesChanged(getLayoutDirection());
19636            // Refresh
19637            requestLayout();
19638            invalidate(true);
19639        }
19640    }
19641
19642    /**
19643     * Return the resolved text direction.
19644     *
19645     * @return the resolved text direction. Returns one of:
19646     *
19647     * {@link #TEXT_DIRECTION_FIRST_STRONG}
19648     * {@link #TEXT_DIRECTION_ANY_RTL},
19649     * {@link #TEXT_DIRECTION_LTR},
19650     * {@link #TEXT_DIRECTION_RTL},
19651     * {@link #TEXT_DIRECTION_LOCALE}
19652     *
19653     * @attr ref android.R.styleable#View_textDirection
19654     */
19655    @ViewDebug.ExportedProperty(category = "text", mapping = {
19656            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
19657            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
19658            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
19659            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
19660            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
19661            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
19662    })
19663    public int getTextDirection() {
19664        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
19665    }
19666
19667    /**
19668     * Resolve the text direction.
19669     *
19670     * @return true if resolution has been done, false otherwise.
19671     *
19672     * @hide
19673     */
19674    public boolean resolveTextDirection() {
19675        // Reset any previous text direction resolution
19676        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19677
19678        if (hasRtlSupport()) {
19679            // Set resolved text direction flag depending on text direction flag
19680            final int textDirection = getRawTextDirection();
19681            switch(textDirection) {
19682                case TEXT_DIRECTION_INHERIT:
19683                    if (!canResolveTextDirection()) {
19684                        // We cannot do the resolution if there is no parent, so use the default one
19685                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19686                        // Resolution will need to happen again later
19687                        return false;
19688                    }
19689
19690                    // Parent has not yet resolved, so we still return the default
19691                    try {
19692                        if (!mParent.isTextDirectionResolved()) {
19693                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19694                            // Resolution will need to happen again later
19695                            return false;
19696                        }
19697                    } catch (AbstractMethodError e) {
19698                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19699                                " does not fully implement ViewParent", e);
19700                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
19701                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19702                        return true;
19703                    }
19704
19705                    // Set current resolved direction to the same value as the parent's one
19706                    int parentResolvedDirection;
19707                    try {
19708                        parentResolvedDirection = mParent.getTextDirection();
19709                    } catch (AbstractMethodError e) {
19710                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19711                                " does not fully implement ViewParent", e);
19712                        parentResolvedDirection = TEXT_DIRECTION_LTR;
19713                    }
19714                    switch (parentResolvedDirection) {
19715                        case TEXT_DIRECTION_FIRST_STRONG:
19716                        case TEXT_DIRECTION_ANY_RTL:
19717                        case TEXT_DIRECTION_LTR:
19718                        case TEXT_DIRECTION_RTL:
19719                        case TEXT_DIRECTION_LOCALE:
19720                            mPrivateFlags2 |=
19721                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19722                            break;
19723                        default:
19724                            // Default resolved direction is "first strong" heuristic
19725                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19726                    }
19727                    break;
19728                case TEXT_DIRECTION_FIRST_STRONG:
19729                case TEXT_DIRECTION_ANY_RTL:
19730                case TEXT_DIRECTION_LTR:
19731                case TEXT_DIRECTION_RTL:
19732                case TEXT_DIRECTION_LOCALE:
19733                    // Resolved direction is the same as text direction
19734                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
19735                    break;
19736                default:
19737                    // Default resolved direction is "first strong" heuristic
19738                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19739            }
19740        } else {
19741            // Default resolved direction is "first strong" heuristic
19742            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19743        }
19744
19745        // Set to resolved
19746        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
19747        return true;
19748    }
19749
19750    /**
19751     * Check if text direction resolution can be done.
19752     *
19753     * @return true if text direction resolution can be done otherwise return false.
19754     */
19755    public boolean canResolveTextDirection() {
19756        switch (getRawTextDirection()) {
19757            case TEXT_DIRECTION_INHERIT:
19758                if (mParent != null) {
19759                    try {
19760                        return mParent.canResolveTextDirection();
19761                    } catch (AbstractMethodError e) {
19762                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19763                                " does not fully implement ViewParent", e);
19764                    }
19765                }
19766                return false;
19767
19768            default:
19769                return true;
19770        }
19771    }
19772
19773    /**
19774     * Reset resolved text direction. Text direction will be resolved during a call to
19775     * {@link #onMeasure(int, int)}.
19776     *
19777     * @hide
19778     */
19779    public void resetResolvedTextDirection() {
19780        // Reset any previous text direction resolution
19781        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
19782        // Set to default value
19783        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
19784    }
19785
19786    /**
19787     * @return true if text direction is inherited.
19788     *
19789     * @hide
19790     */
19791    public boolean isTextDirectionInherited() {
19792        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
19793    }
19794
19795    /**
19796     * @return true if text direction is resolved.
19797     */
19798    public boolean isTextDirectionResolved() {
19799        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
19800    }
19801
19802    /**
19803     * Return the value specifying the text alignment or policy that was set with
19804     * {@link #setTextAlignment(int)}.
19805     *
19806     * @return the defined text alignment. It can be one of:
19807     *
19808     * {@link #TEXT_ALIGNMENT_INHERIT},
19809     * {@link #TEXT_ALIGNMENT_GRAVITY},
19810     * {@link #TEXT_ALIGNMENT_CENTER},
19811     * {@link #TEXT_ALIGNMENT_TEXT_START},
19812     * {@link #TEXT_ALIGNMENT_TEXT_END},
19813     * {@link #TEXT_ALIGNMENT_VIEW_START},
19814     * {@link #TEXT_ALIGNMENT_VIEW_END}
19815     *
19816     * @attr ref android.R.styleable#View_textAlignment
19817     *
19818     * @hide
19819     */
19820    @ViewDebug.ExportedProperty(category = "text", mapping = {
19821            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19822            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19823            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19824            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19825            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19826            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19827            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19828    })
19829    @TextAlignment
19830    public int getRawTextAlignment() {
19831        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
19832    }
19833
19834    /**
19835     * Set the text alignment.
19836     *
19837     * @param textAlignment The text alignment to set. Should be one of
19838     *
19839     * {@link #TEXT_ALIGNMENT_INHERIT},
19840     * {@link #TEXT_ALIGNMENT_GRAVITY},
19841     * {@link #TEXT_ALIGNMENT_CENTER},
19842     * {@link #TEXT_ALIGNMENT_TEXT_START},
19843     * {@link #TEXT_ALIGNMENT_TEXT_END},
19844     * {@link #TEXT_ALIGNMENT_VIEW_START},
19845     * {@link #TEXT_ALIGNMENT_VIEW_END}
19846     *
19847     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
19848     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
19849     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
19850     *
19851     * @attr ref android.R.styleable#View_textAlignment
19852     */
19853    public void setTextAlignment(@TextAlignment int textAlignment) {
19854        if (textAlignment != getRawTextAlignment()) {
19855            // Reset the current and resolved text alignment
19856            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
19857            resetResolvedTextAlignment();
19858            // Set the new text alignment
19859            mPrivateFlags2 |=
19860                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
19861            // Do resolution
19862            resolveTextAlignment();
19863            // Notify change
19864            onRtlPropertiesChanged(getLayoutDirection());
19865            // Refresh
19866            requestLayout();
19867            invalidate(true);
19868        }
19869    }
19870
19871    /**
19872     * Return the resolved text alignment.
19873     *
19874     * @return the resolved text alignment. Returns one of:
19875     *
19876     * {@link #TEXT_ALIGNMENT_GRAVITY},
19877     * {@link #TEXT_ALIGNMENT_CENTER},
19878     * {@link #TEXT_ALIGNMENT_TEXT_START},
19879     * {@link #TEXT_ALIGNMENT_TEXT_END},
19880     * {@link #TEXT_ALIGNMENT_VIEW_START},
19881     * {@link #TEXT_ALIGNMENT_VIEW_END}
19882     *
19883     * @attr ref android.R.styleable#View_textAlignment
19884     */
19885    @ViewDebug.ExportedProperty(category = "text", mapping = {
19886            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
19887            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
19888            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
19889            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
19890            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
19891            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
19892            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
19893    })
19894    @TextAlignment
19895    public int getTextAlignment() {
19896        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
19897                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
19898    }
19899
19900    /**
19901     * Resolve the text alignment.
19902     *
19903     * @return true if resolution has been done, false otherwise.
19904     *
19905     * @hide
19906     */
19907    public boolean resolveTextAlignment() {
19908        // Reset any previous text alignment resolution
19909        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
19910
19911        if (hasRtlSupport()) {
19912            // Set resolved text alignment flag depending on text alignment flag
19913            final int textAlignment = getRawTextAlignment();
19914            switch (textAlignment) {
19915                case TEXT_ALIGNMENT_INHERIT:
19916                    // Check if we can resolve the text alignment
19917                    if (!canResolveTextAlignment()) {
19918                        // We cannot do the resolution if there is no parent so use the default
19919                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19920                        // Resolution will need to happen again later
19921                        return false;
19922                    }
19923
19924                    // Parent has not yet resolved, so we still return the default
19925                    try {
19926                        if (!mParent.isTextAlignmentResolved()) {
19927                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19928                            // Resolution will need to happen again later
19929                            return false;
19930                        }
19931                    } catch (AbstractMethodError e) {
19932                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19933                                " does not fully implement ViewParent", e);
19934                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
19935                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19936                        return true;
19937                    }
19938
19939                    int parentResolvedTextAlignment;
19940                    try {
19941                        parentResolvedTextAlignment = mParent.getTextAlignment();
19942                    } catch (AbstractMethodError e) {
19943                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
19944                                " does not fully implement ViewParent", e);
19945                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
19946                    }
19947                    switch (parentResolvedTextAlignment) {
19948                        case TEXT_ALIGNMENT_GRAVITY:
19949                        case TEXT_ALIGNMENT_TEXT_START:
19950                        case TEXT_ALIGNMENT_TEXT_END:
19951                        case TEXT_ALIGNMENT_CENTER:
19952                        case TEXT_ALIGNMENT_VIEW_START:
19953                        case TEXT_ALIGNMENT_VIEW_END:
19954                            // Resolved text alignment is the same as the parent resolved
19955                            // text alignment
19956                            mPrivateFlags2 |=
19957                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19958                            break;
19959                        default:
19960                            // Use default resolved text alignment
19961                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19962                    }
19963                    break;
19964                case TEXT_ALIGNMENT_GRAVITY:
19965                case TEXT_ALIGNMENT_TEXT_START:
19966                case TEXT_ALIGNMENT_TEXT_END:
19967                case TEXT_ALIGNMENT_CENTER:
19968                case TEXT_ALIGNMENT_VIEW_START:
19969                case TEXT_ALIGNMENT_VIEW_END:
19970                    // Resolved text alignment is the same as text alignment
19971                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
19972                    break;
19973                default:
19974                    // Use default resolved text alignment
19975                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19976            }
19977        } else {
19978            // Use default resolved text alignment
19979            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
19980        }
19981
19982        // Set the resolved
19983        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
19984        return true;
19985    }
19986
19987    /**
19988     * Check if text alignment resolution can be done.
19989     *
19990     * @return true if text alignment resolution can be done otherwise return false.
19991     */
19992    public boolean canResolveTextAlignment() {
19993        switch (getRawTextAlignment()) {
19994            case TEXT_DIRECTION_INHERIT:
19995                if (mParent != null) {
19996                    try {
19997                        return mParent.canResolveTextAlignment();
19998                    } catch (AbstractMethodError e) {
19999                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20000                                " does not fully implement ViewParent", e);
20001                    }
20002                }
20003                return false;
20004
20005            default:
20006                return true;
20007        }
20008    }
20009
20010    /**
20011     * Reset resolved text alignment. Text alignment will be resolved during a call to
20012     * {@link #onMeasure(int, int)}.
20013     *
20014     * @hide
20015     */
20016    public void resetResolvedTextAlignment() {
20017        // Reset any previous text alignment resolution
20018        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20019        // Set to default
20020        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20021    }
20022
20023    /**
20024     * @return true if text alignment is inherited.
20025     *
20026     * @hide
20027     */
20028    public boolean isTextAlignmentInherited() {
20029        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20030    }
20031
20032    /**
20033     * @return true if text alignment is resolved.
20034     */
20035    public boolean isTextAlignmentResolved() {
20036        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20037    }
20038
20039    /**
20040     * Generate a value suitable for use in {@link #setId(int)}.
20041     * This value will not collide with ID values generated at build time by aapt for R.id.
20042     *
20043     * @return a generated ID value
20044     */
20045    public static int generateViewId() {
20046        for (;;) {
20047            final int result = sNextGeneratedId.get();
20048            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20049            int newValue = result + 1;
20050            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20051            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20052                return result;
20053            }
20054        }
20055    }
20056
20057    /**
20058     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20059     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20060     *                           a normal View or a ViewGroup with
20061     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20062     * @hide
20063     */
20064    public void captureTransitioningViews(List<View> transitioningViews) {
20065        if (getVisibility() == View.VISIBLE) {
20066            transitioningViews.add(this);
20067        }
20068    }
20069
20070    /**
20071     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20072     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20073     * @hide
20074     */
20075    public void findNamedViews(Map<String, View> namedElements) {
20076        if (getVisibility() == VISIBLE || mGhostView != null) {
20077            String transitionName = getTransitionName();
20078            if (transitionName != null) {
20079                namedElements.put(transitionName, this);
20080            }
20081        }
20082    }
20083
20084    //
20085    // Properties
20086    //
20087    /**
20088     * A Property wrapper around the <code>alpha</code> functionality handled by the
20089     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20090     */
20091    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20092        @Override
20093        public void setValue(View object, float value) {
20094            object.setAlpha(value);
20095        }
20096
20097        @Override
20098        public Float get(View object) {
20099            return object.getAlpha();
20100        }
20101    };
20102
20103    /**
20104     * A Property wrapper around the <code>translationX</code> functionality handled by the
20105     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20106     */
20107    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20108        @Override
20109        public void setValue(View object, float value) {
20110            object.setTranslationX(value);
20111        }
20112
20113                @Override
20114        public Float get(View object) {
20115            return object.getTranslationX();
20116        }
20117    };
20118
20119    /**
20120     * A Property wrapper around the <code>translationY</code> functionality handled by the
20121     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20122     */
20123    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20124        @Override
20125        public void setValue(View object, float value) {
20126            object.setTranslationY(value);
20127        }
20128
20129        @Override
20130        public Float get(View object) {
20131            return object.getTranslationY();
20132        }
20133    };
20134
20135    /**
20136     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20137     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20138     */
20139    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20140        @Override
20141        public void setValue(View object, float value) {
20142            object.setTranslationZ(value);
20143        }
20144
20145        @Override
20146        public Float get(View object) {
20147            return object.getTranslationZ();
20148        }
20149    };
20150
20151    /**
20152     * A Property wrapper around the <code>x</code> functionality handled by the
20153     * {@link View#setX(float)} and {@link View#getX()} methods.
20154     */
20155    public static final Property<View, Float> X = new FloatProperty<View>("x") {
20156        @Override
20157        public void setValue(View object, float value) {
20158            object.setX(value);
20159        }
20160
20161        @Override
20162        public Float get(View object) {
20163            return object.getX();
20164        }
20165    };
20166
20167    /**
20168     * A Property wrapper around the <code>y</code> functionality handled by the
20169     * {@link View#setY(float)} and {@link View#getY()} methods.
20170     */
20171    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20172        @Override
20173        public void setValue(View object, float value) {
20174            object.setY(value);
20175        }
20176
20177        @Override
20178        public Float get(View object) {
20179            return object.getY();
20180        }
20181    };
20182
20183    /**
20184     * A Property wrapper around the <code>z</code> functionality handled by the
20185     * {@link View#setZ(float)} and {@link View#getZ()} methods.
20186     */
20187    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20188        @Override
20189        public void setValue(View object, float value) {
20190            object.setZ(value);
20191        }
20192
20193        @Override
20194        public Float get(View object) {
20195            return object.getZ();
20196        }
20197    };
20198
20199    /**
20200     * A Property wrapper around the <code>rotation</code> functionality handled by the
20201     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20202     */
20203    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20204        @Override
20205        public void setValue(View object, float value) {
20206            object.setRotation(value);
20207        }
20208
20209        @Override
20210        public Float get(View object) {
20211            return object.getRotation();
20212        }
20213    };
20214
20215    /**
20216     * A Property wrapper around the <code>rotationX</code> functionality handled by the
20217     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20218     */
20219    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20220        @Override
20221        public void setValue(View object, float value) {
20222            object.setRotationX(value);
20223        }
20224
20225        @Override
20226        public Float get(View object) {
20227            return object.getRotationX();
20228        }
20229    };
20230
20231    /**
20232     * A Property wrapper around the <code>rotationY</code> functionality handled by the
20233     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20234     */
20235    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20236        @Override
20237        public void setValue(View object, float value) {
20238            object.setRotationY(value);
20239        }
20240
20241        @Override
20242        public Float get(View object) {
20243            return object.getRotationY();
20244        }
20245    };
20246
20247    /**
20248     * A Property wrapper around the <code>scaleX</code> functionality handled by the
20249     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20250     */
20251    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20252        @Override
20253        public void setValue(View object, float value) {
20254            object.setScaleX(value);
20255        }
20256
20257        @Override
20258        public Float get(View object) {
20259            return object.getScaleX();
20260        }
20261    };
20262
20263    /**
20264     * A Property wrapper around the <code>scaleY</code> functionality handled by the
20265     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20266     */
20267    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20268        @Override
20269        public void setValue(View object, float value) {
20270            object.setScaleY(value);
20271        }
20272
20273        @Override
20274        public Float get(View object) {
20275            return object.getScaleY();
20276        }
20277    };
20278
20279    /**
20280     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20281     * Each MeasureSpec represents a requirement for either the width or the height.
20282     * A MeasureSpec is comprised of a size and a mode. There are three possible
20283     * modes:
20284     * <dl>
20285     * <dt>UNSPECIFIED</dt>
20286     * <dd>
20287     * The parent has not imposed any constraint on the child. It can be whatever size
20288     * it wants.
20289     * </dd>
20290     *
20291     * <dt>EXACTLY</dt>
20292     * <dd>
20293     * The parent has determined an exact size for the child. The child is going to be
20294     * given those bounds regardless of how big it wants to be.
20295     * </dd>
20296     *
20297     * <dt>AT_MOST</dt>
20298     * <dd>
20299     * The child can be as large as it wants up to the specified size.
20300     * </dd>
20301     * </dl>
20302     *
20303     * MeasureSpecs are implemented as ints to reduce object allocation. This class
20304     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20305     */
20306    public static class MeasureSpec {
20307        private static final int MODE_SHIFT = 30;
20308        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
20309
20310        /**
20311         * Measure specification mode: The parent has not imposed any constraint
20312         * on the child. It can be whatever size it wants.
20313         */
20314        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20315
20316        /**
20317         * Measure specification mode: The parent has determined an exact size
20318         * for the child. The child is going to be given those bounds regardless
20319         * of how big it wants to be.
20320         */
20321        public static final int EXACTLY     = 1 << MODE_SHIFT;
20322
20323        /**
20324         * Measure specification mode: The child can be as large as it wants up
20325         * to the specified size.
20326         */
20327        public static final int AT_MOST     = 2 << MODE_SHIFT;
20328
20329        /**
20330         * Creates a measure specification based on the supplied size and mode.
20331         *
20332         * The mode must always be one of the following:
20333         * <ul>
20334         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
20335         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
20336         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
20337         * </ul>
20338         *
20339         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
20340         * implementation was such that the order of arguments did not matter
20341         * and overflow in either value could impact the resulting MeasureSpec.
20342         * {@link android.widget.RelativeLayout} was affected by this bug.
20343         * Apps targeting API levels greater than 17 will get the fixed, more strict
20344         * behavior.</p>
20345         *
20346         * @param size the size of the measure specification
20347         * @param mode the mode of the measure specification
20348         * @return the measure specification based on size and mode
20349         */
20350        public static int makeMeasureSpec(int size, int mode) {
20351            if (sUseBrokenMakeMeasureSpec) {
20352                return size + mode;
20353            } else {
20354                return (size & ~MODE_MASK) | (mode & MODE_MASK);
20355            }
20356        }
20357
20358        /**
20359         * Extracts the mode from the supplied measure specification.
20360         *
20361         * @param measureSpec the measure specification to extract the mode from
20362         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
20363         *         {@link android.view.View.MeasureSpec#AT_MOST} or
20364         *         {@link android.view.View.MeasureSpec#EXACTLY}
20365         */
20366        public static int getMode(int measureSpec) {
20367            return (measureSpec & MODE_MASK);
20368        }
20369
20370        /**
20371         * Extracts the size from the supplied measure specification.
20372         *
20373         * @param measureSpec the measure specification to extract the size from
20374         * @return the size in pixels defined in the supplied measure specification
20375         */
20376        public static int getSize(int measureSpec) {
20377            return (measureSpec & ~MODE_MASK);
20378        }
20379
20380        static int adjust(int measureSpec, int delta) {
20381            final int mode = getMode(measureSpec);
20382            if (mode == UNSPECIFIED) {
20383                // No need to adjust size for UNSPECIFIED mode.
20384                return makeMeasureSpec(0, UNSPECIFIED);
20385            }
20386            int size = getSize(measureSpec) + delta;
20387            if (size < 0) {
20388                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
20389                        ") spec: " + toString(measureSpec) + " delta: " + delta);
20390                size = 0;
20391            }
20392            return makeMeasureSpec(size, mode);
20393        }
20394
20395        /**
20396         * Returns a String representation of the specified measure
20397         * specification.
20398         *
20399         * @param measureSpec the measure specification to convert to a String
20400         * @return a String with the following format: "MeasureSpec: MODE SIZE"
20401         */
20402        public static String toString(int measureSpec) {
20403            int mode = getMode(measureSpec);
20404            int size = getSize(measureSpec);
20405
20406            StringBuilder sb = new StringBuilder("MeasureSpec: ");
20407
20408            if (mode == UNSPECIFIED)
20409                sb.append("UNSPECIFIED ");
20410            else if (mode == EXACTLY)
20411                sb.append("EXACTLY ");
20412            else if (mode == AT_MOST)
20413                sb.append("AT_MOST ");
20414            else
20415                sb.append(mode).append(" ");
20416
20417            sb.append(size);
20418            return sb.toString();
20419        }
20420    }
20421
20422    private final class CheckForLongPress implements Runnable {
20423        private int mOriginalWindowAttachCount;
20424
20425        @Override
20426        public void run() {
20427            if (isPressed() && (mParent != null)
20428                    && mOriginalWindowAttachCount == mWindowAttachCount) {
20429                if (performLongClick()) {
20430                    mHasPerformedLongPress = true;
20431                }
20432            }
20433        }
20434
20435        public void rememberWindowAttachCount() {
20436            mOriginalWindowAttachCount = mWindowAttachCount;
20437        }
20438    }
20439
20440    private final class CheckForTap implements Runnable {
20441        public float x;
20442        public float y;
20443
20444        @Override
20445        public void run() {
20446            mPrivateFlags &= ~PFLAG_PREPRESSED;
20447            setPressed(true, x, y);
20448            checkForLongClick(ViewConfiguration.getTapTimeout());
20449        }
20450    }
20451
20452    private final class PerformClick implements Runnable {
20453        @Override
20454        public void run() {
20455            performClick();
20456        }
20457    }
20458
20459    /** @hide */
20460    public void hackTurnOffWindowResizeAnim(boolean off) {
20461        mAttachInfo.mTurnOffWindowResizeAnim = off;
20462    }
20463
20464    /**
20465     * This method returns a ViewPropertyAnimator object, which can be used to animate
20466     * specific properties on this View.
20467     *
20468     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
20469     */
20470    public ViewPropertyAnimator animate() {
20471        if (mAnimator == null) {
20472            mAnimator = new ViewPropertyAnimator(this);
20473        }
20474        return mAnimator;
20475    }
20476
20477    /**
20478     * Sets the name of the View to be used to identify Views in Transitions.
20479     * Names should be unique in the View hierarchy.
20480     *
20481     * @param transitionName The name of the View to uniquely identify it for Transitions.
20482     */
20483    public final void setTransitionName(String transitionName) {
20484        mTransitionName = transitionName;
20485    }
20486
20487    /**
20488     * Returns the name of the View to be used to identify Views in Transitions.
20489     * Names should be unique in the View hierarchy.
20490     *
20491     * <p>This returns null if the View has not been given a name.</p>
20492     *
20493     * @return The name used of the View to be used to identify Views in Transitions or null
20494     * if no name has been given.
20495     */
20496    @ViewDebug.ExportedProperty
20497    public String getTransitionName() {
20498        return mTransitionName;
20499    }
20500
20501    /**
20502     * Interface definition for a callback to be invoked when a hardware key event is
20503     * dispatched to this view. The callback will be invoked before the key event is
20504     * given to the view. This is only useful for hardware keyboards; a software input
20505     * method has no obligation to trigger this listener.
20506     */
20507    public interface OnKeyListener {
20508        /**
20509         * Called when a hardware key is dispatched to a view. This allows listeners to
20510         * get a chance to respond before the target view.
20511         * <p>Key presses in software keyboards will generally NOT trigger this method,
20512         * although some may elect to do so in some situations. Do not assume a
20513         * software input method has to be key-based; even if it is, it may use key presses
20514         * in a different way than you expect, so there is no way to reliably catch soft
20515         * input key presses.
20516         *
20517         * @param v The view the key has been dispatched to.
20518         * @param keyCode The code for the physical key that was pressed
20519         * @param event The KeyEvent object containing full information about
20520         *        the event.
20521         * @return True if the listener has consumed the event, false otherwise.
20522         */
20523        boolean onKey(View v, int keyCode, KeyEvent event);
20524    }
20525
20526    /**
20527     * Interface definition for a callback to be invoked when a touch event is
20528     * dispatched to this view. The callback will be invoked before the touch
20529     * event is given to the view.
20530     */
20531    public interface OnTouchListener {
20532        /**
20533         * Called when a touch event is dispatched to a view. This allows listeners to
20534         * get a chance to respond before the target view.
20535         *
20536         * @param v The view the touch event has been dispatched to.
20537         * @param event The MotionEvent object containing full information about
20538         *        the event.
20539         * @return True if the listener has consumed the event, false otherwise.
20540         */
20541        boolean onTouch(View v, MotionEvent event);
20542    }
20543
20544    /**
20545     * Interface definition for a callback to be invoked when a hover event is
20546     * dispatched to this view. The callback will be invoked before the hover
20547     * event is given to the view.
20548     */
20549    public interface OnHoverListener {
20550        /**
20551         * Called when a hover event is dispatched to a view. This allows listeners to
20552         * get a chance to respond before the target view.
20553         *
20554         * @param v The view the hover event has been dispatched to.
20555         * @param event The MotionEvent object containing full information about
20556         *        the event.
20557         * @return True if the listener has consumed the event, false otherwise.
20558         */
20559        boolean onHover(View v, MotionEvent event);
20560    }
20561
20562    /**
20563     * Interface definition for a callback to be invoked when a generic motion event is
20564     * dispatched to this view. The callback will be invoked before the generic motion
20565     * event is given to the view.
20566     */
20567    public interface OnGenericMotionListener {
20568        /**
20569         * Called when a generic motion event is dispatched to a view. This allows listeners to
20570         * get a chance to respond before the target view.
20571         *
20572         * @param v The view the generic motion event has been dispatched to.
20573         * @param event The MotionEvent object containing full information about
20574         *        the event.
20575         * @return True if the listener has consumed the event, false otherwise.
20576         */
20577        boolean onGenericMotion(View v, MotionEvent event);
20578    }
20579
20580    /**
20581     * Interface definition for a callback to be invoked when a view has been clicked and held.
20582     */
20583    public interface OnLongClickListener {
20584        /**
20585         * Called when a view has been clicked and held.
20586         *
20587         * @param v The view that was clicked and held.
20588         *
20589         * @return true if the callback consumed the long click, false otherwise.
20590         */
20591        boolean onLongClick(View v);
20592    }
20593
20594    /**
20595     * Interface definition for a callback to be invoked when a drag is being dispatched
20596     * to this view.  The callback will be invoked before the hosting view's own
20597     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
20598     * onDrag(event) behavior, it should return 'false' from this callback.
20599     *
20600     * <div class="special reference">
20601     * <h3>Developer Guides</h3>
20602     * <p>For a guide to implementing drag and drop features, read the
20603     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
20604     * </div>
20605     */
20606    public interface OnDragListener {
20607        /**
20608         * Called when a drag event is dispatched to a view. This allows listeners
20609         * to get a chance to override base View behavior.
20610         *
20611         * @param v The View that received the drag event.
20612         * @param event The {@link android.view.DragEvent} object for the drag event.
20613         * @return {@code true} if the drag event was handled successfully, or {@code false}
20614         * if the drag event was not handled. Note that {@code false} will trigger the View
20615         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
20616         */
20617        boolean onDrag(View v, DragEvent event);
20618    }
20619
20620    /**
20621     * Interface definition for a callback to be invoked when the focus state of
20622     * a view changed.
20623     */
20624    public interface OnFocusChangeListener {
20625        /**
20626         * Called when the focus state of a view has changed.
20627         *
20628         * @param v The view whose state has changed.
20629         * @param hasFocus The new focus state of v.
20630         */
20631        void onFocusChange(View v, boolean hasFocus);
20632    }
20633
20634    /**
20635     * Interface definition for a callback to be invoked when a view is clicked.
20636     */
20637    public interface OnClickListener {
20638        /**
20639         * Called when a view has been clicked.
20640         *
20641         * @param v The view that was clicked.
20642         */
20643        void onClick(View v);
20644    }
20645
20646    /**
20647     * Interface definition for a callback to be invoked when the context menu
20648     * for this view is being built.
20649     */
20650    public interface OnCreateContextMenuListener {
20651        /**
20652         * Called when the context menu for this view is being built. It is not
20653         * safe to hold onto the menu after this method returns.
20654         *
20655         * @param menu The context menu that is being built
20656         * @param v The view for which the context menu is being built
20657         * @param menuInfo Extra information about the item for which the
20658         *            context menu should be shown. This information will vary
20659         *            depending on the class of v.
20660         */
20661        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
20662    }
20663
20664    /**
20665     * Interface definition for a callback to be invoked when the status bar changes
20666     * visibility.  This reports <strong>global</strong> changes to the system UI
20667     * state, not what the application is requesting.
20668     *
20669     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
20670     */
20671    public interface OnSystemUiVisibilityChangeListener {
20672        /**
20673         * Called when the status bar changes visibility because of a call to
20674         * {@link View#setSystemUiVisibility(int)}.
20675         *
20676         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
20677         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
20678         * This tells you the <strong>global</strong> state of these UI visibility
20679         * flags, not what your app is currently applying.
20680         */
20681        public void onSystemUiVisibilityChange(int visibility);
20682    }
20683
20684    /**
20685     * Interface definition for a callback to be invoked when this view is attached
20686     * or detached from its window.
20687     */
20688    public interface OnAttachStateChangeListener {
20689        /**
20690         * Called when the view is attached to a window.
20691         * @param v The view that was attached
20692         */
20693        public void onViewAttachedToWindow(View v);
20694        /**
20695         * Called when the view is detached from a window.
20696         * @param v The view that was detached
20697         */
20698        public void onViewDetachedFromWindow(View v);
20699    }
20700
20701    /**
20702     * Listener for applying window insets on a view in a custom way.
20703     *
20704     * <p>Apps may choose to implement this interface if they want to apply custom policy
20705     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
20706     * is set, its
20707     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
20708     * method will be called instead of the View's own
20709     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
20710     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
20711     * the View's normal behavior as part of its own.</p>
20712     */
20713    public interface OnApplyWindowInsetsListener {
20714        /**
20715         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
20716         * on a View, this listener method will be called instead of the view's own
20717         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
20718         *
20719         * @param v The view applying window insets
20720         * @param insets The insets to apply
20721         * @return The insets supplied, minus any insets that were consumed
20722         */
20723        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
20724    }
20725
20726    private final class UnsetPressedState implements Runnable {
20727        @Override
20728        public void run() {
20729            setPressed(false);
20730        }
20731    }
20732
20733    /**
20734     * Base class for derived classes that want to save and restore their own
20735     * state in {@link android.view.View#onSaveInstanceState()}.
20736     */
20737    public static class BaseSavedState extends AbsSavedState {
20738        /**
20739         * Constructor used when reading from a parcel. Reads the state of the superclass.
20740         *
20741         * @param source
20742         */
20743        public BaseSavedState(Parcel source) {
20744            super(source);
20745        }
20746
20747        /**
20748         * Constructor called by derived classes when creating their SavedState objects
20749         *
20750         * @param superState The state of the superclass of this view
20751         */
20752        public BaseSavedState(Parcelable superState) {
20753            super(superState);
20754        }
20755
20756        public static final Parcelable.Creator<BaseSavedState> CREATOR =
20757                new Parcelable.Creator<BaseSavedState>() {
20758            public BaseSavedState createFromParcel(Parcel in) {
20759                return new BaseSavedState(in);
20760            }
20761
20762            public BaseSavedState[] newArray(int size) {
20763                return new BaseSavedState[size];
20764            }
20765        };
20766    }
20767
20768    /**
20769     * A set of information given to a view when it is attached to its parent
20770     * window.
20771     */
20772    final static class AttachInfo {
20773        interface Callbacks {
20774            void playSoundEffect(int effectId);
20775            boolean performHapticFeedback(int effectId, boolean always);
20776        }
20777
20778        /**
20779         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
20780         * to a Handler. This class contains the target (View) to invalidate and
20781         * the coordinates of the dirty rectangle.
20782         *
20783         * For performance purposes, this class also implements a pool of up to
20784         * POOL_LIMIT objects that get reused. This reduces memory allocations
20785         * whenever possible.
20786         */
20787        static class InvalidateInfo {
20788            private static final int POOL_LIMIT = 10;
20789
20790            private static final SynchronizedPool<InvalidateInfo> sPool =
20791                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
20792
20793            View target;
20794
20795            int left;
20796            int top;
20797            int right;
20798            int bottom;
20799
20800            public static InvalidateInfo obtain() {
20801                InvalidateInfo instance = sPool.acquire();
20802                return (instance != null) ? instance : new InvalidateInfo();
20803            }
20804
20805            public void recycle() {
20806                target = null;
20807                sPool.release(this);
20808            }
20809        }
20810
20811        final IWindowSession mSession;
20812
20813        final IWindow mWindow;
20814
20815        final IBinder mWindowToken;
20816
20817        final Display mDisplay;
20818
20819        final Callbacks mRootCallbacks;
20820
20821        IWindowId mIWindowId;
20822        WindowId mWindowId;
20823
20824        /**
20825         * The top view of the hierarchy.
20826         */
20827        View mRootView;
20828
20829        IBinder mPanelParentWindowToken;
20830
20831        boolean mHardwareAccelerated;
20832        boolean mHardwareAccelerationRequested;
20833        HardwareRenderer mHardwareRenderer;
20834        List<RenderNode> mPendingAnimatingRenderNodes;
20835
20836        /**
20837         * The state of the display to which the window is attached, as reported
20838         * by {@link Display#getState()}.  Note that the display state constants
20839         * declared by {@link Display} do not exactly line up with the screen state
20840         * constants declared by {@link View} (there are more display states than
20841         * screen states).
20842         */
20843        int mDisplayState = Display.STATE_UNKNOWN;
20844
20845        /**
20846         * Scale factor used by the compatibility mode
20847         */
20848        float mApplicationScale;
20849
20850        /**
20851         * Indicates whether the application is in compatibility mode
20852         */
20853        boolean mScalingRequired;
20854
20855        /**
20856         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
20857         */
20858        boolean mTurnOffWindowResizeAnim;
20859
20860        /**
20861         * Left position of this view's window
20862         */
20863        int mWindowLeft;
20864
20865        /**
20866         * Top position of this view's window
20867         */
20868        int mWindowTop;
20869
20870        /**
20871         * Indicates whether views need to use 32-bit drawing caches
20872         */
20873        boolean mUse32BitDrawingCache;
20874
20875        /**
20876         * For windows that are full-screen but using insets to layout inside
20877         * of the screen areas, these are the current insets to appear inside
20878         * the overscan area of the display.
20879         */
20880        final Rect mOverscanInsets = new Rect();
20881
20882        /**
20883         * For windows that are full-screen but using insets to layout inside
20884         * of the screen decorations, these are the current insets for the
20885         * content of the window.
20886         */
20887        final Rect mContentInsets = new Rect();
20888
20889        /**
20890         * For windows that are full-screen but using insets to layout inside
20891         * of the screen decorations, these are the current insets for the
20892         * actual visible parts of the window.
20893         */
20894        final Rect mVisibleInsets = new Rect();
20895
20896        /**
20897         * For windows that are full-screen but using insets to layout inside
20898         * of the screen decorations, these are the current insets for the
20899         * stable system windows.
20900         */
20901        final Rect mStableInsets = new Rect();
20902
20903        /**
20904         * The internal insets given by this window.  This value is
20905         * supplied by the client (through
20906         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
20907         * be given to the window manager when changed to be used in laying
20908         * out windows behind it.
20909         */
20910        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
20911                = new ViewTreeObserver.InternalInsetsInfo();
20912
20913        /**
20914         * Set to true when mGivenInternalInsets is non-empty.
20915         */
20916        boolean mHasNonEmptyGivenInternalInsets;
20917
20918        /**
20919         * All views in the window's hierarchy that serve as scroll containers,
20920         * used to determine if the window can be resized or must be panned
20921         * to adjust for a soft input area.
20922         */
20923        final ArrayList<View> mScrollContainers = new ArrayList<View>();
20924
20925        final KeyEvent.DispatcherState mKeyDispatchState
20926                = new KeyEvent.DispatcherState();
20927
20928        /**
20929         * Indicates whether the view's window currently has the focus.
20930         */
20931        boolean mHasWindowFocus;
20932
20933        /**
20934         * The current visibility of the window.
20935         */
20936        int mWindowVisibility;
20937
20938        /**
20939         * Indicates the time at which drawing started to occur.
20940         */
20941        long mDrawingTime;
20942
20943        /**
20944         * Indicates whether or not ignoring the DIRTY_MASK flags.
20945         */
20946        boolean mIgnoreDirtyState;
20947
20948        /**
20949         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
20950         * to avoid clearing that flag prematurely.
20951         */
20952        boolean mSetIgnoreDirtyState = false;
20953
20954        /**
20955         * Indicates whether the view's window is currently in touch mode.
20956         */
20957        boolean mInTouchMode;
20958
20959        /**
20960         * Indicates whether the view has requested unbuffered input dispatching for the current
20961         * event stream.
20962         */
20963        boolean mUnbufferedDispatchRequested;
20964
20965        /**
20966         * Indicates that ViewAncestor should trigger a global layout change
20967         * the next time it performs a traversal
20968         */
20969        boolean mRecomputeGlobalAttributes;
20970
20971        /**
20972         * Always report new attributes at next traversal.
20973         */
20974        boolean mForceReportNewAttributes;
20975
20976        /**
20977         * Set during a traveral if any views want to keep the screen on.
20978         */
20979        boolean mKeepScreenOn;
20980
20981        /**
20982         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
20983         */
20984        int mSystemUiVisibility;
20985
20986        /**
20987         * Hack to force certain system UI visibility flags to be cleared.
20988         */
20989        int mDisabledSystemUiVisibility;
20990
20991        /**
20992         * Last global system UI visibility reported by the window manager.
20993         */
20994        int mGlobalSystemUiVisibility;
20995
20996        /**
20997         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
20998         * attached.
20999         */
21000        boolean mHasSystemUiListeners;
21001
21002        /**
21003         * Set if the window has requested to extend into the overscan region
21004         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21005         */
21006        boolean mOverscanRequested;
21007
21008        /**
21009         * Set if the visibility of any views has changed.
21010         */
21011        boolean mViewVisibilityChanged;
21012
21013        /**
21014         * Set to true if a view has been scrolled.
21015         */
21016        boolean mViewScrollChanged;
21017
21018        /**
21019         * Set to true if high contrast mode enabled
21020         */
21021        boolean mHighContrastText;
21022
21023        /**
21024         * Global to the view hierarchy used as a temporary for dealing with
21025         * x/y points in the transparent region computations.
21026         */
21027        final int[] mTransparentLocation = new int[2];
21028
21029        /**
21030         * Global to the view hierarchy used as a temporary for dealing with
21031         * x/y points in the ViewGroup.invalidateChild implementation.
21032         */
21033        final int[] mInvalidateChildLocation = new int[2];
21034
21035        /**
21036         * Global to the view hierarchy used as a temporary for dealng with
21037         * computing absolute on-screen location.
21038         */
21039        final int[] mTmpLocation = new int[2];
21040
21041        /**
21042         * Global to the view hierarchy used as a temporary for dealing with
21043         * x/y location when view is transformed.
21044         */
21045        final float[] mTmpTransformLocation = new float[2];
21046
21047        /**
21048         * The view tree observer used to dispatch global events like
21049         * layout, pre-draw, touch mode change, etc.
21050         */
21051        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21052
21053        /**
21054         * A Canvas used by the view hierarchy to perform bitmap caching.
21055         */
21056        Canvas mCanvas;
21057
21058        /**
21059         * The view root impl.
21060         */
21061        final ViewRootImpl mViewRootImpl;
21062
21063        /**
21064         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21065         * handler can be used to pump events in the UI events queue.
21066         */
21067        final Handler mHandler;
21068
21069        /**
21070         * Temporary for use in computing invalidate rectangles while
21071         * calling up the hierarchy.
21072         */
21073        final Rect mTmpInvalRect = new Rect();
21074
21075        /**
21076         * Temporary for use in computing hit areas with transformed views
21077         */
21078        final RectF mTmpTransformRect = new RectF();
21079
21080        /**
21081         * Temporary for use in computing hit areas with transformed views
21082         */
21083        final RectF mTmpTransformRect1 = new RectF();
21084
21085        /**
21086         * Temporary list of rectanges.
21087         */
21088        final List<RectF> mTmpRectList = new ArrayList<>();
21089
21090        /**
21091         * Temporary for use in transforming invalidation rect
21092         */
21093        final Matrix mTmpMatrix = new Matrix();
21094
21095        /**
21096         * Temporary for use in transforming invalidation rect
21097         */
21098        final Transformation mTmpTransformation = new Transformation();
21099
21100        /**
21101         * Temporary for use in querying outlines from OutlineProviders
21102         */
21103        final Outline mTmpOutline = new Outline();
21104
21105        /**
21106         * Temporary list for use in collecting focusable descendents of a view.
21107         */
21108        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21109
21110        /**
21111         * The id of the window for accessibility purposes.
21112         */
21113        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21114
21115        /**
21116         * Flags related to accessibility processing.
21117         *
21118         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21119         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21120         */
21121        int mAccessibilityFetchFlags;
21122
21123        /**
21124         * The drawable for highlighting accessibility focus.
21125         */
21126        Drawable mAccessibilityFocusDrawable;
21127
21128        /**
21129         * Show where the margins, bounds and layout bounds are for each view.
21130         */
21131        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21132
21133        /**
21134         * Point used to compute visible regions.
21135         */
21136        final Point mPoint = new Point();
21137
21138        /**
21139         * Used to track which View originated a requestLayout() call, used when
21140         * requestLayout() is called during layout.
21141         */
21142        View mViewRequestingLayout;
21143
21144        /**
21145         * Creates a new set of attachment information with the specified
21146         * events handler and thread.
21147         *
21148         * @param handler the events handler the view must use
21149         */
21150        AttachInfo(IWindowSession session, IWindow window, Display display,
21151                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21152            mSession = session;
21153            mWindow = window;
21154            mWindowToken = window.asBinder();
21155            mDisplay = display;
21156            mViewRootImpl = viewRootImpl;
21157            mHandler = handler;
21158            mRootCallbacks = effectPlayer;
21159        }
21160    }
21161
21162    /**
21163     * <p>ScrollabilityCache holds various fields used by a View when scrolling
21164     * is supported. This avoids keeping too many unused fields in most
21165     * instances of View.</p>
21166     */
21167    private static class ScrollabilityCache implements Runnable {
21168
21169        /**
21170         * Scrollbars are not visible
21171         */
21172        public static final int OFF = 0;
21173
21174        /**
21175         * Scrollbars are visible
21176         */
21177        public static final int ON = 1;
21178
21179        /**
21180         * Scrollbars are fading away
21181         */
21182        public static final int FADING = 2;
21183
21184        public boolean fadeScrollBars;
21185
21186        public int fadingEdgeLength;
21187        public int scrollBarDefaultDelayBeforeFade;
21188        public int scrollBarFadeDuration;
21189
21190        public int scrollBarSize;
21191        public ScrollBarDrawable scrollBar;
21192        public float[] interpolatorValues;
21193        public View host;
21194
21195        public final Paint paint;
21196        public final Matrix matrix;
21197        public Shader shader;
21198
21199        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21200
21201        private static final float[] OPAQUE = { 255 };
21202        private static final float[] TRANSPARENT = { 0.0f };
21203
21204        /**
21205         * When fading should start. This time moves into the future every time
21206         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21207         */
21208        public long fadeStartTime;
21209
21210
21211        /**
21212         * The current state of the scrollbars: ON, OFF, or FADING
21213         */
21214        public int state = OFF;
21215
21216        private int mLastColor;
21217
21218        public ScrollabilityCache(ViewConfiguration configuration, View host) {
21219            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21220            scrollBarSize = configuration.getScaledScrollBarSize();
21221            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21222            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21223
21224            paint = new Paint();
21225            matrix = new Matrix();
21226            // use use a height of 1, and then wack the matrix each time we
21227            // actually use it.
21228            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21229            paint.setShader(shader);
21230            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21231
21232            this.host = host;
21233        }
21234
21235        public void setFadeColor(int color) {
21236            if (color != mLastColor) {
21237                mLastColor = color;
21238
21239                if (color != 0) {
21240                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21241                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21242                    paint.setShader(shader);
21243                    // Restore the default transfer mode (src_over)
21244                    paint.setXfermode(null);
21245                } else {
21246                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21247                    paint.setShader(shader);
21248                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21249                }
21250            }
21251        }
21252
21253        public void run() {
21254            long now = AnimationUtils.currentAnimationTimeMillis();
21255            if (now >= fadeStartTime) {
21256
21257                // the animation fades the scrollbars out by changing
21258                // the opacity (alpha) from fully opaque to fully
21259                // transparent
21260                int nextFrame = (int) now;
21261                int framesCount = 0;
21262
21263                Interpolator interpolator = scrollBarInterpolator;
21264
21265                // Start opaque
21266                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21267
21268                // End transparent
21269                nextFrame += scrollBarFadeDuration;
21270                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21271
21272                state = FADING;
21273
21274                // Kick off the fade animation
21275                host.invalidate(true);
21276            }
21277        }
21278    }
21279
21280    /**
21281     * Resuable callback for sending
21282     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
21283     */
21284    private class SendViewScrolledAccessibilityEvent implements Runnable {
21285        public volatile boolean mIsPending;
21286
21287        public void run() {
21288            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
21289            mIsPending = false;
21290        }
21291    }
21292
21293    /**
21294     * <p>
21295     * This class represents a delegate that can be registered in a {@link View}
21296     * to enhance accessibility support via composition rather via inheritance.
21297     * It is specifically targeted to widget developers that extend basic View
21298     * classes i.e. classes in package android.view, that would like their
21299     * applications to be backwards compatible.
21300     * </p>
21301     * <div class="special reference">
21302     * <h3>Developer Guides</h3>
21303     * <p>For more information about making applications accessible, read the
21304     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
21305     * developer guide.</p>
21306     * </div>
21307     * <p>
21308     * A scenario in which a developer would like to use an accessibility delegate
21309     * is overriding a method introduced in a later API version then the minimal API
21310     * version supported by the application. For example, the method
21311     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
21312     * in API version 4 when the accessibility APIs were first introduced. If a
21313     * developer would like his application to run on API version 4 devices (assuming
21314     * all other APIs used by the application are version 4 or lower) and take advantage
21315     * of this method, instead of overriding the method which would break the application's
21316     * backwards compatibility, he can override the corresponding method in this
21317     * delegate and register the delegate in the target View if the API version of
21318     * the system is high enough i.e. the API version is same or higher to the API
21319     * version that introduced
21320     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
21321     * </p>
21322     * <p>
21323     * Here is an example implementation:
21324     * </p>
21325     * <code><pre><p>
21326     * if (Build.VERSION.SDK_INT >= 14) {
21327     *     // If the API version is equal of higher than the version in
21328     *     // which onInitializeAccessibilityNodeInfo was introduced we
21329     *     // register a delegate with a customized implementation.
21330     *     View view = findViewById(R.id.view_id);
21331     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
21332     *         public void onInitializeAccessibilityNodeInfo(View host,
21333     *                 AccessibilityNodeInfo info) {
21334     *             // Let the default implementation populate the info.
21335     *             super.onInitializeAccessibilityNodeInfo(host, info);
21336     *             // Set some other information.
21337     *             info.setEnabled(host.isEnabled());
21338     *         }
21339     *     });
21340     * }
21341     * </code></pre></p>
21342     * <p>
21343     * This delegate contains methods that correspond to the accessibility methods
21344     * in View. If a delegate has been specified the implementation in View hands
21345     * off handling to the corresponding method in this delegate. The default
21346     * implementation the delegate methods behaves exactly as the corresponding
21347     * method in View for the case of no accessibility delegate been set. Hence,
21348     * to customize the behavior of a View method, clients can override only the
21349     * corresponding delegate method without altering the behavior of the rest
21350     * accessibility related methods of the host view.
21351     * </p>
21352     */
21353    public static class AccessibilityDelegate {
21354
21355        /**
21356         * Sends an accessibility event of the given type. If accessibility is not
21357         * enabled this method has no effect.
21358         * <p>
21359         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
21360         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
21361         * been set.
21362         * </p>
21363         *
21364         * @param host The View hosting the delegate.
21365         * @param eventType The type of the event to send.
21366         *
21367         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
21368         */
21369        public void sendAccessibilityEvent(View host, int eventType) {
21370            host.sendAccessibilityEventInternal(eventType);
21371        }
21372
21373        /**
21374         * Performs the specified accessibility action on the view. For
21375         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
21376         * <p>
21377         * The default implementation behaves as
21378         * {@link View#performAccessibilityAction(int, Bundle)
21379         *  View#performAccessibilityAction(int, Bundle)} for the case of
21380         *  no accessibility delegate been set.
21381         * </p>
21382         *
21383         * @param action The action to perform.
21384         * @return Whether the action was performed.
21385         *
21386         * @see View#performAccessibilityAction(int, Bundle)
21387         *      View#performAccessibilityAction(int, Bundle)
21388         */
21389        public boolean performAccessibilityAction(View host, int action, Bundle args) {
21390            return host.performAccessibilityActionInternal(action, args);
21391        }
21392
21393        /**
21394         * Sends an accessibility event. This method behaves exactly as
21395         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
21396         * empty {@link AccessibilityEvent} and does not perform a check whether
21397         * accessibility is enabled.
21398         * <p>
21399         * The default implementation behaves as
21400         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21401         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
21402         * the case of no accessibility delegate been set.
21403         * </p>
21404         *
21405         * @param host The View hosting the delegate.
21406         * @param event The event to send.
21407         *
21408         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21409         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
21410         */
21411        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
21412            host.sendAccessibilityEventUncheckedInternal(event);
21413        }
21414
21415        /**
21416         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
21417         * to its children for adding their text content to the event.
21418         * <p>
21419         * The default implementation behaves as
21420         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21421         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
21422         * the case of no accessibility delegate been set.
21423         * </p>
21424         *
21425         * @param host The View hosting the delegate.
21426         * @param event The event.
21427         * @return True if the event population was completed.
21428         *
21429         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21430         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
21431         */
21432        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
21433            return host.dispatchPopulateAccessibilityEventInternal(event);
21434        }
21435
21436        /**
21437         * Gives a chance to the host View to populate the accessibility event with its
21438         * text content.
21439         * <p>
21440         * The default implementation behaves as
21441         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
21442         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
21443         * the case of no accessibility delegate been set.
21444         * </p>
21445         *
21446         * @param host The View hosting the delegate.
21447         * @param event The accessibility event which to populate.
21448         *
21449         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
21450         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
21451         */
21452        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
21453            host.onPopulateAccessibilityEventInternal(event);
21454        }
21455
21456        /**
21457         * Initializes an {@link AccessibilityEvent} with information about the
21458         * the host View which is the event source.
21459         * <p>
21460         * The default implementation behaves as
21461         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
21462         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
21463         * the case of no accessibility delegate been set.
21464         * </p>
21465         *
21466         * @param host The View hosting the delegate.
21467         * @param event The event to initialize.
21468         *
21469         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
21470         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
21471         */
21472        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
21473            host.onInitializeAccessibilityEventInternal(event);
21474        }
21475
21476        /**
21477         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
21478         * <p>
21479         * The default implementation behaves as
21480         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21481         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
21482         * the case of no accessibility delegate been set.
21483         * </p>
21484         *
21485         * @param host The View hosting the delegate.
21486         * @param info The instance to initialize.
21487         *
21488         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21489         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
21490         */
21491        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
21492            host.onInitializeAccessibilityNodeInfoInternal(info);
21493        }
21494
21495        /**
21496         * Called when a child of the host View has requested sending an
21497         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
21498         * to augment the event.
21499         * <p>
21500         * The default implementation behaves as
21501         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21502         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
21503         * the case of no accessibility delegate been set.
21504         * </p>
21505         *
21506         * @param host The View hosting the delegate.
21507         * @param child The child which requests sending the event.
21508         * @param event The event to be sent.
21509         * @return True if the event should be sent
21510         *
21511         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21512         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
21513         */
21514        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
21515                AccessibilityEvent event) {
21516            return host.onRequestSendAccessibilityEventInternal(child, event);
21517        }
21518
21519        /**
21520         * Gets the provider for managing a virtual view hierarchy rooted at this View
21521         * and reported to {@link android.accessibilityservice.AccessibilityService}s
21522         * that explore the window content.
21523         * <p>
21524         * The default implementation behaves as
21525         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
21526         * the case of no accessibility delegate been set.
21527         * </p>
21528         *
21529         * @return The provider.
21530         *
21531         * @see AccessibilityNodeProvider
21532         */
21533        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
21534            return null;
21535        }
21536
21537        /**
21538         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
21539         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
21540         * This method is responsible for obtaining an accessibility node info from a
21541         * pool of reusable instances and calling
21542         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
21543         * view to initialize the former.
21544         * <p>
21545         * <strong>Note:</strong> The client is responsible for recycling the obtained
21546         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
21547         * creation.
21548         * </p>
21549         * <p>
21550         * The default implementation behaves as
21551         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
21552         * the case of no accessibility delegate been set.
21553         * </p>
21554         * @return A populated {@link AccessibilityNodeInfo}.
21555         *
21556         * @see AccessibilityNodeInfo
21557         *
21558         * @hide
21559         */
21560        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
21561            return host.createAccessibilityNodeInfoInternal();
21562        }
21563    }
21564
21565    private class MatchIdPredicate implements Predicate<View> {
21566        public int mId;
21567
21568        @Override
21569        public boolean apply(View view) {
21570            return (view.mID == mId);
21571        }
21572    }
21573
21574    private class MatchLabelForPredicate implements Predicate<View> {
21575        private int mLabeledId;
21576
21577        @Override
21578        public boolean apply(View view) {
21579            return (view.mLabelForId == mLabeledId);
21580        }
21581    }
21582
21583    private class SendViewStateChangedAccessibilityEvent implements Runnable {
21584        private int mChangeTypes = 0;
21585        private boolean mPosted;
21586        private boolean mPostedWithDelay;
21587        private long mLastEventTimeMillis;
21588
21589        @Override
21590        public void run() {
21591            mPosted = false;
21592            mPostedWithDelay = false;
21593            mLastEventTimeMillis = SystemClock.uptimeMillis();
21594            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
21595                final AccessibilityEvent event = AccessibilityEvent.obtain();
21596                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
21597                event.setContentChangeTypes(mChangeTypes);
21598                sendAccessibilityEventUnchecked(event);
21599            }
21600            mChangeTypes = 0;
21601        }
21602
21603        public void runOrPost(int changeType) {
21604            mChangeTypes |= changeType;
21605
21606            // If this is a live region or the child of a live region, collect
21607            // all events from this frame and send them on the next frame.
21608            if (inLiveRegion()) {
21609                // If we're already posted with a delay, remove that.
21610                if (mPostedWithDelay) {
21611                    removeCallbacks(this);
21612                    mPostedWithDelay = false;
21613                }
21614                // Only post if we're not already posted.
21615                if (!mPosted) {
21616                    post(this);
21617                    mPosted = true;
21618                }
21619                return;
21620            }
21621
21622            if (mPosted) {
21623                return;
21624            }
21625
21626            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
21627            final long minEventIntevalMillis =
21628                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
21629            if (timeSinceLastMillis >= minEventIntevalMillis) {
21630                removeCallbacks(this);
21631                run();
21632            } else {
21633                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
21634                mPostedWithDelay = true;
21635            }
21636        }
21637    }
21638
21639    private boolean inLiveRegion() {
21640        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21641            return true;
21642        }
21643
21644        ViewParent parent = getParent();
21645        while (parent instanceof View) {
21646            if (((View) parent).getAccessibilityLiveRegion()
21647                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
21648                return true;
21649            }
21650            parent = parent.getParent();
21651        }
21652
21653        return false;
21654    }
21655
21656    /**
21657     * Dump all private flags in readable format, useful for documentation and
21658     * sanity checking.
21659     */
21660    private static void dumpFlags() {
21661        final HashMap<String, String> found = Maps.newHashMap();
21662        try {
21663            for (Field field : View.class.getDeclaredFields()) {
21664                final int modifiers = field.getModifiers();
21665                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
21666                    if (field.getType().equals(int.class)) {
21667                        final int value = field.getInt(null);
21668                        dumpFlag(found, field.getName(), value);
21669                    } else if (field.getType().equals(int[].class)) {
21670                        final int[] values = (int[]) field.get(null);
21671                        for (int i = 0; i < values.length; i++) {
21672                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
21673                        }
21674                    }
21675                }
21676            }
21677        } catch (IllegalAccessException e) {
21678            throw new RuntimeException(e);
21679        }
21680
21681        final ArrayList<String> keys = Lists.newArrayList();
21682        keys.addAll(found.keySet());
21683        Collections.sort(keys);
21684        for (String key : keys) {
21685            Log.d(VIEW_LOG_TAG, found.get(key));
21686        }
21687    }
21688
21689    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
21690        // Sort flags by prefix, then by bits, always keeping unique keys
21691        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
21692        final int prefix = name.indexOf('_');
21693        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
21694        final String output = bits + " " + name;
21695        found.put(key, output);
21696    }
21697}
21698