View.java revision e2acc5e2839abe7dfc59bf6e2154cc88cd039436
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
19import android.animation.AnimatorInflater;
20import android.animation.StateListAnimator;
21import android.annotation.CallSuper;
22import android.annotation.ColorInt;
23import android.annotation.DrawableRes;
24import android.annotation.FloatRange;
25import android.annotation.IdRes;
26import android.annotation.IntDef;
27import android.annotation.LayoutRes;
28import android.annotation.NonNull;
29import android.annotation.Nullable;
30import android.annotation.Size;
31import android.annotation.UiThread;
32import android.content.ClipData;
33import android.content.Context;
34import android.content.ContextWrapper;
35import android.content.Intent;
36import android.content.res.ColorStateList;
37import android.content.res.Configuration;
38import android.content.res.Resources;
39import android.content.res.TypedArray;
40import android.graphics.Bitmap;
41import android.graphics.Canvas;
42import android.graphics.Insets;
43import android.graphics.Interpolator;
44import android.graphics.LinearGradient;
45import android.graphics.Matrix;
46import android.graphics.Outline;
47import android.graphics.Paint;
48import android.graphics.PixelFormat;
49import android.graphics.Point;
50import android.graphics.PorterDuff;
51import android.graphics.PorterDuffXfermode;
52import android.graphics.Rect;
53import android.graphics.RectF;
54import android.graphics.Region;
55import android.graphics.Shader;
56import android.graphics.drawable.ColorDrawable;
57import android.graphics.drawable.Drawable;
58import android.hardware.display.DisplayManagerGlobal;
59import android.os.Build.VERSION_CODES;
60import android.os.Bundle;
61import android.os.Handler;
62import android.os.IBinder;
63import android.os.Parcel;
64import android.os.Parcelable;
65import android.os.RemoteException;
66import android.os.SystemClock;
67import android.os.SystemProperties;
68import android.os.Trace;
69import android.text.TextUtils;
70import android.util.AttributeSet;
71import android.util.FloatProperty;
72import android.util.LayoutDirection;
73import android.util.Log;
74import android.util.LongSparseLongArray;
75import android.util.Pools.SynchronizedPool;
76import android.util.Property;
77import android.util.SparseArray;
78import android.util.StateSet;
79import android.util.SuperNotCalledException;
80import android.util.TypedValue;
81import android.view.ContextMenu.ContextMenuInfo;
82import android.view.AccessibilityIterators.TextSegmentIterator;
83import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
84import android.view.AccessibilityIterators.WordTextSegmentIterator;
85import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
86import android.view.accessibility.AccessibilityEvent;
87import android.view.accessibility.AccessibilityEventSource;
88import android.view.accessibility.AccessibilityManager;
89import android.view.accessibility.AccessibilityNodeInfo;
90import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
91import android.view.accessibility.AccessibilityNodeProvider;
92import android.view.animation.Animation;
93import android.view.animation.AnimationUtils;
94import android.view.animation.Transformation;
95import android.view.inputmethod.EditorInfo;
96import android.view.inputmethod.InputConnection;
97import android.view.inputmethod.InputMethodManager;
98import android.widget.Checkable;
99import android.widget.FrameLayout;
100import android.widget.ScrollBarDrawable;
101
102import static android.os.Build.VERSION_CODES.*;
103import static java.lang.Math.max;
104
105import com.android.internal.R;
106import com.android.internal.util.Predicate;
107import com.android.internal.view.menu.MenuBuilder;
108import com.google.android.collect.Lists;
109import com.google.android.collect.Maps;
110
111import java.lang.annotation.Retention;
112import java.lang.annotation.RetentionPolicy;
113import java.lang.ref.WeakReference;
114import java.lang.reflect.Field;
115import java.lang.reflect.InvocationTargetException;
116import java.lang.reflect.Method;
117import java.lang.reflect.Modifier;
118import java.util.ArrayList;
119import java.util.Arrays;
120import java.util.Collections;
121import java.util.HashMap;
122import java.util.List;
123import java.util.Locale;
124import java.util.Map;
125import java.util.concurrent.CopyOnWriteArrayList;
126import java.util.concurrent.atomic.AtomicInteger;
127
128/**
129 * <p>
130 * This class represents the basic building block for user interface components. A View
131 * occupies a rectangular area on the screen and is responsible for drawing and
132 * event handling. View is the base class for <em>widgets</em>, which are
133 * used to create interactive UI components (buttons, text fields, etc.). The
134 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
135 * are invisible containers that hold other Views (or other ViewGroups) and define
136 * their layout properties.
137 * </p>
138 *
139 * <div class="special reference">
140 * <h3>Developer Guides</h3>
141 * <p>For information about using this class to develop your application's user interface,
142 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
143 * </div>
144 *
145 * <a name="Using"></a>
146 * <h3>Using Views</h3>
147 * <p>
148 * All of the views in a window are arranged in a single tree. You can add views
149 * either from code or by specifying a tree of views in one or more XML layout
150 * files. There are many specialized subclasses of views that act as controls or
151 * are capable of displaying text, images, or other content.
152 * </p>
153 * <p>
154 * Once you have created a tree of views, there are typically a few types of
155 * common operations you may wish to perform:
156 * <ul>
157 * <li><strong>Set properties:</strong> for example setting the text of a
158 * {@link android.widget.TextView}. The available properties and the methods
159 * that set them will vary among the different subclasses of views. Note that
160 * properties that are known at build time can be set in the XML layout
161 * files.</li>
162 * <li><strong>Set focus:</strong> The framework will handled moving focus in
163 * response to user input. To force focus to a specific view, call
164 * {@link #requestFocus}.</li>
165 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
166 * that will be notified when something interesting happens to the view. For
167 * example, all views will let you set a listener to be notified when the view
168 * gains or loses focus. You can register such a listener using
169 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
170 * Other view subclasses offer more specialized listeners. For example, a Button
171 * exposes a listener to notify clients when the button is clicked.</li>
172 * <li><strong>Set visibility:</strong> You can hide or show views using
173 * {@link #setVisibility(int)}.</li>
174 * </ul>
175 * </p>
176 * <p><em>
177 * Note: The Android framework is responsible for measuring, laying out and
178 * drawing views. You should not call methods that perform these actions on
179 * views yourself unless you are actually implementing a
180 * {@link android.view.ViewGroup}.
181 * </em></p>
182 *
183 * <a name="Lifecycle"></a>
184 * <h3>Implementing a Custom View</h3>
185 *
186 * <p>
187 * To implement a custom view, you will usually begin by providing overrides for
188 * some of the standard methods that the framework calls on all views. You do
189 * not need to override all of these methods. In fact, you can start by just
190 * overriding {@link #onDraw(android.graphics.Canvas)}.
191 * <table border="2" width="85%" align="center" cellpadding="5">
192 *     <thead>
193 *         <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
194 *     </thead>
195 *
196 *     <tbody>
197 *     <tr>
198 *         <td rowspan="2">Creation</td>
199 *         <td>Constructors</td>
200 *         <td>There is a form of the constructor that are called when the view
201 *         is created from code and a form that is called when the view is
202 *         inflated from a layout file. The second form should parse and apply
203 *         any attributes defined in the layout file.
204 *         </td>
205 *     </tr>
206 *     <tr>
207 *         <td><code>{@link #onFinishInflate()}</code></td>
208 *         <td>Called after a view and all of its children has been inflated
209 *         from XML.</td>
210 *     </tr>
211 *
212 *     <tr>
213 *         <td rowspan="3">Layout</td>
214 *         <td><code>{@link #onMeasure(int, int)}</code></td>
215 *         <td>Called to determine the size requirements for this view and all
216 *         of its children.
217 *         </td>
218 *     </tr>
219 *     <tr>
220 *         <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
221 *         <td>Called when this view should assign a size and position to all
222 *         of its children.
223 *         </td>
224 *     </tr>
225 *     <tr>
226 *         <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
227 *         <td>Called when the size of this view has changed.
228 *         </td>
229 *     </tr>
230 *
231 *     <tr>
232 *         <td>Drawing</td>
233 *         <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
234 *         <td>Called when the view should render its content.
235 *         </td>
236 *     </tr>
237 *
238 *     <tr>
239 *         <td rowspan="4">Event processing</td>
240 *         <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
241 *         <td>Called when a new hardware key event occurs.
242 *         </td>
243 *     </tr>
244 *     <tr>
245 *         <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
246 *         <td>Called when a hardware key up event occurs.
247 *         </td>
248 *     </tr>
249 *     <tr>
250 *         <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
251 *         <td>Called when a trackball motion event occurs.
252 *         </td>
253 *     </tr>
254 *     <tr>
255 *         <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
256 *         <td>Called when a touch screen motion event occurs.
257 *         </td>
258 *     </tr>
259 *
260 *     <tr>
261 *         <td rowspan="2">Focus</td>
262 *         <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
263 *         <td>Called when the view gains or loses focus.
264 *         </td>
265 *     </tr>
266 *
267 *     <tr>
268 *         <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
269 *         <td>Called when the window containing the view gains or loses focus.
270 *         </td>
271 *     </tr>
272 *
273 *     <tr>
274 *         <td rowspan="3">Attaching</td>
275 *         <td><code>{@link #onAttachedToWindow()}</code></td>
276 *         <td>Called when the view is attached to a window.
277 *         </td>
278 *     </tr>
279 *
280 *     <tr>
281 *         <td><code>{@link #onDetachedFromWindow}</code></td>
282 *         <td>Called when the view is detached from its window.
283 *         </td>
284 *     </tr>
285 *
286 *     <tr>
287 *         <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
288 *         <td>Called when the visibility of the window containing the view
289 *         has changed.
290 *         </td>
291 *     </tr>
292 *     </tbody>
293 *
294 * </table>
295 * </p>
296 *
297 * <a name="IDs"></a>
298 * <h3>IDs</h3>
299 * Views may have an integer id associated with them. These ids are typically
300 * assigned in the layout XML files, and are used to find specific views within
301 * the view tree. A common pattern is to:
302 * <ul>
303 * <li>Define a Button in the layout file and assign it a unique ID.
304 * <pre>
305 * &lt;Button
306 *     android:id="@+id/my_button"
307 *     android:layout_width="wrap_content"
308 *     android:layout_height="wrap_content"
309 *     android:text="@string/my_button_text"/&gt;
310 * </pre></li>
311 * <li>From the onCreate method of an Activity, find the Button
312 * <pre class="prettyprint">
313 *      Button myButton = (Button) findViewById(R.id.my_button);
314 * </pre></li>
315 * </ul>
316 * <p>
317 * View IDs need not be unique throughout the tree, but it is good practice to
318 * ensure that they are at least unique within the part of the tree you are
319 * searching.
320 * </p>
321 *
322 * <a name="Position"></a>
323 * <h3>Position</h3>
324 * <p>
325 * The geometry of a view is that of a rectangle. A view has a location,
326 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
327 * two dimensions, expressed as a width and a height. The unit for location
328 * and dimensions is the pixel.
329 * </p>
330 *
331 * <p>
332 * It is possible to retrieve the location of a view by invoking the methods
333 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
334 * coordinate of the rectangle representing the view. The latter returns the
335 * top, or Y, coordinate of the rectangle representing the view. These methods
336 * both return the location of the view relative to its parent. For instance,
337 * when getLeft() returns 20, that means the view is located 20 pixels to the
338 * right of the left edge of its direct parent.
339 * </p>
340 *
341 * <p>
342 * In addition, several convenience methods are offered to avoid unnecessary
343 * computations, namely {@link #getRight()} and {@link #getBottom()}.
344 * These methods return the coordinates of the right and bottom edges of the
345 * rectangle representing the view. For instance, calling {@link #getRight()}
346 * is similar to the following computation: <code>getLeft() + getWidth()</code>
347 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
348 * </p>
349 *
350 * <a name="SizePaddingMargins"></a>
351 * <h3>Size, padding and margins</h3>
352 * <p>
353 * The size of a view is expressed with a width and a height. A view actually
354 * possess two pairs of width and height values.
355 * </p>
356 *
357 * <p>
358 * The first pair is known as <em>measured width</em> and
359 * <em>measured height</em>. These dimensions define how big a view wants to be
360 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
361 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
362 * and {@link #getMeasuredHeight()}.
363 * </p>
364 *
365 * <p>
366 * The second pair is simply known as <em>width</em> and <em>height</em>, or
367 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
368 * dimensions define the actual size of the view on screen, at drawing time and
369 * after layout. These values may, but do not have to, be different from the
370 * measured width and height. The width and height can be obtained by calling
371 * {@link #getWidth()} and {@link #getHeight()}.
372 * </p>
373 *
374 * <p>
375 * To measure its dimensions, a view takes into account its padding. The padding
376 * is expressed in pixels for the left, top, right and bottom parts of the view.
377 * Padding can be used to offset the content of the view by a specific amount of
378 * pixels. For instance, a left padding of 2 will push the view's content by
379 * 2 pixels to the right of the left edge. Padding can be set using the
380 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
381 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
382 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
383 * {@link #getPaddingEnd()}.
384 * </p>
385 *
386 * <p>
387 * Even though a view can define a padding, it does not provide any support for
388 * margins. However, view groups provide such a support. Refer to
389 * {@link android.view.ViewGroup} and
390 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
391 * </p>
392 *
393 * <a name="Layout"></a>
394 * <h3>Layout</h3>
395 * <p>
396 * Layout is a two pass process: a measure pass and a layout pass. The measuring
397 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
398 * of the view tree. Each view pushes dimension specifications down the tree
399 * during the recursion. At the end of the measure pass, every view has stored
400 * its measurements. The second pass happens in
401 * {@link #layout(int,int,int,int)} and is also top-down. During
402 * this pass each parent is responsible for positioning all of its children
403 * using the sizes computed in the measure pass.
404 * </p>
405 *
406 * <p>
407 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
408 * {@link #getMeasuredHeight()} values must be set, along with those for all of
409 * that view's descendants. A view's measured width and measured height values
410 * must respect the constraints imposed by the view's parents. This guarantees
411 * that at the end of the measure pass, all parents accept all of their
412 * children's measurements. A parent view may call measure() more than once on
413 * its children. For example, the parent may measure each child once with
414 * unspecified dimensions to find out how big they want to be, then call
415 * measure() on them again with actual numbers if the sum of all the children's
416 * unconstrained sizes is too big or too small.
417 * </p>
418 *
419 * <p>
420 * The measure pass uses two classes to communicate dimensions. The
421 * {@link MeasureSpec} class is used by views to tell their parents how they
422 * want to be measured and positioned. The base LayoutParams class just
423 * describes how big the view wants to be for both width and height. For each
424 * dimension, it can specify one of:
425 * <ul>
426 * <li> an exact number
427 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
428 * (minus padding)
429 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
430 * enclose its content (plus padding).
431 * </ul>
432 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
433 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
434 * an X and Y value.
435 * </p>
436 *
437 * <p>
438 * MeasureSpecs are used to push requirements down the tree from parent to
439 * child. A MeasureSpec can be in one of three modes:
440 * <ul>
441 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
442 * of a child view. For example, a LinearLayout may call measure() on its child
443 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
444 * tall the child view wants to be given a width of 240 pixels.
445 * <li>EXACTLY: This is used by the parent to impose an exact size on the
446 * child. The child must use this size, and guarantee that all of its
447 * descendants will fit within this size.
448 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
449 * child. The child must guarantee that it and all of its descendants will fit
450 * within this size.
451 * </ul>
452 * </p>
453 *
454 * <p>
455 * To initiate a layout, call {@link #requestLayout}. This method is typically
456 * called by a view on itself when it believes that is can no longer fit within
457 * its current bounds.
458 * </p>
459 *
460 * <a name="Drawing"></a>
461 * <h3>Drawing</h3>
462 * <p>
463 * Drawing is handled by walking the tree and recording the drawing commands of
464 * any View that needs to update. After this, the drawing commands of the
465 * entire tree are issued to screen, clipped to the newly damaged area.
466 * </p>
467 *
468 * <p>
469 * The tree is largely recorded and drawn in order, with parents drawn before
470 * (i.e., behind) their children, with siblings drawn in the order they appear
471 * in the tree. If you set a background drawable for a View, then the View will
472 * draw it before calling back to its <code>onDraw()</code> method. The child
473 * drawing order can be overridden with
474 * {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean) custom child drawing order}
475 * in a ViewGroup, and with {@link #setZ(float)} custom Z values} set on Views.
476 * </p>
477 *
478 * <p>
479 * To force a view to draw, call {@link #invalidate()}.
480 * </p>
481 *
482 * <a name="EventHandlingThreading"></a>
483 * <h3>Event Handling and Threading</h3>
484 * <p>
485 * The basic cycle of a view is as follows:
486 * <ol>
487 * <li>An event comes in and is dispatched to the appropriate view. The view
488 * handles the event and notifies any listeners.</li>
489 * <li>If in the course of processing the event, the view's bounds may need
490 * to be changed, the view will call {@link #requestLayout()}.</li>
491 * <li>Similarly, if in the course of processing the event the view's appearance
492 * may need to be changed, the view will call {@link #invalidate()}.</li>
493 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
494 * the framework will take care of measuring, laying out, and drawing the tree
495 * as appropriate.</li>
496 * </ol>
497 * </p>
498 *
499 * <p><em>Note: The entire view tree is single threaded. You must always be on
500 * the UI thread when calling any method on any view.</em>
501 * If you are doing work on other threads and want to update the state of a view
502 * from that thread, you should use a {@link Handler}.
503 * </p>
504 *
505 * <a name="FocusHandling"></a>
506 * <h3>Focus Handling</h3>
507 * <p>
508 * The framework will handle routine focus movement in response to user input.
509 * This includes changing the focus as views are removed or hidden, or as new
510 * views become available. Views indicate their willingness to take focus
511 * through the {@link #isFocusable} method. To change whether a view can take
512 * focus, call {@link #setFocusable(boolean)}.  When in touch mode (see notes below)
513 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
514 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
515 * </p>
516 * <p>
517 * Focus movement is based on an algorithm which finds the nearest neighbor in a
518 * given direction. In rare cases, the default algorithm may not match the
519 * intended behavior of the developer. In these situations, you can provide
520 * explicit overrides by using these XML attributes in the layout file:
521 * <pre>
522 * nextFocusDown
523 * nextFocusLeft
524 * nextFocusRight
525 * nextFocusUp
526 * </pre>
527 * </p>
528 *
529 *
530 * <p>
531 * To get a particular view to take focus, call {@link #requestFocus()}.
532 * </p>
533 *
534 * <a name="TouchMode"></a>
535 * <h3>Touch Mode</h3>
536 * <p>
537 * When a user is navigating a user interface via directional keys such as a D-pad, it is
538 * necessary to give focus to actionable items such as buttons so the user can see
539 * what will take input.  If the device has touch capabilities, however, and the user
540 * begins interacting with the interface by touching it, it is no longer necessary to
541 * always highlight, or give focus to, a particular view.  This motivates a mode
542 * for interaction named 'touch mode'.
543 * </p>
544 * <p>
545 * For a touch capable device, once the user touches the screen, the device
546 * will enter touch mode.  From this point onward, only views for which
547 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
548 * Other views that are touchable, like buttons, will not take focus when touched; they will
549 * only fire the on click listeners.
550 * </p>
551 * <p>
552 * Any time a user hits a directional key, such as a D-pad direction, the view device will
553 * exit touch mode, and find a view to take focus, so that the user may resume interacting
554 * with the user interface without touching the screen again.
555 * </p>
556 * <p>
557 * The touch mode state is maintained across {@link android.app.Activity}s.  Call
558 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
559 * </p>
560 *
561 * <a name="Scrolling"></a>
562 * <h3>Scrolling</h3>
563 * <p>
564 * The framework provides basic support for views that wish to internally
565 * scroll their content. This includes keeping track of the X and Y scroll
566 * offset as well as mechanisms for drawing scrollbars. See
567 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
568 * {@link #awakenScrollBars()} for more details.
569 * </p>
570 *
571 * <a name="Tags"></a>
572 * <h3>Tags</h3>
573 * <p>
574 * Unlike IDs, tags are not used to identify views. Tags are essentially an
575 * extra piece of information that can be associated with a view. They are most
576 * often used as a convenience to store data related to views in the views
577 * themselves rather than by putting them in a separate structure.
578 * </p>
579 *
580 * <a name="Properties"></a>
581 * <h3>Properties</h3>
582 * <p>
583 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
584 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
585 * available both in the {@link Property} form as well as in similarly-named setter/getter
586 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
587 * be used to set persistent state associated with these rendering-related properties on the view.
588 * The properties and methods can also be used in conjunction with
589 * {@link android.animation.Animator Animator}-based animations, described more in the
590 * <a href="#Animation">Animation</a> section.
591 * </p>
592 *
593 * <a name="Animation"></a>
594 * <h3>Animation</h3>
595 * <p>
596 * Starting with Android 3.0, the preferred way of animating views is to use the
597 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
598 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
599 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
600 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
601 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
602 * makes animating these View properties particularly easy and efficient.
603 * </p>
604 * <p>
605 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
606 * You can attach an {@link Animation} object to a view using
607 * {@link #setAnimation(Animation)} or
608 * {@link #startAnimation(Animation)}. The animation can alter the scale,
609 * rotation, translation and alpha of a view over time. If the animation is
610 * attached to a view that has children, the animation will affect the entire
611 * subtree rooted by that node. When an animation is started, the framework will
612 * take care of redrawing the appropriate views until the animation completes.
613 * </p>
614 *
615 * <a name="Security"></a>
616 * <h3>Security</h3>
617 * <p>
618 * Sometimes it is essential that an application be able to verify that an action
619 * is being performed with the full knowledge and consent of the user, such as
620 * granting a permission request, making a purchase or clicking on an advertisement.
621 * Unfortunately, a malicious application could try to spoof the user into
622 * performing these actions, unaware, by concealing the intended purpose of the view.
623 * As a remedy, the framework offers a touch filtering mechanism that can be used to
624 * improve the security of views that provide access to sensitive functionality.
625 * </p><p>
626 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
627 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
628 * will discard touches that are received whenever the view's window is obscured by
629 * another visible window.  As a result, the view will not receive touches whenever a
630 * toast, dialog or other window appears above the view's window.
631 * </p><p>
632 * For more fine-grained control over security, consider overriding the
633 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
634 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
635 * </p>
636 *
637 * @attr ref android.R.styleable#View_alpha
638 * @attr ref android.R.styleable#View_background
639 * @attr ref android.R.styleable#View_clickable
640 * @attr ref android.R.styleable#View_contentDescription
641 * @attr ref android.R.styleable#View_drawingCacheQuality
642 * @attr ref android.R.styleable#View_duplicateParentState
643 * @attr ref android.R.styleable#View_id
644 * @attr ref android.R.styleable#View_requiresFadingEdge
645 * @attr ref android.R.styleable#View_fadeScrollbars
646 * @attr ref android.R.styleable#View_fadingEdgeLength
647 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
648 * @attr ref android.R.styleable#View_fitsSystemWindows
649 * @attr ref android.R.styleable#View_isScrollContainer
650 * @attr ref android.R.styleable#View_focusable
651 * @attr ref android.R.styleable#View_focusableInTouchMode
652 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
653 * @attr ref android.R.styleable#View_keepScreenOn
654 * @attr ref android.R.styleable#View_layerType
655 * @attr ref android.R.styleable#View_layoutDirection
656 * @attr ref android.R.styleable#View_longClickable
657 * @attr ref android.R.styleable#View_minHeight
658 * @attr ref android.R.styleable#View_minWidth
659 * @attr ref android.R.styleable#View_nextFocusDown
660 * @attr ref android.R.styleable#View_nextFocusLeft
661 * @attr ref android.R.styleable#View_nextFocusRight
662 * @attr ref android.R.styleable#View_nextFocusUp
663 * @attr ref android.R.styleable#View_onClick
664 * @attr ref android.R.styleable#View_padding
665 * @attr ref android.R.styleable#View_paddingBottom
666 * @attr ref android.R.styleable#View_paddingLeft
667 * @attr ref android.R.styleable#View_paddingRight
668 * @attr ref android.R.styleable#View_paddingTop
669 * @attr ref android.R.styleable#View_paddingStart
670 * @attr ref android.R.styleable#View_paddingEnd
671 * @attr ref android.R.styleable#View_saveEnabled
672 * @attr ref android.R.styleable#View_rotation
673 * @attr ref android.R.styleable#View_rotationX
674 * @attr ref android.R.styleable#View_rotationY
675 * @attr ref android.R.styleable#View_scaleX
676 * @attr ref android.R.styleable#View_scaleY
677 * @attr ref android.R.styleable#View_scrollX
678 * @attr ref android.R.styleable#View_scrollY
679 * @attr ref android.R.styleable#View_scrollbarSize
680 * @attr ref android.R.styleable#View_scrollbarStyle
681 * @attr ref android.R.styleable#View_scrollbars
682 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
683 * @attr ref android.R.styleable#View_scrollbarFadeDuration
684 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
685 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
686 * @attr ref android.R.styleable#View_scrollbarThumbVertical
687 * @attr ref android.R.styleable#View_scrollbarTrackVertical
688 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
689 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
690 * @attr ref android.R.styleable#View_stateListAnimator
691 * @attr ref android.R.styleable#View_transitionName
692 * @attr ref android.R.styleable#View_soundEffectsEnabled
693 * @attr ref android.R.styleable#View_tag
694 * @attr ref android.R.styleable#View_textAlignment
695 * @attr ref android.R.styleable#View_textDirection
696 * @attr ref android.R.styleable#View_transformPivotX
697 * @attr ref android.R.styleable#View_transformPivotY
698 * @attr ref android.R.styleable#View_translationX
699 * @attr ref android.R.styleable#View_translationY
700 * @attr ref android.R.styleable#View_translationZ
701 * @attr ref android.R.styleable#View_visibility
702 *
703 * @see android.view.ViewGroup
704 */
705@UiThread
706public class View implements Drawable.Callback, KeyEvent.Callback,
707        AccessibilityEventSource {
708    private static final boolean DBG = false;
709
710    /**
711     * The logging tag used by this class with android.util.Log.
712     */
713    protected static final String VIEW_LOG_TAG = "View";
714
715    /**
716     * When set to true, apps will draw debugging information about their layouts.
717     *
718     * @hide
719     */
720    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
721
722    /**
723     * When set to true, this view will save its attribute data.
724     *
725     * @hide
726     */
727    public static boolean mDebugViewAttributes = false;
728
729    /**
730     * Used to mark a View that has no ID.
731     */
732    public static final int NO_ID = -1;
733
734    /**
735     * Signals that compatibility booleans have been initialized according to
736     * target SDK versions.
737     */
738    private static boolean sCompatibilityDone = false;
739
740    /**
741     * Use the old (broken) way of building MeasureSpecs.
742     */
743    private static boolean sUseBrokenMakeMeasureSpec = false;
744
745    /**
746     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
747     */
748    static boolean sUseZeroUnspecifiedMeasureSpec = false;
749
750    /**
751     * Ignore any optimizations using the measure cache.
752     */
753    private static boolean sIgnoreMeasureCache = false;
754
755    /**
756     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
757     */
758    private static boolean sAlwaysRemeasureExactly = false;
759
760    /**
761     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
762     * calling setFlags.
763     */
764    private static final int NOT_FOCUSABLE = 0x00000000;
765
766    /**
767     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
768     * setFlags.
769     */
770    private static final int FOCUSABLE = 0x00000001;
771
772    /**
773     * Mask for use with setFlags indicating bits used for focus.
774     */
775    private static final int FOCUSABLE_MASK = 0x00000001;
776
777    /**
778     * This view will adjust its padding to fit sytem windows (e.g. status bar)
779     */
780    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
781
782    /** @hide */
783    @IntDef({VISIBLE, INVISIBLE, GONE})
784    @Retention(RetentionPolicy.SOURCE)
785    public @interface Visibility {}
786
787    /**
788     * This view is visible.
789     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
790     * android:visibility}.
791     */
792    public static final int VISIBLE = 0x00000000;
793
794    /**
795     * This view is invisible, but it still takes up space for layout purposes.
796     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
797     * android:visibility}.
798     */
799    public static final int INVISIBLE = 0x00000004;
800
801    /**
802     * This view is invisible, and it doesn't take any space for layout
803     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
804     * android:visibility}.
805     */
806    public static final int GONE = 0x00000008;
807
808    /**
809     * Mask for use with setFlags indicating bits used for visibility.
810     * {@hide}
811     */
812    static final int VISIBILITY_MASK = 0x0000000C;
813
814    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
815
816    /**
817     * This view is enabled. Interpretation varies by subclass.
818     * Use with ENABLED_MASK when calling setFlags.
819     * {@hide}
820     */
821    static final int ENABLED = 0x00000000;
822
823    /**
824     * This view is disabled. Interpretation varies by subclass.
825     * Use with ENABLED_MASK when calling setFlags.
826     * {@hide}
827     */
828    static final int DISABLED = 0x00000020;
829
830   /**
831    * Mask for use with setFlags indicating bits used for indicating whether
832    * this view is enabled
833    * {@hide}
834    */
835    static final int ENABLED_MASK = 0x00000020;
836
837    /**
838     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
839     * called and further optimizations will be performed. It is okay to have
840     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
841     * {@hide}
842     */
843    static final int WILL_NOT_DRAW = 0x00000080;
844
845    /**
846     * Mask for use with setFlags indicating bits used for indicating whether
847     * this view is will draw
848     * {@hide}
849     */
850    static final int DRAW_MASK = 0x00000080;
851
852    /**
853     * <p>This view doesn't show scrollbars.</p>
854     * {@hide}
855     */
856    static final int SCROLLBARS_NONE = 0x00000000;
857
858    /**
859     * <p>This view shows horizontal scrollbars.</p>
860     * {@hide}
861     */
862    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
863
864    /**
865     * <p>This view shows vertical scrollbars.</p>
866     * {@hide}
867     */
868    static final int SCROLLBARS_VERTICAL = 0x00000200;
869
870    /**
871     * <p>Mask for use with setFlags indicating bits used for indicating which
872     * scrollbars are enabled.</p>
873     * {@hide}
874     */
875    static final int SCROLLBARS_MASK = 0x00000300;
876
877    /**
878     * Indicates that the view should filter touches when its window is obscured.
879     * Refer to the class comments for more information about this security feature.
880     * {@hide}
881     */
882    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
883
884    /**
885     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
886     * that they are optional and should be skipped if the window has
887     * requested system UI flags that ignore those insets for layout.
888     */
889    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
890
891    /**
892     * <p>This view doesn't show fading edges.</p>
893     * {@hide}
894     */
895    static final int FADING_EDGE_NONE = 0x00000000;
896
897    /**
898     * <p>This view shows horizontal fading edges.</p>
899     * {@hide}
900     */
901    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
902
903    /**
904     * <p>This view shows vertical fading edges.</p>
905     * {@hide}
906     */
907    static final int FADING_EDGE_VERTICAL = 0x00002000;
908
909    /**
910     * <p>Mask for use with setFlags indicating bits used for indicating which
911     * fading edges are enabled.</p>
912     * {@hide}
913     */
914    static final int FADING_EDGE_MASK = 0x00003000;
915
916    /**
917     * <p>Indicates this view can be clicked. When clickable, a View reacts
918     * to clicks by notifying the OnClickListener.<p>
919     * {@hide}
920     */
921    static final int CLICKABLE = 0x00004000;
922
923    /**
924     * <p>Indicates this view is caching its drawing into a bitmap.</p>
925     * {@hide}
926     */
927    static final int DRAWING_CACHE_ENABLED = 0x00008000;
928
929    /**
930     * <p>Indicates that no icicle should be saved for this view.<p>
931     * {@hide}
932     */
933    static final int SAVE_DISABLED = 0x000010000;
934
935    /**
936     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
937     * property.</p>
938     * {@hide}
939     */
940    static final int SAVE_DISABLED_MASK = 0x000010000;
941
942    /**
943     * <p>Indicates that no drawing cache should ever be created for this view.<p>
944     * {@hide}
945     */
946    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
947
948    /**
949     * <p>Indicates this view can take / keep focus when int touch mode.</p>
950     * {@hide}
951     */
952    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
953
954    /** @hide */
955    @Retention(RetentionPolicy.SOURCE)
956    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
957    public @interface DrawingCacheQuality {}
958
959    /**
960     * <p>Enables low quality mode for the drawing cache.</p>
961     */
962    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
963
964    /**
965     * <p>Enables high quality mode for the drawing cache.</p>
966     */
967    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
968
969    /**
970     * <p>Enables automatic quality mode for the drawing cache.</p>
971     */
972    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
973
974    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
975            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
976    };
977
978    /**
979     * <p>Mask for use with setFlags indicating bits used for the cache
980     * quality property.</p>
981     * {@hide}
982     */
983    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
984
985    /**
986     * <p>
987     * Indicates this view can be long clicked. When long clickable, a View
988     * reacts to long clicks by notifying the OnLongClickListener or showing a
989     * context menu.
990     * </p>
991     * {@hide}
992     */
993    static final int LONG_CLICKABLE = 0x00200000;
994
995    /**
996     * <p>Indicates that this view gets its drawable states from its direct parent
997     * and ignores its original internal states.</p>
998     *
999     * @hide
1000     */
1001    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1002
1003    /**
1004     * <p>
1005     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1006     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1007     * OnContextClickListener.
1008     * </p>
1009     * {@hide}
1010     */
1011    static final int CONTEXT_CLICKABLE = 0x00800000;
1012
1013
1014    /** @hide */
1015    @IntDef({
1016        SCROLLBARS_INSIDE_OVERLAY,
1017        SCROLLBARS_INSIDE_INSET,
1018        SCROLLBARS_OUTSIDE_OVERLAY,
1019        SCROLLBARS_OUTSIDE_INSET
1020    })
1021    @Retention(RetentionPolicy.SOURCE)
1022    public @interface ScrollBarStyle {}
1023
1024    /**
1025     * The scrollbar style to display the scrollbars inside the content area,
1026     * without increasing the padding. The scrollbars will be overlaid with
1027     * translucency on the view's content.
1028     */
1029    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1030
1031    /**
1032     * The scrollbar style to display the scrollbars inside the padded area,
1033     * increasing the padding of the view. The scrollbars will not overlap the
1034     * content area of the view.
1035     */
1036    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1037
1038    /**
1039     * The scrollbar style to display the scrollbars at the edge of the view,
1040     * without increasing the padding. The scrollbars will be overlaid with
1041     * translucency.
1042     */
1043    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1044
1045    /**
1046     * The scrollbar style to display the scrollbars at the edge of the view,
1047     * increasing the padding of the view. The scrollbars will only overlap the
1048     * background, if any.
1049     */
1050    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1051
1052    /**
1053     * Mask to check if the scrollbar style is overlay or inset.
1054     * {@hide}
1055     */
1056    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1057
1058    /**
1059     * Mask to check if the scrollbar style is inside or outside.
1060     * {@hide}
1061     */
1062    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1063
1064    /**
1065     * Mask for scrollbar style.
1066     * {@hide}
1067     */
1068    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1069
1070    /**
1071     * View flag indicating that the screen should remain on while the
1072     * window containing this view is visible to the user.  This effectively
1073     * takes care of automatically setting the WindowManager's
1074     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1075     */
1076    public static final int KEEP_SCREEN_ON = 0x04000000;
1077
1078    /**
1079     * View flag indicating whether this view should have sound effects enabled
1080     * for events such as clicking and touching.
1081     */
1082    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1083
1084    /**
1085     * View flag indicating whether this view should have haptic feedback
1086     * enabled for events such as long presses.
1087     */
1088    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1089
1090    /**
1091     * <p>Indicates that the view hierarchy should stop saving state when
1092     * it reaches this view.  If state saving is initiated immediately at
1093     * the view, it will be allowed.
1094     * {@hide}
1095     */
1096    static final int PARENT_SAVE_DISABLED = 0x20000000;
1097
1098    /**
1099     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1100     * {@hide}
1101     */
1102    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1103
1104    /** @hide */
1105    @IntDef(flag = true,
1106            value = {
1107                FOCUSABLES_ALL,
1108                FOCUSABLES_TOUCH_MODE
1109            })
1110    @Retention(RetentionPolicy.SOURCE)
1111    public @interface FocusableMode {}
1112
1113    /**
1114     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1115     * should add all focusable Views regardless if they are focusable in touch mode.
1116     */
1117    public static final int FOCUSABLES_ALL = 0x00000000;
1118
1119    /**
1120     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1121     * should add only Views focusable in touch mode.
1122     */
1123    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1124
1125    /** @hide */
1126    @IntDef({
1127            FOCUS_BACKWARD,
1128            FOCUS_FORWARD,
1129            FOCUS_LEFT,
1130            FOCUS_UP,
1131            FOCUS_RIGHT,
1132            FOCUS_DOWN
1133    })
1134    @Retention(RetentionPolicy.SOURCE)
1135    public @interface FocusDirection {}
1136
1137    /** @hide */
1138    @IntDef({
1139            FOCUS_LEFT,
1140            FOCUS_UP,
1141            FOCUS_RIGHT,
1142            FOCUS_DOWN
1143    })
1144    @Retention(RetentionPolicy.SOURCE)
1145    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1146
1147    /**
1148     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1149     * item.
1150     */
1151    public static final int FOCUS_BACKWARD = 0x00000001;
1152
1153    /**
1154     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1155     * item.
1156     */
1157    public static final int FOCUS_FORWARD = 0x00000002;
1158
1159    /**
1160     * Use with {@link #focusSearch(int)}. Move focus to the left.
1161     */
1162    public static final int FOCUS_LEFT = 0x00000011;
1163
1164    /**
1165     * Use with {@link #focusSearch(int)}. Move focus up.
1166     */
1167    public static final int FOCUS_UP = 0x00000021;
1168
1169    /**
1170     * Use with {@link #focusSearch(int)}. Move focus to the right.
1171     */
1172    public static final int FOCUS_RIGHT = 0x00000042;
1173
1174    /**
1175     * Use with {@link #focusSearch(int)}. Move focus down.
1176     */
1177    public static final int FOCUS_DOWN = 0x00000082;
1178
1179    /**
1180     * Bits of {@link #getMeasuredWidthAndState()} and
1181     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1182     */
1183    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1184
1185    /**
1186     * Bits of {@link #getMeasuredWidthAndState()} and
1187     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1188     */
1189    public static final int MEASURED_STATE_MASK = 0xff000000;
1190
1191    /**
1192     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1193     * for functions that combine both width and height into a single int,
1194     * such as {@link #getMeasuredState()} and the childState argument of
1195     * {@link #resolveSizeAndState(int, int, int)}.
1196     */
1197    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1198
1199    /**
1200     * Bit of {@link #getMeasuredWidthAndState()} and
1201     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1202     * is smaller that the space the view would like to have.
1203     */
1204    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1205
1206    /**
1207     * Base View state sets
1208     */
1209    // Singles
1210    /**
1211     * Indicates the view has no states set. 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[] EMPTY_STATE_SET;
1219    /**
1220     * Indicates the view is enabled. 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[] ENABLED_STATE_SET;
1228    /**
1229     * Indicates the view is focused. 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[] FOCUSED_STATE_SET;
1237    /**
1238     * Indicates the view is selected. States are used with
1239     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1240     * view depending on its state.
1241     *
1242     * @see android.graphics.drawable.Drawable
1243     * @see #getDrawableState()
1244     */
1245    protected static final int[] SELECTED_STATE_SET;
1246    /**
1247     * Indicates the view is pressed. States are used with
1248     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1249     * view depending on its state.
1250     *
1251     * @see android.graphics.drawable.Drawable
1252     * @see #getDrawableState()
1253     */
1254    protected static final int[] PRESSED_STATE_SET;
1255    /**
1256     * Indicates the view's window has focus. States are used with
1257     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1258     * view depending on its state.
1259     *
1260     * @see android.graphics.drawable.Drawable
1261     * @see #getDrawableState()
1262     */
1263    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1264    // Doubles
1265    /**
1266     * Indicates the view is enabled and has the focus.
1267     *
1268     * @see #ENABLED_STATE_SET
1269     * @see #FOCUSED_STATE_SET
1270     */
1271    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1272    /**
1273     * Indicates the view is enabled and selected.
1274     *
1275     * @see #ENABLED_STATE_SET
1276     * @see #SELECTED_STATE_SET
1277     */
1278    protected static final int[] ENABLED_SELECTED_STATE_SET;
1279    /**
1280     * Indicates the view is enabled and that its window has focus.
1281     *
1282     * @see #ENABLED_STATE_SET
1283     * @see #WINDOW_FOCUSED_STATE_SET
1284     */
1285    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1286    /**
1287     * Indicates the view is focused and selected.
1288     *
1289     * @see #FOCUSED_STATE_SET
1290     * @see #SELECTED_STATE_SET
1291     */
1292    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1293    /**
1294     * Indicates the view has the focus and that its window has the focus.
1295     *
1296     * @see #FOCUSED_STATE_SET
1297     * @see #WINDOW_FOCUSED_STATE_SET
1298     */
1299    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1300    /**
1301     * Indicates the view is selected and that its window has the focus.
1302     *
1303     * @see #SELECTED_STATE_SET
1304     * @see #WINDOW_FOCUSED_STATE_SET
1305     */
1306    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1307    // Triples
1308    /**
1309     * Indicates the view is enabled, focused and selected.
1310     *
1311     * @see #ENABLED_STATE_SET
1312     * @see #FOCUSED_STATE_SET
1313     * @see #SELECTED_STATE_SET
1314     */
1315    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1316    /**
1317     * Indicates the view is enabled, focused and its window has the focus.
1318     *
1319     * @see #ENABLED_STATE_SET
1320     * @see #FOCUSED_STATE_SET
1321     * @see #WINDOW_FOCUSED_STATE_SET
1322     */
1323    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1324    /**
1325     * Indicates the view is enabled, selected and its window has the focus.
1326     *
1327     * @see #ENABLED_STATE_SET
1328     * @see #SELECTED_STATE_SET
1329     * @see #WINDOW_FOCUSED_STATE_SET
1330     */
1331    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1332    /**
1333     * Indicates the view is focused, selected and its window has the focus.
1334     *
1335     * @see #FOCUSED_STATE_SET
1336     * @see #SELECTED_STATE_SET
1337     * @see #WINDOW_FOCUSED_STATE_SET
1338     */
1339    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1340    /**
1341     * Indicates the view is enabled, focused, selected and its window
1342     * has the focus.
1343     *
1344     * @see #ENABLED_STATE_SET
1345     * @see #FOCUSED_STATE_SET
1346     * @see #SELECTED_STATE_SET
1347     * @see #WINDOW_FOCUSED_STATE_SET
1348     */
1349    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1350    /**
1351     * Indicates the view is pressed and its window has the focus.
1352     *
1353     * @see #PRESSED_STATE_SET
1354     * @see #WINDOW_FOCUSED_STATE_SET
1355     */
1356    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1357    /**
1358     * Indicates the view is pressed and selected.
1359     *
1360     * @see #PRESSED_STATE_SET
1361     * @see #SELECTED_STATE_SET
1362     */
1363    protected static final int[] PRESSED_SELECTED_STATE_SET;
1364    /**
1365     * Indicates the view is pressed, selected and its window has the focus.
1366     *
1367     * @see #PRESSED_STATE_SET
1368     * @see #SELECTED_STATE_SET
1369     * @see #WINDOW_FOCUSED_STATE_SET
1370     */
1371    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1372    /**
1373     * Indicates the view is pressed and focused.
1374     *
1375     * @see #PRESSED_STATE_SET
1376     * @see #FOCUSED_STATE_SET
1377     */
1378    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1379    /**
1380     * Indicates the view is pressed, focused and its window has the focus.
1381     *
1382     * @see #PRESSED_STATE_SET
1383     * @see #FOCUSED_STATE_SET
1384     * @see #WINDOW_FOCUSED_STATE_SET
1385     */
1386    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1387    /**
1388     * Indicates the view is pressed, focused and selected.
1389     *
1390     * @see #PRESSED_STATE_SET
1391     * @see #SELECTED_STATE_SET
1392     * @see #FOCUSED_STATE_SET
1393     */
1394    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1395    /**
1396     * Indicates the view is pressed, focused, selected and its window has the focus.
1397     *
1398     * @see #PRESSED_STATE_SET
1399     * @see #FOCUSED_STATE_SET
1400     * @see #SELECTED_STATE_SET
1401     * @see #WINDOW_FOCUSED_STATE_SET
1402     */
1403    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1404    /**
1405     * Indicates the view is pressed and enabled.
1406     *
1407     * @see #PRESSED_STATE_SET
1408     * @see #ENABLED_STATE_SET
1409     */
1410    protected static final int[] PRESSED_ENABLED_STATE_SET;
1411    /**
1412     * Indicates the view is pressed, enabled and its window has the focus.
1413     *
1414     * @see #PRESSED_STATE_SET
1415     * @see #ENABLED_STATE_SET
1416     * @see #WINDOW_FOCUSED_STATE_SET
1417     */
1418    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1419    /**
1420     * Indicates the view is pressed, enabled and selected.
1421     *
1422     * @see #PRESSED_STATE_SET
1423     * @see #ENABLED_STATE_SET
1424     * @see #SELECTED_STATE_SET
1425     */
1426    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1427    /**
1428     * Indicates the view is pressed, enabled, selected and its window has the
1429     * focus.
1430     *
1431     * @see #PRESSED_STATE_SET
1432     * @see #ENABLED_STATE_SET
1433     * @see #SELECTED_STATE_SET
1434     * @see #WINDOW_FOCUSED_STATE_SET
1435     */
1436    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1437    /**
1438     * Indicates the view is pressed, enabled and focused.
1439     *
1440     * @see #PRESSED_STATE_SET
1441     * @see #ENABLED_STATE_SET
1442     * @see #FOCUSED_STATE_SET
1443     */
1444    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1445    /**
1446     * Indicates the view is pressed, enabled, focused and its window has the
1447     * focus.
1448     *
1449     * @see #PRESSED_STATE_SET
1450     * @see #ENABLED_STATE_SET
1451     * @see #FOCUSED_STATE_SET
1452     * @see #WINDOW_FOCUSED_STATE_SET
1453     */
1454    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1455    /**
1456     * Indicates the view is pressed, enabled, focused and selected.
1457     *
1458     * @see #PRESSED_STATE_SET
1459     * @see #ENABLED_STATE_SET
1460     * @see #SELECTED_STATE_SET
1461     * @see #FOCUSED_STATE_SET
1462     */
1463    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1464    /**
1465     * Indicates the view is pressed, enabled, focused, selected and its window
1466     * has the focus.
1467     *
1468     * @see #PRESSED_STATE_SET
1469     * @see #ENABLED_STATE_SET
1470     * @see #SELECTED_STATE_SET
1471     * @see #FOCUSED_STATE_SET
1472     * @see #WINDOW_FOCUSED_STATE_SET
1473     */
1474    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1475
1476    static {
1477        EMPTY_STATE_SET = StateSet.get(0);
1478
1479        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1480
1481        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1482        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1483                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1484
1485        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1486        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1487                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1488        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1489                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1490        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1491                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1492                        | StateSet.VIEW_STATE_FOCUSED);
1493
1494        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1495        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1496                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1497        ENABLED_SELECTED_STATE_SET = StateSet.get(
1498                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1499        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1500                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1501                        | StateSet.VIEW_STATE_ENABLED);
1502        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1503                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1504        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1505                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1506                        | StateSet.VIEW_STATE_ENABLED);
1507        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1508                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1509                        | StateSet.VIEW_STATE_ENABLED);
1510        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1511                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1512                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1513
1514        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1515        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1516                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1517        PRESSED_SELECTED_STATE_SET = StateSet.get(
1518                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1519        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1520                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1521                        | StateSet.VIEW_STATE_PRESSED);
1522        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1523                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1524        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1525                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1526                        | StateSet.VIEW_STATE_PRESSED);
1527        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1528                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1529                        | StateSet.VIEW_STATE_PRESSED);
1530        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1532                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1533        PRESSED_ENABLED_STATE_SET = StateSet.get(
1534                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1535        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1536                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1537                        | StateSet.VIEW_STATE_PRESSED);
1538        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1539                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1540                        | StateSet.VIEW_STATE_PRESSED);
1541        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1542                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1543                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1544        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1545                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1546                        | StateSet.VIEW_STATE_PRESSED);
1547        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1548                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1549                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1550        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1551                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1552                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1553        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1554                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1555                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1556                        | StateSet.VIEW_STATE_PRESSED);
1557    }
1558
1559    /**
1560     * Accessibility event types that are dispatched for text population.
1561     */
1562    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1563            AccessibilityEvent.TYPE_VIEW_CLICKED
1564            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1565            | AccessibilityEvent.TYPE_VIEW_SELECTED
1566            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1567            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1568            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1569            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1570            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1571            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1572            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1573            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1574
1575    /**
1576     * Temporary Rect currently for use in setBackground().  This will probably
1577     * be extended in the future to hold our own class with more than just
1578     * a Rect. :)
1579     */
1580    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1581
1582    /**
1583     * Map used to store views' tags.
1584     */
1585    private SparseArray<Object> mKeyedTags;
1586
1587    /**
1588     * The next available accessibility id.
1589     */
1590    private static int sNextAccessibilityViewId;
1591
1592    /**
1593     * The animation currently associated with this view.
1594     * @hide
1595     */
1596    protected Animation mCurrentAnimation = null;
1597
1598    /**
1599     * Width as measured during measure pass.
1600     * {@hide}
1601     */
1602    @ViewDebug.ExportedProperty(category = "measurement")
1603    int mMeasuredWidth;
1604
1605    /**
1606     * Height as measured during measure pass.
1607     * {@hide}
1608     */
1609    @ViewDebug.ExportedProperty(category = "measurement")
1610    int mMeasuredHeight;
1611
1612    /**
1613     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1614     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1615     * its display list. This flag, used only when hw accelerated, allows us to clear the
1616     * flag while retaining this information until it's needed (at getDisplayList() time and
1617     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1618     *
1619     * {@hide}
1620     */
1621    boolean mRecreateDisplayList = false;
1622
1623    /**
1624     * The view's identifier.
1625     * {@hide}
1626     *
1627     * @see #setId(int)
1628     * @see #getId()
1629     */
1630    @IdRes
1631    @ViewDebug.ExportedProperty(resolveId = true)
1632    int mID = NO_ID;
1633
1634    /**
1635     * The stable ID of this view for accessibility purposes.
1636     */
1637    int mAccessibilityViewId = NO_ID;
1638
1639    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1640
1641    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1642
1643    /**
1644     * The view's tag.
1645     * {@hide}
1646     *
1647     * @see #setTag(Object)
1648     * @see #getTag()
1649     */
1650    protected Object mTag = null;
1651
1652    // for mPrivateFlags:
1653    /** {@hide} */
1654    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1655    /** {@hide} */
1656    static final int PFLAG_FOCUSED                     = 0x00000002;
1657    /** {@hide} */
1658    static final int PFLAG_SELECTED                    = 0x00000004;
1659    /** {@hide} */
1660    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1661    /** {@hide} */
1662    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1663    /** {@hide} */
1664    static final int PFLAG_DRAWN                       = 0x00000020;
1665    /**
1666     * When this flag is set, this view is running an animation on behalf of its
1667     * children and should therefore not cancel invalidate requests, even if they
1668     * lie outside of this view's bounds.
1669     *
1670     * {@hide}
1671     */
1672    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1673    /** {@hide} */
1674    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1675    /** {@hide} */
1676    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1677    /** {@hide} */
1678    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1679    /** {@hide} */
1680    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1681    /** {@hide} */
1682    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1683    /** {@hide} */
1684    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1685
1686    private static final int PFLAG_PRESSED             = 0x00004000;
1687
1688    /** {@hide} */
1689    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1690    /**
1691     * Flag used to indicate that this view should be drawn once more (and only once
1692     * more) after its animation has completed.
1693     * {@hide}
1694     */
1695    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1696
1697    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1698
1699    /**
1700     * Indicates that the View returned true when onSetAlpha() was called and that
1701     * the alpha must be restored.
1702     * {@hide}
1703     */
1704    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1705
1706    /**
1707     * Set by {@link #setScrollContainer(boolean)}.
1708     */
1709    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1710
1711    /**
1712     * Set by {@link #setScrollContainer(boolean)}.
1713     */
1714    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1715
1716    /**
1717     * View flag indicating whether this view was invalidated (fully or partially.)
1718     *
1719     * @hide
1720     */
1721    static final int PFLAG_DIRTY                       = 0x00200000;
1722
1723    /**
1724     * View flag indicating whether this view was invalidated by an opaque
1725     * invalidate request.
1726     *
1727     * @hide
1728     */
1729    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1730
1731    /**
1732     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1733     *
1734     * @hide
1735     */
1736    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1737
1738    /**
1739     * Indicates whether the background is opaque.
1740     *
1741     * @hide
1742     */
1743    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1744
1745    /**
1746     * Indicates whether the scrollbars are opaque.
1747     *
1748     * @hide
1749     */
1750    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1751
1752    /**
1753     * Indicates whether the view is opaque.
1754     *
1755     * @hide
1756     */
1757    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1758
1759    /**
1760     * Indicates a prepressed state;
1761     * the short time between ACTION_DOWN and recognizing
1762     * a 'real' press. Prepressed is used to recognize quick taps
1763     * even when they are shorter than ViewConfiguration.getTapTimeout().
1764     *
1765     * @hide
1766     */
1767    private static final int PFLAG_PREPRESSED          = 0x02000000;
1768
1769    /**
1770     * Indicates whether the view is temporarily detached.
1771     *
1772     * @hide
1773     */
1774    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1775
1776    /**
1777     * Indicates that we should awaken scroll bars once attached
1778     *
1779     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1780     * during window attachment and it is no longer needed. Feel free to repurpose it.
1781     *
1782     * @hide
1783     */
1784    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1785
1786    /**
1787     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1788     * @hide
1789     */
1790    private static final int PFLAG_HOVERED             = 0x10000000;
1791
1792    /**
1793     * no longer needed, should be reused
1794     */
1795    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1796
1797    /** {@hide} */
1798    static final int PFLAG_ACTIVATED                   = 0x40000000;
1799
1800    /**
1801     * Indicates that this view was specifically invalidated, not just dirtied because some
1802     * child view was invalidated. The flag is used to determine when we need to recreate
1803     * a view's display list (as opposed to just returning a reference to its existing
1804     * display list).
1805     *
1806     * @hide
1807     */
1808    static final int PFLAG_INVALIDATED                 = 0x80000000;
1809
1810    /**
1811     * Masks for mPrivateFlags2, as generated by dumpFlags():
1812     *
1813     * |-------|-------|-------|-------|
1814     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1815     *                                1  PFLAG2_DRAG_HOVERED
1816     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1817     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1818     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1819     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1820     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1821     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1822     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1823     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1824     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1825     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1826     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1827     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1828     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1829     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1830     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1831     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1832     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1833     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1834     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1835     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1836     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1837     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1838     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1839     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1840     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1841     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1842     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1843     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1844     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1845     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1846     *    1                              PFLAG2_PADDING_RESOLVED
1847     *   1                               PFLAG2_DRAWABLE_RESOLVED
1848     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1849     * |-------|-------|-------|-------|
1850     */
1851
1852    /**
1853     * Indicates that this view has reported that it can accept the current drag's content.
1854     * Cleared when the drag operation concludes.
1855     * @hide
1856     */
1857    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1858
1859    /**
1860     * Indicates that this view is currently directly under the drag location in a
1861     * drag-and-drop operation involving content that it can accept.  Cleared when
1862     * the drag exits the view, or when the drag operation concludes.
1863     * @hide
1864     */
1865    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1866
1867    /** @hide */
1868    @IntDef({
1869        LAYOUT_DIRECTION_LTR,
1870        LAYOUT_DIRECTION_RTL,
1871        LAYOUT_DIRECTION_INHERIT,
1872        LAYOUT_DIRECTION_LOCALE
1873    })
1874    @Retention(RetentionPolicy.SOURCE)
1875    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1876    public @interface LayoutDir {}
1877
1878    /** @hide */
1879    @IntDef({
1880        LAYOUT_DIRECTION_LTR,
1881        LAYOUT_DIRECTION_RTL
1882    })
1883    @Retention(RetentionPolicy.SOURCE)
1884    public @interface ResolvedLayoutDir {}
1885
1886    /**
1887     * A flag to indicate that the layout direction of this view has not been defined yet.
1888     * @hide
1889     */
1890    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1891
1892    /**
1893     * Horizontal layout direction of this view is from Left to Right.
1894     * Use with {@link #setLayoutDirection}.
1895     */
1896    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1897
1898    /**
1899     * Horizontal layout direction of this view is from Right to Left.
1900     * Use with {@link #setLayoutDirection}.
1901     */
1902    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1903
1904    /**
1905     * Horizontal layout direction of this view is inherited from its parent.
1906     * Use with {@link #setLayoutDirection}.
1907     */
1908    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1909
1910    /**
1911     * Horizontal layout direction of this view is from deduced from the default language
1912     * script for the locale. Use with {@link #setLayoutDirection}.
1913     */
1914    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1915
1916    /**
1917     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1918     * @hide
1919     */
1920    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1921
1922    /**
1923     * Mask for use with private flags indicating bits used for horizontal layout direction.
1924     * @hide
1925     */
1926    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1927
1928    /**
1929     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1930     * right-to-left direction.
1931     * @hide
1932     */
1933    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1934
1935    /**
1936     * Indicates whether the view horizontal layout direction has been resolved.
1937     * @hide
1938     */
1939    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1940
1941    /**
1942     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1943     * @hide
1944     */
1945    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1946            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1947
1948    /*
1949     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1950     * flag value.
1951     * @hide
1952     */
1953    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1954            LAYOUT_DIRECTION_LTR,
1955            LAYOUT_DIRECTION_RTL,
1956            LAYOUT_DIRECTION_INHERIT,
1957            LAYOUT_DIRECTION_LOCALE
1958    };
1959
1960    /**
1961     * Default horizontal layout direction.
1962     */
1963    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1964
1965    /**
1966     * Default horizontal layout direction.
1967     * @hide
1968     */
1969    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1970
1971    /**
1972     * Text direction is inherited through {@link ViewGroup}
1973     */
1974    public static final int TEXT_DIRECTION_INHERIT = 0;
1975
1976    /**
1977     * Text direction is using "first strong algorithm". The first strong directional character
1978     * determines the paragraph direction. If there is no strong directional character, the
1979     * paragraph direction is the view's resolved layout direction.
1980     */
1981    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1982
1983    /**
1984     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1985     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1986     * If there are neither, the paragraph direction is the view's resolved layout direction.
1987     */
1988    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1989
1990    /**
1991     * Text direction is forced to LTR.
1992     */
1993    public static final int TEXT_DIRECTION_LTR = 3;
1994
1995    /**
1996     * Text direction is forced to RTL.
1997     */
1998    public static final int TEXT_DIRECTION_RTL = 4;
1999
2000    /**
2001     * Text direction is coming from the system Locale.
2002     */
2003    public static final int TEXT_DIRECTION_LOCALE = 5;
2004
2005    /**
2006     * Text direction is using "first strong algorithm". The first strong directional character
2007     * determines the paragraph direction. If there is no strong directional character, the
2008     * paragraph direction is LTR.
2009     */
2010    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2011
2012    /**
2013     * Text direction is using "first strong algorithm". The first strong directional character
2014     * determines the paragraph direction. If there is no strong directional character, the
2015     * paragraph direction is RTL.
2016     */
2017    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2018
2019    /**
2020     * Default text direction is inherited
2021     */
2022    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2023
2024    /**
2025     * Default resolved text direction
2026     * @hide
2027     */
2028    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2029
2030    /**
2031     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2032     * @hide
2033     */
2034    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2035
2036    /**
2037     * Mask for use with private flags indicating bits used for text direction.
2038     * @hide
2039     */
2040    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2041            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2042
2043    /**
2044     * Array of text direction flags for mapping attribute "textDirection" to correct
2045     * flag value.
2046     * @hide
2047     */
2048    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2049            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2050            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2051            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2052            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2053            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2054            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2055            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2056            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2057    };
2058
2059    /**
2060     * Indicates whether the view text direction has been resolved.
2061     * @hide
2062     */
2063    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2064            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2065
2066    /**
2067     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2068     * @hide
2069     */
2070    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2071
2072    /**
2073     * Mask for use with private flags indicating bits used for resolved text direction.
2074     * @hide
2075     */
2076    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2077            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2078
2079    /**
2080     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2081     * @hide
2082     */
2083    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2084            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2085
2086    /** @hide */
2087    @IntDef({
2088        TEXT_ALIGNMENT_INHERIT,
2089        TEXT_ALIGNMENT_GRAVITY,
2090        TEXT_ALIGNMENT_CENTER,
2091        TEXT_ALIGNMENT_TEXT_START,
2092        TEXT_ALIGNMENT_TEXT_END,
2093        TEXT_ALIGNMENT_VIEW_START,
2094        TEXT_ALIGNMENT_VIEW_END
2095    })
2096    @Retention(RetentionPolicy.SOURCE)
2097    public @interface TextAlignment {}
2098
2099    /**
2100     * Default text alignment. The text alignment of this View is inherited from its parent.
2101     * Use with {@link #setTextAlignment(int)}
2102     */
2103    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2104
2105    /**
2106     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2107     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2108     *
2109     * Use with {@link #setTextAlignment(int)}
2110     */
2111    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2112
2113    /**
2114     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2115     *
2116     * Use with {@link #setTextAlignment(int)}
2117     */
2118    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2119
2120    /**
2121     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2122     *
2123     * Use with {@link #setTextAlignment(int)}
2124     */
2125    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2126
2127    /**
2128     * Center the paragraph, e.g. ALIGN_CENTER.
2129     *
2130     * Use with {@link #setTextAlignment(int)}
2131     */
2132    public static final int TEXT_ALIGNMENT_CENTER = 4;
2133
2134    /**
2135     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2136     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2137     *
2138     * Use with {@link #setTextAlignment(int)}
2139     */
2140    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2141
2142    /**
2143     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2144     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2145     *
2146     * Use with {@link #setTextAlignment(int)}
2147     */
2148    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2149
2150    /**
2151     * Default text alignment is inherited
2152     */
2153    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2154
2155    /**
2156     * Default resolved text alignment
2157     * @hide
2158     */
2159    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2160
2161    /**
2162      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2163      * @hide
2164      */
2165    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2166
2167    /**
2168      * Mask for use with private flags indicating bits used for text alignment.
2169      * @hide
2170      */
2171    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2172
2173    /**
2174     * Array of text direction flags for mapping attribute "textAlignment" to correct
2175     * flag value.
2176     * @hide
2177     */
2178    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2179            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2180            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2181            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2182            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2183            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2184            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2185            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2186    };
2187
2188    /**
2189     * Indicates whether the view text alignment has been resolved.
2190     * @hide
2191     */
2192    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2193
2194    /**
2195     * Bit shift to get the resolved text alignment.
2196     * @hide
2197     */
2198    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2199
2200    /**
2201     * Mask for use with private flags indicating bits used for text alignment.
2202     * @hide
2203     */
2204    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2205            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2206
2207    /**
2208     * Indicates whether if the view text alignment has been resolved to gravity
2209     */
2210    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2211            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2212
2213    // Accessiblity constants for mPrivateFlags2
2214
2215    /**
2216     * Shift for the bits in {@link #mPrivateFlags2} related to the
2217     * "importantForAccessibility" attribute.
2218     */
2219    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2220
2221    /**
2222     * Automatically determine whether a view is important for accessibility.
2223     */
2224    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2225
2226    /**
2227     * The view is important for accessibility.
2228     */
2229    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2230
2231    /**
2232     * The view is not important for accessibility.
2233     */
2234    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2235
2236    /**
2237     * The view is not important for accessibility, nor are any of its
2238     * descendant views.
2239     */
2240    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2241
2242    /**
2243     * The default whether the view is important for accessibility.
2244     */
2245    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2246
2247    /**
2248     * Mask for obtainig the bits which specify how to determine
2249     * whether a view is important for accessibility.
2250     */
2251    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2252        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2253        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2254        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2255
2256    /**
2257     * Shift for the bits in {@link #mPrivateFlags2} related to the
2258     * "accessibilityLiveRegion" attribute.
2259     */
2260    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2261
2262    /**
2263     * Live region mode specifying that accessibility services should not
2264     * automatically announce changes to this view. This is the default live
2265     * region mode for most views.
2266     * <p>
2267     * Use with {@link #setAccessibilityLiveRegion(int)}.
2268     */
2269    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2270
2271    /**
2272     * Live region mode specifying that accessibility services should announce
2273     * changes to this view.
2274     * <p>
2275     * Use with {@link #setAccessibilityLiveRegion(int)}.
2276     */
2277    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2278
2279    /**
2280     * Live region mode specifying that accessibility services should interrupt
2281     * ongoing speech to immediately announce changes to this view.
2282     * <p>
2283     * Use with {@link #setAccessibilityLiveRegion(int)}.
2284     */
2285    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2286
2287    /**
2288     * The default whether the view is important for accessibility.
2289     */
2290    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2291
2292    /**
2293     * Mask for obtaining the bits which specify a view's accessibility live
2294     * region mode.
2295     */
2296    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2297            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2298            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2299
2300    /**
2301     * Flag indicating whether a view has accessibility focus.
2302     */
2303    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2304
2305    /**
2306     * Flag whether the accessibility state of the subtree rooted at this view changed.
2307     */
2308    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2309
2310    /**
2311     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2312     * is used to check whether later changes to the view's transform should invalidate the
2313     * view to force the quickReject test to run again.
2314     */
2315    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2316
2317    /**
2318     * Flag indicating that start/end padding has been resolved into left/right padding
2319     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2320     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2321     * during measurement. In some special cases this is required such as when an adapter-based
2322     * view measures prospective children without attaching them to a window.
2323     */
2324    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2325
2326    /**
2327     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2328     */
2329    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2330
2331    /**
2332     * Indicates that the view is tracking some sort of transient state
2333     * that the app should not need to be aware of, but that the framework
2334     * should take special care to preserve.
2335     */
2336    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2337
2338    /**
2339     * Group of bits indicating that RTL properties resolution is done.
2340     */
2341    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2342            PFLAG2_TEXT_DIRECTION_RESOLVED |
2343            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2344            PFLAG2_PADDING_RESOLVED |
2345            PFLAG2_DRAWABLE_RESOLVED;
2346
2347    // There are a couple of flags left in mPrivateFlags2
2348
2349    /* End of masks for mPrivateFlags2 */
2350
2351    /**
2352     * Masks for mPrivateFlags3, as generated by dumpFlags():
2353     *
2354     * |-------|-------|-------|-------|
2355     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2356     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2357     *                               1   PFLAG3_IS_LAID_OUT
2358     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2359     *                             1     PFLAG3_CALLED_SUPER
2360     *                            1      PFLAG3_APPLYING_INSETS
2361     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2362     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2363     *                         1         PFLAG3_ASSIST_BLOCKED
2364     * |-------|-------|-------|-------|
2365     */
2366
2367    /**
2368     * Flag indicating that view has a transform animation set on it. This is used to track whether
2369     * an animation is cleared between successive frames, in order to tell the associated
2370     * DisplayList to clear its animation matrix.
2371     */
2372    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2373
2374    /**
2375     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2376     * animation is cleared between successive frames, in order to tell the associated
2377     * DisplayList to restore its alpha value.
2378     */
2379    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2380
2381    /**
2382     * Flag indicating that the view has been through at least one layout since it
2383     * was last attached to a window.
2384     */
2385    static final int PFLAG3_IS_LAID_OUT = 0x4;
2386
2387    /**
2388     * Flag indicating that a call to measure() was skipped and should be done
2389     * instead when layout() is invoked.
2390     */
2391    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2392
2393    /**
2394     * Flag indicating that an overridden method correctly called down to
2395     * the superclass implementation as required by the API spec.
2396     */
2397    static final int PFLAG3_CALLED_SUPER = 0x10;
2398
2399    /**
2400     * Flag indicating that we're in the process of applying window insets.
2401     */
2402    static final int PFLAG3_APPLYING_INSETS = 0x20;
2403
2404    /**
2405     * Flag indicating that we're in the process of fitting system windows using the old method.
2406     */
2407    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2408
2409    /**
2410     * Flag indicating that nested scrolling is enabled for this view.
2411     * The view will optionally cooperate with views up its parent chain to allow for
2412     * integrated nested scrolling along the same axis.
2413     */
2414    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2415
2416    /**
2417     * Flag indicating that the bottom scroll indicator should be displayed
2418     * when this view can scroll up.
2419     */
2420    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2421
2422    /**
2423     * Flag indicating that the bottom scroll indicator should be displayed
2424     * when this view can scroll down.
2425     */
2426    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2427
2428    /**
2429     * Flag indicating that the left scroll indicator should be displayed
2430     * when this view can scroll left.
2431     */
2432    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2433
2434    /**
2435     * Flag indicating that the right scroll indicator should be displayed
2436     * when this view can scroll right.
2437     */
2438    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2439
2440    /**
2441     * Flag indicating that the start scroll indicator should be displayed
2442     * when this view can scroll in the start direction.
2443     */
2444    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2445
2446    /**
2447     * Flag indicating that the end scroll indicator should be displayed
2448     * when this view can scroll in the end direction.
2449     */
2450    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2451
2452    /* End of masks for mPrivateFlags3 */
2453
2454    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2455
2456    static final int SCROLL_INDICATORS_NONE = 0x0000;
2457
2458    /**
2459     * Mask for use with setFlags indicating bits used for indicating which
2460     * scroll indicators are enabled.
2461     */
2462    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2463            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2464            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2465            | PFLAG3_SCROLL_INDICATOR_END;
2466
2467    /**
2468     * Left-shift required to translate between public scroll indicator flags
2469     * and internal PFLAGS3 flags. When used as a right-shift, translates
2470     * PFLAGS3 flags to public flags.
2471     */
2472    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2473
2474    /** @hide */
2475    @Retention(RetentionPolicy.SOURCE)
2476    @IntDef(flag = true,
2477            value = {
2478                    SCROLL_INDICATOR_TOP,
2479                    SCROLL_INDICATOR_BOTTOM,
2480                    SCROLL_INDICATOR_LEFT,
2481                    SCROLL_INDICATOR_RIGHT,
2482                    SCROLL_INDICATOR_START,
2483                    SCROLL_INDICATOR_END,
2484            })
2485    public @interface ScrollIndicators {}
2486
2487    /**
2488     * Scroll indicator direction for the top edge of the view.
2489     *
2490     * @see #setScrollIndicators(int)
2491     * @see #setScrollIndicators(int, int)
2492     * @see #getScrollIndicators()
2493     */
2494    public static final int SCROLL_INDICATOR_TOP =
2495            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2496
2497    /**
2498     * Scroll indicator direction for the bottom edge of the view.
2499     *
2500     * @see #setScrollIndicators(int)
2501     * @see #setScrollIndicators(int, int)
2502     * @see #getScrollIndicators()
2503     */
2504    public static final int SCROLL_INDICATOR_BOTTOM =
2505            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2506
2507    /**
2508     * Scroll indicator direction for the left edge of the view.
2509     *
2510     * @see #setScrollIndicators(int)
2511     * @see #setScrollIndicators(int, int)
2512     * @see #getScrollIndicators()
2513     */
2514    public static final int SCROLL_INDICATOR_LEFT =
2515            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2516
2517    /**
2518     * Scroll indicator direction for the right edge of the view.
2519     *
2520     * @see #setScrollIndicators(int)
2521     * @see #setScrollIndicators(int, int)
2522     * @see #getScrollIndicators()
2523     */
2524    public static final int SCROLL_INDICATOR_RIGHT =
2525            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2526
2527    /**
2528     * Scroll indicator direction for the starting edge of the view.
2529     * <p>
2530     * Resolved according to the view's layout direction, see
2531     * {@link #getLayoutDirection()} for more information.
2532     *
2533     * @see #setScrollIndicators(int)
2534     * @see #setScrollIndicators(int, int)
2535     * @see #getScrollIndicators()
2536     */
2537    public static final int SCROLL_INDICATOR_START =
2538            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2539
2540    /**
2541     * Scroll indicator direction for the ending edge of the view.
2542     * <p>
2543     * Resolved according to the view's layout direction, see
2544     * {@link #getLayoutDirection()} for more information.
2545     *
2546     * @see #setScrollIndicators(int)
2547     * @see #setScrollIndicators(int, int)
2548     * @see #getScrollIndicators()
2549     */
2550    public static final int SCROLL_INDICATOR_END =
2551            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2552
2553    /**
2554     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2555     * into this view.<p>
2556     */
2557    static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2558
2559    /**
2560     * Always allow a user to over-scroll this view, provided it is a
2561     * view that can scroll.
2562     *
2563     * @see #getOverScrollMode()
2564     * @see #setOverScrollMode(int)
2565     */
2566    public static final int OVER_SCROLL_ALWAYS = 0;
2567
2568    /**
2569     * Allow a user to over-scroll this view only if the content is large
2570     * enough to meaningfully scroll, provided it is a view that can scroll.
2571     *
2572     * @see #getOverScrollMode()
2573     * @see #setOverScrollMode(int)
2574     */
2575    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2576
2577    /**
2578     * Never allow a user to over-scroll this view.
2579     *
2580     * @see #getOverScrollMode()
2581     * @see #setOverScrollMode(int)
2582     */
2583    public static final int OVER_SCROLL_NEVER = 2;
2584
2585    /**
2586     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2587     * requested the system UI (status bar) to be visible (the default).
2588     *
2589     * @see #setSystemUiVisibility(int)
2590     */
2591    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2592
2593    /**
2594     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2595     * system UI to enter an unobtrusive "low profile" mode.
2596     *
2597     * <p>This is for use in games, book readers, video players, or any other
2598     * "immersive" application where the usual system chrome is deemed too distracting.
2599     *
2600     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2601     *
2602     * @see #setSystemUiVisibility(int)
2603     */
2604    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2605
2606    /**
2607     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2608     * system navigation be temporarily hidden.
2609     *
2610     * <p>This is an even less obtrusive state than that called for by
2611     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2612     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2613     * those to disappear. This is useful (in conjunction with the
2614     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2615     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2616     * window flags) for displaying content using every last pixel on the display.
2617     *
2618     * <p>There is a limitation: because navigation controls are so important, the least user
2619     * interaction will cause them to reappear immediately.  When this happens, both
2620     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2621     * so that both elements reappear at the same time.
2622     *
2623     * @see #setSystemUiVisibility(int)
2624     */
2625    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2626
2627    /**
2628     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2629     * into the normal fullscreen mode so that its content can take over the screen
2630     * while still allowing the user to interact with the application.
2631     *
2632     * <p>This has the same visual effect as
2633     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2634     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2635     * meaning that non-critical screen decorations (such as the status bar) will be
2636     * hidden while the user is in the View's window, focusing the experience on
2637     * that content.  Unlike the window flag, if you are using ActionBar in
2638     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2639     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2640     * hide the action bar.
2641     *
2642     * <p>This approach to going fullscreen is best used over the window flag when
2643     * it is a transient state -- that is, the application does this at certain
2644     * points in its user interaction where it wants to allow the user to focus
2645     * on content, but not as a continuous state.  For situations where the application
2646     * would like to simply stay full screen the entire time (such as a game that
2647     * wants to take over the screen), the
2648     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2649     * is usually a better approach.  The state set here will be removed by the system
2650     * in various situations (such as the user moving to another application) like
2651     * the other system UI states.
2652     *
2653     * <p>When using this flag, the application should provide some easy facility
2654     * for the user to go out of it.  A common example would be in an e-book
2655     * reader, where tapping on the screen brings back whatever screen and UI
2656     * decorations that had been hidden while the user was immersed in reading
2657     * the book.
2658     *
2659     * @see #setSystemUiVisibility(int)
2660     */
2661    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2662
2663    /**
2664     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2665     * flags, we would like a stable view of the content insets given to
2666     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2667     * will always represent the worst case that the application can expect
2668     * as a continuous state.  In the stock Android UI this is the space for
2669     * the system bar, nav bar, and status bar, but not more transient elements
2670     * such as an input method.
2671     *
2672     * The stable layout your UI sees is based on the system UI modes you can
2673     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2674     * then you will get a stable layout for changes of the
2675     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2676     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2677     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2678     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2679     * with a stable layout.  (Note that you should avoid using
2680     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2681     *
2682     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2683     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2684     * then a hidden status bar will be considered a "stable" state for purposes
2685     * here.  This allows your UI to continually hide the status bar, while still
2686     * using the system UI flags to hide the action bar while still retaining
2687     * a stable layout.  Note that changing the window fullscreen flag will never
2688     * provide a stable layout for a clean transition.
2689     *
2690     * <p>If you are using ActionBar in
2691     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2692     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2693     * insets it adds to those given to the application.
2694     */
2695    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2696
2697    /**
2698     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2699     * to be laid out as if it has requested
2700     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2701     * allows it to avoid artifacts when switching in and out of that mode, at
2702     * the expense that some of its user interface may be covered by screen
2703     * decorations when they are shown.  You can perform layout of your inner
2704     * UI elements to account for the navigation system UI through the
2705     * {@link #fitSystemWindows(Rect)} method.
2706     */
2707    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2708
2709    /**
2710     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2711     * to be laid out as if it has requested
2712     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2713     * allows it to avoid artifacts when switching in and out of that mode, at
2714     * the expense that some of its user interface may be covered by screen
2715     * decorations when they are shown.  You can perform layout of your inner
2716     * UI elements to account for non-fullscreen system UI through the
2717     * {@link #fitSystemWindows(Rect)} method.
2718     */
2719    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2720
2721    /**
2722     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2723     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2724     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2725     * user interaction.
2726     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2727     * has an effect when used in combination with that flag.</p>
2728     */
2729    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2730
2731    /**
2732     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2733     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2734     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2735     * experience while also hiding the system bars.  If this flag is not set,
2736     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2737     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2738     * if the user swipes from the top of the screen.
2739     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2740     * system gestures, such as swiping from the top of the screen.  These transient system bars
2741     * will overlay app’s content, may have some degree of transparency, and will automatically
2742     * hide after a short timeout.
2743     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2744     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2745     * with one or both of those flags.</p>
2746     */
2747    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2748
2749    /**
2750     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2751     * is compatible with light status bar backgrounds.
2752     *
2753     * <p>For this to take effect, the window must request
2754     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2755     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2756     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2757     *         FLAG_TRANSLUCENT_STATUS}.
2758     *
2759     * @see android.R.attr#windowLightStatusBar
2760     */
2761    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2762
2763    /**
2764     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2765     */
2766    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2767
2768    /**
2769     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2770     */
2771    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2772
2773    /**
2774     * @hide
2775     *
2776     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2777     * out of the public fields to keep the undefined bits out of the developer's way.
2778     *
2779     * Flag to make the status bar not expandable.  Unless you also
2780     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2781     */
2782    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2783
2784    /**
2785     * @hide
2786     *
2787     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2788     * out of the public fields to keep the undefined bits out of the developer's way.
2789     *
2790     * Flag to hide notification icons and scrolling ticker text.
2791     */
2792    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2793
2794    /**
2795     * @hide
2796     *
2797     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2798     * out of the public fields to keep the undefined bits out of the developer's way.
2799     *
2800     * Flag to disable incoming notification alerts.  This will not block
2801     * icons, but it will block sound, vibrating and other visual or aural notifications.
2802     */
2803    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2804
2805    /**
2806     * @hide
2807     *
2808     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2809     * out of the public fields to keep the undefined bits out of the developer's way.
2810     *
2811     * Flag to hide only the scrolling ticker.  Note that
2812     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2813     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2814     */
2815    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2816
2817    /**
2818     * @hide
2819     *
2820     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2821     * out of the public fields to keep the undefined bits out of the developer's way.
2822     *
2823     * Flag to hide the center system info area.
2824     */
2825    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2826
2827    /**
2828     * @hide
2829     *
2830     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2831     * out of the public fields to keep the undefined bits out of the developer's way.
2832     *
2833     * Flag to hide only the home button.  Don't use this
2834     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2835     */
2836    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2837
2838    /**
2839     * @hide
2840     *
2841     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2842     * out of the public fields to keep the undefined bits out of the developer's way.
2843     *
2844     * Flag to hide only the back button. Don't use this
2845     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2846     */
2847    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2848
2849    /**
2850     * @hide
2851     *
2852     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2853     * out of the public fields to keep the undefined bits out of the developer's way.
2854     *
2855     * Flag to hide only the clock.  You might use this if your activity has
2856     * its own clock making the status bar's clock redundant.
2857     */
2858    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2859
2860    /**
2861     * @hide
2862     *
2863     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2864     * out of the public fields to keep the undefined bits out of the developer's way.
2865     *
2866     * Flag to hide only the recent apps button. Don't use this
2867     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2868     */
2869    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2870
2871    /**
2872     * @hide
2873     *
2874     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2875     * out of the public fields to keep the undefined bits out of the developer's way.
2876     *
2877     * Flag to disable the global search gesture. Don't use this
2878     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2879     */
2880    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2881
2882    /**
2883     * @hide
2884     *
2885     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2886     * out of the public fields to keep the undefined bits out of the developer's way.
2887     *
2888     * Flag to specify that the status bar is displayed in transient mode.
2889     */
2890    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2891
2892    /**
2893     * @hide
2894     *
2895     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2896     * out of the public fields to keep the undefined bits out of the developer's way.
2897     *
2898     * Flag to specify that the navigation bar is displayed in transient mode.
2899     */
2900    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2901
2902    /**
2903     * @hide
2904     *
2905     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2906     * out of the public fields to keep the undefined bits out of the developer's way.
2907     *
2908     * Flag to specify that the hidden status bar would like to be shown.
2909     */
2910    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2911
2912    /**
2913     * @hide
2914     *
2915     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2916     * out of the public fields to keep the undefined bits out of the developer's way.
2917     *
2918     * Flag to specify that the hidden navigation bar would like to be shown.
2919     */
2920    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2921
2922    /**
2923     * @hide
2924     *
2925     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2926     * out of the public fields to keep the undefined bits out of the developer's way.
2927     *
2928     * Flag to specify that the status bar is displayed in translucent mode.
2929     */
2930    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2931
2932    /**
2933     * @hide
2934     *
2935     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2936     * out of the public fields to keep the undefined bits out of the developer's way.
2937     *
2938     * Flag to specify that the navigation bar is displayed in translucent mode.
2939     */
2940    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2941
2942    /**
2943     * @hide
2944     *
2945     * Whether Recents is visible or not.
2946     */
2947    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2948
2949    /**
2950     * @hide
2951     *
2952     * Makes system ui transparent.
2953     */
2954    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2955
2956    /**
2957     * @hide
2958     */
2959    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2960
2961    /**
2962     * These are the system UI flags that can be cleared by events outside
2963     * of an application.  Currently this is just the ability to tap on the
2964     * screen while hiding the navigation bar to have it return.
2965     * @hide
2966     */
2967    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2968            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2969            | SYSTEM_UI_FLAG_FULLSCREEN;
2970
2971    /**
2972     * Flags that can impact the layout in relation to system UI.
2973     */
2974    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2975            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2976            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2977
2978    /** @hide */
2979    @IntDef(flag = true,
2980            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2981    @Retention(RetentionPolicy.SOURCE)
2982    public @interface FindViewFlags {}
2983
2984    /**
2985     * Find views that render the specified text.
2986     *
2987     * @see #findViewsWithText(ArrayList, CharSequence, int)
2988     */
2989    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2990
2991    /**
2992     * Find find views that contain the specified content description.
2993     *
2994     * @see #findViewsWithText(ArrayList, CharSequence, int)
2995     */
2996    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2997
2998    /**
2999     * Find views that contain {@link AccessibilityNodeProvider}. Such
3000     * a View is a root of virtual view hierarchy and may contain the searched
3001     * text. If this flag is set Views with providers are automatically
3002     * added and it is a responsibility of the client to call the APIs of
3003     * the provider to determine whether the virtual tree rooted at this View
3004     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3005     * representing the virtual views with this text.
3006     *
3007     * @see #findViewsWithText(ArrayList, CharSequence, int)
3008     *
3009     * @hide
3010     */
3011    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3012
3013    /**
3014     * The undefined cursor position.
3015     *
3016     * @hide
3017     */
3018    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3019
3020    /**
3021     * Indicates that the screen has changed state and is now off.
3022     *
3023     * @see #onScreenStateChanged(int)
3024     */
3025    public static final int SCREEN_STATE_OFF = 0x0;
3026
3027    /**
3028     * Indicates that the screen has changed state and is now on.
3029     *
3030     * @see #onScreenStateChanged(int)
3031     */
3032    public static final int SCREEN_STATE_ON = 0x1;
3033
3034    /**
3035     * Indicates no axis of view scrolling.
3036     */
3037    public static final int SCROLL_AXIS_NONE = 0;
3038
3039    /**
3040     * Indicates scrolling along the horizontal axis.
3041     */
3042    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3043
3044    /**
3045     * Indicates scrolling along the vertical axis.
3046     */
3047    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3048
3049    /**
3050     * Controls the over-scroll mode for this view.
3051     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3052     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3053     * and {@link #OVER_SCROLL_NEVER}.
3054     */
3055    private int mOverScrollMode;
3056
3057    /**
3058     * The parent this view is attached to.
3059     * {@hide}
3060     *
3061     * @see #getParent()
3062     */
3063    protected ViewParent mParent;
3064
3065    /**
3066     * {@hide}
3067     */
3068    AttachInfo mAttachInfo;
3069
3070    /**
3071     * {@hide}
3072     */
3073    @ViewDebug.ExportedProperty(flagMapping = {
3074        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3075                name = "FORCE_LAYOUT"),
3076        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3077                name = "LAYOUT_REQUIRED"),
3078        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3079            name = "DRAWING_CACHE_INVALID", outputIf = false),
3080        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3081        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3082        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3083        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3084    }, formatToHexString = true)
3085    int mPrivateFlags;
3086    int mPrivateFlags2;
3087    int mPrivateFlags3;
3088
3089    /**
3090     * This view's request for the visibility of the status bar.
3091     * @hide
3092     */
3093    @ViewDebug.ExportedProperty(flagMapping = {
3094        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3095                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3096                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3097        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3098                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3099                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3100        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3101                                equals = SYSTEM_UI_FLAG_VISIBLE,
3102                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3103    }, formatToHexString = true)
3104    int mSystemUiVisibility;
3105
3106    /**
3107     * Reference count for transient state.
3108     * @see #setHasTransientState(boolean)
3109     */
3110    int mTransientStateCount = 0;
3111
3112    /**
3113     * Count of how many windows this view has been attached to.
3114     */
3115    int mWindowAttachCount;
3116
3117    /**
3118     * The layout parameters associated with this view and used by the parent
3119     * {@link android.view.ViewGroup} to determine how this view should be
3120     * laid out.
3121     * {@hide}
3122     */
3123    protected ViewGroup.LayoutParams mLayoutParams;
3124
3125    /**
3126     * The view flags hold various views states.
3127     * {@hide}
3128     */
3129    @ViewDebug.ExportedProperty(formatToHexString = true)
3130    int mViewFlags;
3131
3132    static class TransformationInfo {
3133        /**
3134         * The transform matrix for the View. This transform is calculated internally
3135         * based on the translation, rotation, and scale properties.
3136         *
3137         * Do *not* use this variable directly; instead call getMatrix(), which will
3138         * load the value from the View's RenderNode.
3139         */
3140        private final Matrix mMatrix = new Matrix();
3141
3142        /**
3143         * The inverse transform matrix for the View. This transform is calculated
3144         * internally based on the translation, rotation, and scale properties.
3145         *
3146         * Do *not* use this variable directly; instead call getInverseMatrix(),
3147         * which will load the value from the View's RenderNode.
3148         */
3149        private Matrix mInverseMatrix;
3150
3151        /**
3152         * The opacity of the View. This is a value from 0 to 1, where 0 means
3153         * completely transparent and 1 means completely opaque.
3154         */
3155        @ViewDebug.ExportedProperty
3156        float mAlpha = 1f;
3157
3158        /**
3159         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3160         * property only used by transitions, which is composited with the other alpha
3161         * values to calculate the final visual alpha value.
3162         */
3163        float mTransitionAlpha = 1f;
3164    }
3165
3166    TransformationInfo mTransformationInfo;
3167
3168    /**
3169     * Current clip bounds. to which all drawing of this view are constrained.
3170     */
3171    Rect mClipBounds = null;
3172
3173    private boolean mLastIsOpaque;
3174
3175    /**
3176     * The distance in pixels from the left edge of this view's parent
3177     * to the left edge of this view.
3178     * {@hide}
3179     */
3180    @ViewDebug.ExportedProperty(category = "layout")
3181    protected int mLeft;
3182    /**
3183     * The distance in pixels from the left edge of this view's parent
3184     * to the right edge of this view.
3185     * {@hide}
3186     */
3187    @ViewDebug.ExportedProperty(category = "layout")
3188    protected int mRight;
3189    /**
3190     * The distance in pixels from the top edge of this view's parent
3191     * to the top edge of this view.
3192     * {@hide}
3193     */
3194    @ViewDebug.ExportedProperty(category = "layout")
3195    protected int mTop;
3196    /**
3197     * The distance in pixels from the top edge of this view's parent
3198     * to the bottom edge of this view.
3199     * {@hide}
3200     */
3201    @ViewDebug.ExportedProperty(category = "layout")
3202    protected int mBottom;
3203
3204    /**
3205     * The offset, in pixels, by which the content of this view is scrolled
3206     * horizontally.
3207     * {@hide}
3208     */
3209    @ViewDebug.ExportedProperty(category = "scrolling")
3210    protected int mScrollX;
3211    /**
3212     * The offset, in pixels, by which the content of this view is scrolled
3213     * vertically.
3214     * {@hide}
3215     */
3216    @ViewDebug.ExportedProperty(category = "scrolling")
3217    protected int mScrollY;
3218
3219    /**
3220     * The left padding in pixels, that is the distance in pixels between the
3221     * left edge of this view and the left edge of its content.
3222     * {@hide}
3223     */
3224    @ViewDebug.ExportedProperty(category = "padding")
3225    protected int mPaddingLeft = 0;
3226    /**
3227     * The right padding in pixels, that is the distance in pixels between the
3228     * right edge of this view and the right edge of its content.
3229     * {@hide}
3230     */
3231    @ViewDebug.ExportedProperty(category = "padding")
3232    protected int mPaddingRight = 0;
3233    /**
3234     * The top padding in pixels, that is the distance in pixels between the
3235     * top edge of this view and the top edge of its content.
3236     * {@hide}
3237     */
3238    @ViewDebug.ExportedProperty(category = "padding")
3239    protected int mPaddingTop;
3240    /**
3241     * The bottom padding in pixels, that is the distance in pixels between the
3242     * bottom edge of this view and the bottom edge of its content.
3243     * {@hide}
3244     */
3245    @ViewDebug.ExportedProperty(category = "padding")
3246    protected int mPaddingBottom;
3247
3248    /**
3249     * The layout insets in pixels, that is the distance in pixels between the
3250     * visible edges of this view its bounds.
3251     */
3252    private Insets mLayoutInsets;
3253
3254    /**
3255     * Briefly describes the view and is primarily used for accessibility support.
3256     */
3257    private CharSequence mContentDescription;
3258
3259    /**
3260     * Specifies the id of a view for which this view serves as a label for
3261     * accessibility purposes.
3262     */
3263    private int mLabelForId = View.NO_ID;
3264
3265    /**
3266     * Predicate for matching labeled view id with its label for
3267     * accessibility purposes.
3268     */
3269    private MatchLabelForPredicate mMatchLabelForPredicate;
3270
3271    /**
3272     * Specifies a view before which this one is visited in accessibility traversal.
3273     */
3274    private int mAccessibilityTraversalBeforeId = NO_ID;
3275
3276    /**
3277     * Specifies a view after which this one is visited in accessibility traversal.
3278     */
3279    private int mAccessibilityTraversalAfterId = NO_ID;
3280
3281    /**
3282     * Predicate for matching a view by its id.
3283     */
3284    private MatchIdPredicate mMatchIdPredicate;
3285
3286    /**
3287     * Cache the paddingRight set by the user to append to the scrollbar's size.
3288     *
3289     * @hide
3290     */
3291    @ViewDebug.ExportedProperty(category = "padding")
3292    protected int mUserPaddingRight;
3293
3294    /**
3295     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3296     *
3297     * @hide
3298     */
3299    @ViewDebug.ExportedProperty(category = "padding")
3300    protected int mUserPaddingBottom;
3301
3302    /**
3303     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3304     *
3305     * @hide
3306     */
3307    @ViewDebug.ExportedProperty(category = "padding")
3308    protected int mUserPaddingLeft;
3309
3310    /**
3311     * Cache the paddingStart set by the user to append to the scrollbar's size.
3312     *
3313     */
3314    @ViewDebug.ExportedProperty(category = "padding")
3315    int mUserPaddingStart;
3316
3317    /**
3318     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3319     *
3320     */
3321    @ViewDebug.ExportedProperty(category = "padding")
3322    int mUserPaddingEnd;
3323
3324    /**
3325     * Cache initial left padding.
3326     *
3327     * @hide
3328     */
3329    int mUserPaddingLeftInitial;
3330
3331    /**
3332     * Cache initial right padding.
3333     *
3334     * @hide
3335     */
3336    int mUserPaddingRightInitial;
3337
3338    /**
3339     * Default undefined padding
3340     */
3341    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3342
3343    /**
3344     * Cache if a left padding has been defined
3345     */
3346    private boolean mLeftPaddingDefined = false;
3347
3348    /**
3349     * Cache if a right padding has been defined
3350     */
3351    private boolean mRightPaddingDefined = false;
3352
3353    /**
3354     * @hide
3355     */
3356    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3357    /**
3358     * @hide
3359     */
3360    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3361
3362    private LongSparseLongArray mMeasureCache;
3363
3364    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3365    private Drawable mBackground;
3366    private TintInfo mBackgroundTint;
3367
3368    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3369    private ForegroundInfo mForegroundInfo;
3370
3371    private Drawable mScrollIndicatorDrawable;
3372
3373    /**
3374     * RenderNode used for backgrounds.
3375     * <p>
3376     * When non-null and valid, this is expected to contain an up-to-date copy
3377     * of the background drawable. It is cleared on temporary detach, and reset
3378     * on cleanup.
3379     */
3380    private RenderNode mBackgroundRenderNode;
3381
3382    private int mBackgroundResource;
3383    private boolean mBackgroundSizeChanged;
3384
3385    private String mTransitionName;
3386
3387    static class TintInfo {
3388        ColorStateList mTintList;
3389        PorterDuff.Mode mTintMode;
3390        boolean mHasTintMode;
3391        boolean mHasTintList;
3392    }
3393
3394    private static class ForegroundInfo {
3395        private Drawable mDrawable;
3396        private TintInfo mTintInfo;
3397        private int mGravity = Gravity.FILL;
3398        private boolean mInsidePadding = true;
3399        private boolean mBoundsChanged = true;
3400        private final Rect mSelfBounds = new Rect();
3401        private final Rect mOverlayBounds = new Rect();
3402    }
3403
3404    static class ListenerInfo {
3405        /**
3406         * Listener used to dispatch focus change events.
3407         * This field should be made private, so it is hidden from the SDK.
3408         * {@hide}
3409         */
3410        protected OnFocusChangeListener mOnFocusChangeListener;
3411
3412        /**
3413         * Listeners for layout change events.
3414         */
3415        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3416
3417        protected OnScrollChangeListener mOnScrollChangeListener;
3418
3419        /**
3420         * Listeners for attach events.
3421         */
3422        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3423
3424        /**
3425         * Listener used to dispatch click events.
3426         * This field should be made private, so it is hidden from the SDK.
3427         * {@hide}
3428         */
3429        public OnClickListener mOnClickListener;
3430
3431        /**
3432         * Listener used to dispatch long click events.
3433         * This field should be made private, so it is hidden from the SDK.
3434         * {@hide}
3435         */
3436        protected OnLongClickListener mOnLongClickListener;
3437
3438        /**
3439         * Listener used to dispatch context click events. This field should be made private, so it
3440         * is hidden from the SDK.
3441         * {@hide}
3442         */
3443        protected OnContextClickListener mOnContextClickListener;
3444
3445        /**
3446         * Listener used to build the context menu.
3447         * This field should be made private, so it is hidden from the SDK.
3448         * {@hide}
3449         */
3450        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3451
3452        private OnKeyListener mOnKeyListener;
3453
3454        private OnTouchListener mOnTouchListener;
3455
3456        private OnHoverListener mOnHoverListener;
3457
3458        private OnGenericMotionListener mOnGenericMotionListener;
3459
3460        private OnDragListener mOnDragListener;
3461
3462        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3463
3464        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3465    }
3466
3467    ListenerInfo mListenerInfo;
3468
3469    /**
3470     * The application environment this view lives in.
3471     * This field should be made private, so it is hidden from the SDK.
3472     * {@hide}
3473     */
3474    @ViewDebug.ExportedProperty(deepExport = true)
3475    protected Context mContext;
3476
3477    private final Resources mResources;
3478
3479    private ScrollabilityCache mScrollCache;
3480
3481    private int[] mDrawableState = null;
3482
3483    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3484
3485    /**
3486     * Animator that automatically runs based on state changes.
3487     */
3488    private StateListAnimator mStateListAnimator;
3489
3490    /**
3491     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3492     * the user may specify which view to go to next.
3493     */
3494    private int mNextFocusLeftId = View.NO_ID;
3495
3496    /**
3497     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3498     * the user may specify which view to go to next.
3499     */
3500    private int mNextFocusRightId = View.NO_ID;
3501
3502    /**
3503     * When this view has focus and the next focus is {@link #FOCUS_UP},
3504     * the user may specify which view to go to next.
3505     */
3506    private int mNextFocusUpId = View.NO_ID;
3507
3508    /**
3509     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3510     * the user may specify which view to go to next.
3511     */
3512    private int mNextFocusDownId = View.NO_ID;
3513
3514    /**
3515     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3516     * the user may specify which view to go to next.
3517     */
3518    int mNextFocusForwardId = View.NO_ID;
3519
3520    private CheckForLongPress mPendingCheckForLongPress;
3521    private CheckForTap mPendingCheckForTap = null;
3522    private PerformClick mPerformClick;
3523    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3524
3525    private UnsetPressedState mUnsetPressedState;
3526
3527    /**
3528     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3529     * up event while a long press is invoked as soon as the long press duration is reached, so
3530     * a long press could be performed before the tap is checked, in which case the tap's action
3531     * should not be invoked.
3532     */
3533    private boolean mHasPerformedLongPress;
3534
3535    /**
3536     * Whether a context click button is currently pressed down. This is true when the stylus is
3537     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3538     * pressed. This is false once the button is released or if the stylus has been lifted.
3539     */
3540    private boolean mInContextButtonPress;
3541
3542    /**
3543     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3544     * true after a stylus button press has occured, when the next up event should not be recognized
3545     * as a tap.
3546     */
3547    private boolean mIgnoreNextUpEvent;
3548
3549    /**
3550     * The minimum height of the view. We'll try our best to have the height
3551     * of this view to at least this amount.
3552     */
3553    @ViewDebug.ExportedProperty(category = "measurement")
3554    private int mMinHeight;
3555
3556    /**
3557     * The minimum width of the view. We'll try our best to have the width
3558     * of this view to at least this amount.
3559     */
3560    @ViewDebug.ExportedProperty(category = "measurement")
3561    private int mMinWidth;
3562
3563    /**
3564     * The delegate to handle touch events that are physically in this view
3565     * but should be handled by another view.
3566     */
3567    private TouchDelegate mTouchDelegate = null;
3568
3569    /**
3570     * Solid color to use as a background when creating the drawing cache. Enables
3571     * the cache to use 16 bit bitmaps instead of 32 bit.
3572     */
3573    private int mDrawingCacheBackgroundColor = 0;
3574
3575    /**
3576     * Special tree observer used when mAttachInfo is null.
3577     */
3578    private ViewTreeObserver mFloatingTreeObserver;
3579
3580    /**
3581     * Cache the touch slop from the context that created the view.
3582     */
3583    private int mTouchSlop;
3584
3585    /**
3586     * Object that handles automatic animation of view properties.
3587     */
3588    private ViewPropertyAnimator mAnimator = null;
3589
3590    /**
3591     * Flag indicating that a drag can cross window boundaries.  When
3592     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3593     * with this flag set, all visible applications will be able to participate
3594     * in the drag operation and receive the dragged content.
3595     *
3596     * @hide
3597     */
3598    public static final int DRAG_FLAG_GLOBAL = 1;
3599
3600    /**
3601     * Flag indicating that the drag shadow will be opaque.  When
3602     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3603     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3604     */
3605    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3606
3607    /**
3608     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3609     */
3610    private float mVerticalScrollFactor;
3611
3612    /**
3613     * Position of the vertical scroll bar.
3614     */
3615    private int mVerticalScrollbarPosition;
3616
3617    /**
3618     * Position the scroll bar at the default position as determined by the system.
3619     */
3620    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3621
3622    /**
3623     * Position the scroll bar along the left edge.
3624     */
3625    public static final int SCROLLBAR_POSITION_LEFT = 1;
3626
3627    /**
3628     * Position the scroll bar along the right edge.
3629     */
3630    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3631
3632    /**
3633     * Indicates that the view does not have a layer.
3634     *
3635     * @see #getLayerType()
3636     * @see #setLayerType(int, android.graphics.Paint)
3637     * @see #LAYER_TYPE_SOFTWARE
3638     * @see #LAYER_TYPE_HARDWARE
3639     */
3640    public static final int LAYER_TYPE_NONE = 0;
3641
3642    /**
3643     * <p>Indicates that the view has a software layer. A software layer is backed
3644     * by a bitmap and causes the view to be rendered using Android's software
3645     * rendering pipeline, even if hardware acceleration is enabled.</p>
3646     *
3647     * <p>Software layers have various usages:</p>
3648     * <p>When the application is not using hardware acceleration, a software layer
3649     * is useful to apply a specific color filter and/or blending mode and/or
3650     * translucency to a view and all its children.</p>
3651     * <p>When the application is using hardware acceleration, a software layer
3652     * is useful to render drawing primitives not supported by the hardware
3653     * accelerated pipeline. It can also be used to cache a complex view tree
3654     * into a texture and reduce the complexity of drawing operations. For instance,
3655     * when animating a complex view tree with a translation, a software layer can
3656     * be used to render the view tree only once.</p>
3657     * <p>Software layers should be avoided when the affected view tree updates
3658     * often. Every update will require to re-render the software layer, which can
3659     * potentially be slow (particularly when hardware acceleration is turned on
3660     * since the layer will have to be uploaded into a hardware texture after every
3661     * update.)</p>
3662     *
3663     * @see #getLayerType()
3664     * @see #setLayerType(int, android.graphics.Paint)
3665     * @see #LAYER_TYPE_NONE
3666     * @see #LAYER_TYPE_HARDWARE
3667     */
3668    public static final int LAYER_TYPE_SOFTWARE = 1;
3669
3670    /**
3671     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3672     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3673     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3674     * rendering pipeline, but only if hardware acceleration is turned on for the
3675     * view hierarchy. When hardware acceleration is turned off, hardware layers
3676     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3677     *
3678     * <p>A hardware layer is useful to apply a specific color filter and/or
3679     * blending mode and/or translucency to a view and all its children.</p>
3680     * <p>A hardware layer can be used to cache a complex view tree into a
3681     * texture and reduce the complexity of drawing operations. For instance,
3682     * when animating a complex view tree with a translation, a hardware layer can
3683     * be used to render the view tree only once.</p>
3684     * <p>A hardware layer can also be used to increase the rendering quality when
3685     * rotation transformations are applied on a view. It can also be used to
3686     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3687     *
3688     * @see #getLayerType()
3689     * @see #setLayerType(int, android.graphics.Paint)
3690     * @see #LAYER_TYPE_NONE
3691     * @see #LAYER_TYPE_SOFTWARE
3692     */
3693    public static final int LAYER_TYPE_HARDWARE = 2;
3694
3695    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3696            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3697            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3698            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3699    })
3700    int mLayerType = LAYER_TYPE_NONE;
3701    Paint mLayerPaint;
3702
3703    /**
3704     * Set to true when drawing cache is enabled and cannot be created.
3705     *
3706     * @hide
3707     */
3708    public boolean mCachingFailed;
3709    private Bitmap mDrawingCache;
3710    private Bitmap mUnscaledDrawingCache;
3711
3712    /**
3713     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3714     * <p>
3715     * When non-null and valid, this is expected to contain an up-to-date copy
3716     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3717     * cleanup.
3718     */
3719    final RenderNode mRenderNode;
3720
3721    /**
3722     * Set to true when the view is sending hover accessibility events because it
3723     * is the innermost hovered view.
3724     */
3725    private boolean mSendingHoverAccessibilityEvents;
3726
3727    /**
3728     * Delegate for injecting accessibility functionality.
3729     */
3730    AccessibilityDelegate mAccessibilityDelegate;
3731
3732    /**
3733     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3734     * and add/remove objects to/from the overlay directly through the Overlay methods.
3735     */
3736    ViewOverlay mOverlay;
3737
3738    /**
3739     * The currently active parent view for receiving delegated nested scrolling events.
3740     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3741     * by {@link #stopNestedScroll()} at the same point where we clear
3742     * requestDisallowInterceptTouchEvent.
3743     */
3744    private ViewParent mNestedScrollingParent;
3745
3746    /**
3747     * Consistency verifier for debugging purposes.
3748     * @hide
3749     */
3750    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3751            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3752                    new InputEventConsistencyVerifier(this, 0) : null;
3753
3754    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3755
3756    private int[] mTempNestedScrollConsumed;
3757
3758    /**
3759     * An overlay is going to draw this View instead of being drawn as part of this
3760     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3761     * when this view is invalidated.
3762     */
3763    GhostView mGhostView;
3764
3765    /**
3766     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3767     * @hide
3768     */
3769    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3770    public String[] mAttributes;
3771
3772    /**
3773     * Maps a Resource id to its name.
3774     */
3775    private static SparseArray<String> mAttributeMap;
3776
3777    /**
3778     * @hide
3779     */
3780    String mStartActivityRequestWho;
3781
3782    /**
3783     * Simple constructor to use when creating a view from code.
3784     *
3785     * @param context The Context the view is running in, through which it can
3786     *        access the current theme, resources, etc.
3787     */
3788    public View(Context context) {
3789        mContext = context;
3790        mResources = context != null ? context.getResources() : null;
3791        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3792        // Set some flags defaults
3793        mPrivateFlags2 =
3794                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3795                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3796                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3797                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3798                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3799                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3800        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3801        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3802        mUserPaddingStart = UNDEFINED_PADDING;
3803        mUserPaddingEnd = UNDEFINED_PADDING;
3804        mRenderNode = RenderNode.create(getClass().getName(), this);
3805
3806        if (!sCompatibilityDone && context != null) {
3807            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3808
3809            // Older apps may need this compatibility hack for measurement.
3810            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3811
3812            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3813            // of whether a layout was requested on that View.
3814            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3815
3816            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3817
3818            // In M and newer, our widgets can pass a "hint" value in the size
3819            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3820            // know what the expected parent size is going to be, so e.g. list items can size
3821            // themselves at 1/3 the size of their container. It breaks older apps though,
3822            // specifically apps that use some popular open source libraries.
3823            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3824
3825            // Old versions of the platform would give different results from
3826            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
3827            // modes, so we always need to run an additional EXACTLY pass.
3828            sAlwaysRemeasureExactly = targetSdkVersion <= M;
3829
3830            sCompatibilityDone = true;
3831        }
3832    }
3833
3834    /**
3835     * Constructor that is called when inflating a view from XML. This is called
3836     * when a view is being constructed from an XML file, supplying attributes
3837     * that were specified in the XML file. This version uses a default style of
3838     * 0, so the only attribute values applied are those in the Context's Theme
3839     * and the given AttributeSet.
3840     *
3841     * <p>
3842     * The method onFinishInflate() will be called after all children have been
3843     * added.
3844     *
3845     * @param context The Context the view is running in, through which it can
3846     *        access the current theme, resources, etc.
3847     * @param attrs The attributes of the XML tag that is inflating the view.
3848     * @see #View(Context, AttributeSet, int)
3849     */
3850    public View(Context context, @Nullable AttributeSet attrs) {
3851        this(context, attrs, 0);
3852    }
3853
3854    /**
3855     * Perform inflation from XML and apply a class-specific base style from a
3856     * theme attribute. This constructor of View allows subclasses to use their
3857     * own base style when they are inflating. For example, a Button class's
3858     * constructor would call this version of the super class constructor and
3859     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3860     * allows the theme's button style to modify all of the base view attributes
3861     * (in particular its background) as well as the Button class's attributes.
3862     *
3863     * @param context The Context the view is running in, through which it can
3864     *        access the current theme, resources, etc.
3865     * @param attrs The attributes of the XML tag that is inflating the view.
3866     * @param defStyleAttr An attribute in the current theme that contains a
3867     *        reference to a style resource that supplies default values for
3868     *        the view. Can be 0 to not look for defaults.
3869     * @see #View(Context, AttributeSet)
3870     */
3871    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3872        this(context, attrs, defStyleAttr, 0);
3873    }
3874
3875    /**
3876     * Perform inflation from XML and apply a class-specific base style from a
3877     * theme attribute or style resource. This constructor of View allows
3878     * subclasses to use their own base style when they are inflating.
3879     * <p>
3880     * When determining the final value of a particular attribute, there are
3881     * four inputs that come into play:
3882     * <ol>
3883     * <li>Any attribute values in the given AttributeSet.
3884     * <li>The style resource specified in the AttributeSet (named "style").
3885     * <li>The default style specified by <var>defStyleAttr</var>.
3886     * <li>The default style specified by <var>defStyleRes</var>.
3887     * <li>The base values in this theme.
3888     * </ol>
3889     * <p>
3890     * Each of these inputs is considered in-order, with the first listed taking
3891     * precedence over the following ones. In other words, if in the
3892     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3893     * , then the button's text will <em>always</em> be black, regardless of
3894     * what is specified in any of the styles.
3895     *
3896     * @param context The Context the view is running in, through which it can
3897     *        access the current theme, resources, etc.
3898     * @param attrs The attributes of the XML tag that is inflating the view.
3899     * @param defStyleAttr An attribute in the current theme that contains a
3900     *        reference to a style resource that supplies default values for
3901     *        the view. Can be 0 to not look for defaults.
3902     * @param defStyleRes A resource identifier of a style resource that
3903     *        supplies default values for the view, used only if
3904     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3905     *        to not look for defaults.
3906     * @see #View(Context, AttributeSet, int)
3907     */
3908    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3909        this(context);
3910
3911        final TypedArray a = context.obtainStyledAttributes(
3912                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3913
3914        if (mDebugViewAttributes) {
3915            saveAttributeData(attrs, a);
3916        }
3917
3918        Drawable background = null;
3919
3920        int leftPadding = -1;
3921        int topPadding = -1;
3922        int rightPadding = -1;
3923        int bottomPadding = -1;
3924        int startPadding = UNDEFINED_PADDING;
3925        int endPadding = UNDEFINED_PADDING;
3926
3927        int padding = -1;
3928
3929        int viewFlagValues = 0;
3930        int viewFlagMasks = 0;
3931
3932        boolean setScrollContainer = false;
3933
3934        int x = 0;
3935        int y = 0;
3936
3937        float tx = 0;
3938        float ty = 0;
3939        float tz = 0;
3940        float elevation = 0;
3941        float rotation = 0;
3942        float rotationX = 0;
3943        float rotationY = 0;
3944        float sx = 1f;
3945        float sy = 1f;
3946        boolean transformSet = false;
3947
3948        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3949        int overScrollMode = mOverScrollMode;
3950        boolean initializeScrollbars = false;
3951        boolean initializeScrollIndicators = false;
3952
3953        boolean startPaddingDefined = false;
3954        boolean endPaddingDefined = false;
3955        boolean leftPaddingDefined = false;
3956        boolean rightPaddingDefined = false;
3957
3958        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3959
3960        final int N = a.getIndexCount();
3961        for (int i = 0; i < N; i++) {
3962            int attr = a.getIndex(i);
3963            switch (attr) {
3964                case com.android.internal.R.styleable.View_background:
3965                    background = a.getDrawable(attr);
3966                    break;
3967                case com.android.internal.R.styleable.View_padding:
3968                    padding = a.getDimensionPixelSize(attr, -1);
3969                    mUserPaddingLeftInitial = padding;
3970                    mUserPaddingRightInitial = padding;
3971                    leftPaddingDefined = true;
3972                    rightPaddingDefined = true;
3973                    break;
3974                 case com.android.internal.R.styleable.View_paddingLeft:
3975                    leftPadding = a.getDimensionPixelSize(attr, -1);
3976                    mUserPaddingLeftInitial = leftPadding;
3977                    leftPaddingDefined = true;
3978                    break;
3979                case com.android.internal.R.styleable.View_paddingTop:
3980                    topPadding = a.getDimensionPixelSize(attr, -1);
3981                    break;
3982                case com.android.internal.R.styleable.View_paddingRight:
3983                    rightPadding = a.getDimensionPixelSize(attr, -1);
3984                    mUserPaddingRightInitial = rightPadding;
3985                    rightPaddingDefined = true;
3986                    break;
3987                case com.android.internal.R.styleable.View_paddingBottom:
3988                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3989                    break;
3990                case com.android.internal.R.styleable.View_paddingStart:
3991                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3992                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3993                    break;
3994                case com.android.internal.R.styleable.View_paddingEnd:
3995                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3996                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3997                    break;
3998                case com.android.internal.R.styleable.View_scrollX:
3999                    x = a.getDimensionPixelOffset(attr, 0);
4000                    break;
4001                case com.android.internal.R.styleable.View_scrollY:
4002                    y = a.getDimensionPixelOffset(attr, 0);
4003                    break;
4004                case com.android.internal.R.styleable.View_alpha:
4005                    setAlpha(a.getFloat(attr, 1f));
4006                    break;
4007                case com.android.internal.R.styleable.View_transformPivotX:
4008                    setPivotX(a.getDimensionPixelOffset(attr, 0));
4009                    break;
4010                case com.android.internal.R.styleable.View_transformPivotY:
4011                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4012                    break;
4013                case com.android.internal.R.styleable.View_translationX:
4014                    tx = a.getDimensionPixelOffset(attr, 0);
4015                    transformSet = true;
4016                    break;
4017                case com.android.internal.R.styleable.View_translationY:
4018                    ty = a.getDimensionPixelOffset(attr, 0);
4019                    transformSet = true;
4020                    break;
4021                case com.android.internal.R.styleable.View_translationZ:
4022                    tz = a.getDimensionPixelOffset(attr, 0);
4023                    transformSet = true;
4024                    break;
4025                case com.android.internal.R.styleable.View_elevation:
4026                    elevation = a.getDimensionPixelOffset(attr, 0);
4027                    transformSet = true;
4028                    break;
4029                case com.android.internal.R.styleable.View_rotation:
4030                    rotation = a.getFloat(attr, 0);
4031                    transformSet = true;
4032                    break;
4033                case com.android.internal.R.styleable.View_rotationX:
4034                    rotationX = a.getFloat(attr, 0);
4035                    transformSet = true;
4036                    break;
4037                case com.android.internal.R.styleable.View_rotationY:
4038                    rotationY = a.getFloat(attr, 0);
4039                    transformSet = true;
4040                    break;
4041                case com.android.internal.R.styleable.View_scaleX:
4042                    sx = a.getFloat(attr, 1f);
4043                    transformSet = true;
4044                    break;
4045                case com.android.internal.R.styleable.View_scaleY:
4046                    sy = a.getFloat(attr, 1f);
4047                    transformSet = true;
4048                    break;
4049                case com.android.internal.R.styleable.View_id:
4050                    mID = a.getResourceId(attr, NO_ID);
4051                    break;
4052                case com.android.internal.R.styleable.View_tag:
4053                    mTag = a.getText(attr);
4054                    break;
4055                case com.android.internal.R.styleable.View_fitsSystemWindows:
4056                    if (a.getBoolean(attr, false)) {
4057                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4058                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4059                    }
4060                    break;
4061                case com.android.internal.R.styleable.View_focusable:
4062                    if (a.getBoolean(attr, false)) {
4063                        viewFlagValues |= FOCUSABLE;
4064                        viewFlagMasks |= FOCUSABLE_MASK;
4065                    }
4066                    break;
4067                case com.android.internal.R.styleable.View_focusableInTouchMode:
4068                    if (a.getBoolean(attr, false)) {
4069                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4070                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4071                    }
4072                    break;
4073                case com.android.internal.R.styleable.View_clickable:
4074                    if (a.getBoolean(attr, false)) {
4075                        viewFlagValues |= CLICKABLE;
4076                        viewFlagMasks |= CLICKABLE;
4077                    }
4078                    break;
4079                case com.android.internal.R.styleable.View_longClickable:
4080                    if (a.getBoolean(attr, false)) {
4081                        viewFlagValues |= LONG_CLICKABLE;
4082                        viewFlagMasks |= LONG_CLICKABLE;
4083                    }
4084                    break;
4085                case com.android.internal.R.styleable.View_contextClickable:
4086                    if (a.getBoolean(attr, false)) {
4087                        viewFlagValues |= CONTEXT_CLICKABLE;
4088                        viewFlagMasks |= CONTEXT_CLICKABLE;
4089                    }
4090                    break;
4091                case com.android.internal.R.styleable.View_saveEnabled:
4092                    if (!a.getBoolean(attr, true)) {
4093                        viewFlagValues |= SAVE_DISABLED;
4094                        viewFlagMasks |= SAVE_DISABLED_MASK;
4095                    }
4096                    break;
4097                case com.android.internal.R.styleable.View_duplicateParentState:
4098                    if (a.getBoolean(attr, false)) {
4099                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4100                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4101                    }
4102                    break;
4103                case com.android.internal.R.styleable.View_visibility:
4104                    final int visibility = a.getInt(attr, 0);
4105                    if (visibility != 0) {
4106                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4107                        viewFlagMasks |= VISIBILITY_MASK;
4108                    }
4109                    break;
4110                case com.android.internal.R.styleable.View_layoutDirection:
4111                    // Clear any layout direction flags (included resolved bits) already set
4112                    mPrivateFlags2 &=
4113                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4114                    // Set the layout direction flags depending on the value of the attribute
4115                    final int layoutDirection = a.getInt(attr, -1);
4116                    final int value = (layoutDirection != -1) ?
4117                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4118                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4119                    break;
4120                case com.android.internal.R.styleable.View_drawingCacheQuality:
4121                    final int cacheQuality = a.getInt(attr, 0);
4122                    if (cacheQuality != 0) {
4123                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4124                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4125                    }
4126                    break;
4127                case com.android.internal.R.styleable.View_contentDescription:
4128                    setContentDescription(a.getString(attr));
4129                    break;
4130                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4131                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4132                    break;
4133                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4134                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4135                    break;
4136                case com.android.internal.R.styleable.View_labelFor:
4137                    setLabelFor(a.getResourceId(attr, NO_ID));
4138                    break;
4139                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4140                    if (!a.getBoolean(attr, true)) {
4141                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4142                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4143                    }
4144                    break;
4145                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4146                    if (!a.getBoolean(attr, true)) {
4147                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4148                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4149                    }
4150                    break;
4151                case R.styleable.View_scrollbars:
4152                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4153                    if (scrollbars != SCROLLBARS_NONE) {
4154                        viewFlagValues |= scrollbars;
4155                        viewFlagMasks |= SCROLLBARS_MASK;
4156                        initializeScrollbars = true;
4157                    }
4158                    break;
4159                //noinspection deprecation
4160                case R.styleable.View_fadingEdge:
4161                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4162                        // Ignore the attribute starting with ICS
4163                        break;
4164                    }
4165                    // With builds < ICS, fall through and apply fading edges
4166                case R.styleable.View_requiresFadingEdge:
4167                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4168                    if (fadingEdge != FADING_EDGE_NONE) {
4169                        viewFlagValues |= fadingEdge;
4170                        viewFlagMasks |= FADING_EDGE_MASK;
4171                        initializeFadingEdgeInternal(a);
4172                    }
4173                    break;
4174                case R.styleable.View_scrollbarStyle:
4175                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4176                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4177                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4178                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4179                    }
4180                    break;
4181                case R.styleable.View_isScrollContainer:
4182                    setScrollContainer = true;
4183                    if (a.getBoolean(attr, false)) {
4184                        setScrollContainer(true);
4185                    }
4186                    break;
4187                case com.android.internal.R.styleable.View_keepScreenOn:
4188                    if (a.getBoolean(attr, false)) {
4189                        viewFlagValues |= KEEP_SCREEN_ON;
4190                        viewFlagMasks |= KEEP_SCREEN_ON;
4191                    }
4192                    break;
4193                case R.styleable.View_filterTouchesWhenObscured:
4194                    if (a.getBoolean(attr, false)) {
4195                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4196                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4197                    }
4198                    break;
4199                case R.styleable.View_nextFocusLeft:
4200                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4201                    break;
4202                case R.styleable.View_nextFocusRight:
4203                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4204                    break;
4205                case R.styleable.View_nextFocusUp:
4206                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4207                    break;
4208                case R.styleable.View_nextFocusDown:
4209                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4210                    break;
4211                case R.styleable.View_nextFocusForward:
4212                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4213                    break;
4214                case R.styleable.View_minWidth:
4215                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4216                    break;
4217                case R.styleable.View_minHeight:
4218                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4219                    break;
4220                case R.styleable.View_onClick:
4221                    if (context.isRestricted()) {
4222                        throw new IllegalStateException("The android:onClick attribute cannot "
4223                                + "be used within a restricted context");
4224                    }
4225
4226                    final String handlerName = a.getString(attr);
4227                    if (handlerName != null) {
4228                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4229                    }
4230                    break;
4231                case R.styleable.View_overScrollMode:
4232                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4233                    break;
4234                case R.styleable.View_verticalScrollbarPosition:
4235                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4236                    break;
4237                case R.styleable.View_layerType:
4238                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4239                    break;
4240                case R.styleable.View_textDirection:
4241                    // Clear any text direction flag already set
4242                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4243                    // Set the text direction flags depending on the value of the attribute
4244                    final int textDirection = a.getInt(attr, -1);
4245                    if (textDirection != -1) {
4246                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4247                    }
4248                    break;
4249                case R.styleable.View_textAlignment:
4250                    // Clear any text alignment flag already set
4251                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4252                    // Set the text alignment flag depending on the value of the attribute
4253                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4254                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4255                    break;
4256                case R.styleable.View_importantForAccessibility:
4257                    setImportantForAccessibility(a.getInt(attr,
4258                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4259                    break;
4260                case R.styleable.View_accessibilityLiveRegion:
4261                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4262                    break;
4263                case R.styleable.View_transitionName:
4264                    setTransitionName(a.getString(attr));
4265                    break;
4266                case R.styleable.View_nestedScrollingEnabled:
4267                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4268                    break;
4269                case R.styleable.View_stateListAnimator:
4270                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4271                            a.getResourceId(attr, 0)));
4272                    break;
4273                case R.styleable.View_backgroundTint:
4274                    // This will get applied later during setBackground().
4275                    if (mBackgroundTint == null) {
4276                        mBackgroundTint = new TintInfo();
4277                    }
4278                    mBackgroundTint.mTintList = a.getColorStateList(
4279                            R.styleable.View_backgroundTint);
4280                    mBackgroundTint.mHasTintList = true;
4281                    break;
4282                case R.styleable.View_backgroundTintMode:
4283                    // This will get applied later during setBackground().
4284                    if (mBackgroundTint == null) {
4285                        mBackgroundTint = new TintInfo();
4286                    }
4287                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4288                            R.styleable.View_backgroundTintMode, -1), null);
4289                    mBackgroundTint.mHasTintMode = true;
4290                    break;
4291                case R.styleable.View_outlineProvider:
4292                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4293                            PROVIDER_BACKGROUND));
4294                    break;
4295                case R.styleable.View_foreground:
4296                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4297                        setForeground(a.getDrawable(attr));
4298                    }
4299                    break;
4300                case R.styleable.View_foregroundGravity:
4301                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4302                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4303                    }
4304                    break;
4305                case R.styleable.View_foregroundTintMode:
4306                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4307                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4308                    }
4309                    break;
4310                case R.styleable.View_foregroundTint:
4311                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4312                        setForegroundTintList(a.getColorStateList(attr));
4313                    }
4314                    break;
4315                case R.styleable.View_foregroundInsidePadding:
4316                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4317                        if (mForegroundInfo == null) {
4318                            mForegroundInfo = new ForegroundInfo();
4319                        }
4320                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4321                                mForegroundInfo.mInsidePadding);
4322                    }
4323                    break;
4324                case R.styleable.View_scrollIndicators:
4325                    final int scrollIndicators =
4326                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4327                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4328                    if (scrollIndicators != 0) {
4329                        mPrivateFlags3 |= scrollIndicators;
4330                        initializeScrollIndicators = true;
4331                    }
4332                    break;
4333            }
4334        }
4335
4336        setOverScrollMode(overScrollMode);
4337
4338        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4339        // the resolved layout direction). Those cached values will be used later during padding
4340        // resolution.
4341        mUserPaddingStart = startPadding;
4342        mUserPaddingEnd = endPadding;
4343
4344        if (background != null) {
4345            setBackground(background);
4346        }
4347
4348        // setBackground above will record that padding is currently provided by the background.
4349        // If we have padding specified via xml, record that here instead and use it.
4350        mLeftPaddingDefined = leftPaddingDefined;
4351        mRightPaddingDefined = rightPaddingDefined;
4352
4353        if (padding >= 0) {
4354            leftPadding = padding;
4355            topPadding = padding;
4356            rightPadding = padding;
4357            bottomPadding = padding;
4358            mUserPaddingLeftInitial = padding;
4359            mUserPaddingRightInitial = padding;
4360        }
4361
4362        if (isRtlCompatibilityMode()) {
4363            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4364            // left / right padding are used if defined (meaning here nothing to do). If they are not
4365            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4366            // start / end and resolve them as left / right (layout direction is not taken into account).
4367            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4368            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4369            // defined.
4370            if (!mLeftPaddingDefined && startPaddingDefined) {
4371                leftPadding = startPadding;
4372            }
4373            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4374            if (!mRightPaddingDefined && endPaddingDefined) {
4375                rightPadding = endPadding;
4376            }
4377            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4378        } else {
4379            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4380            // values defined. Otherwise, left /right values are used.
4381            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4382            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4383            // defined.
4384            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4385
4386            if (mLeftPaddingDefined && !hasRelativePadding) {
4387                mUserPaddingLeftInitial = leftPadding;
4388            }
4389            if (mRightPaddingDefined && !hasRelativePadding) {
4390                mUserPaddingRightInitial = rightPadding;
4391            }
4392        }
4393
4394        internalSetPadding(
4395                mUserPaddingLeftInitial,
4396                topPadding >= 0 ? topPadding : mPaddingTop,
4397                mUserPaddingRightInitial,
4398                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4399
4400        if (viewFlagMasks != 0) {
4401            setFlags(viewFlagValues, viewFlagMasks);
4402        }
4403
4404        if (initializeScrollbars) {
4405            initializeScrollbarsInternal(a);
4406        }
4407
4408        if (initializeScrollIndicators) {
4409            initializeScrollIndicatorsInternal();
4410        }
4411
4412        a.recycle();
4413
4414        // Needs to be called after mViewFlags is set
4415        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4416            recomputePadding();
4417        }
4418
4419        if (x != 0 || y != 0) {
4420            scrollTo(x, y);
4421        }
4422
4423        if (transformSet) {
4424            setTranslationX(tx);
4425            setTranslationY(ty);
4426            setTranslationZ(tz);
4427            setElevation(elevation);
4428            setRotation(rotation);
4429            setRotationX(rotationX);
4430            setRotationY(rotationY);
4431            setScaleX(sx);
4432            setScaleY(sy);
4433        }
4434
4435        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4436            setScrollContainer(true);
4437        }
4438
4439        computeOpaqueFlags();
4440    }
4441
4442    /**
4443     * An implementation of OnClickListener that attempts to lazily load a
4444     * named click handling method from a parent or ancestor context.
4445     */
4446    private static class DeclaredOnClickListener implements OnClickListener {
4447        private final View mHostView;
4448        private final String mMethodName;
4449
4450        private Method mResolvedMethod;
4451        private Context mResolvedContext;
4452
4453        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4454            mHostView = hostView;
4455            mMethodName = methodName;
4456        }
4457
4458        @Override
4459        public void onClick(@NonNull View v) {
4460            if (mResolvedMethod == null) {
4461                resolveMethod(mHostView.getContext(), mMethodName);
4462            }
4463
4464            try {
4465                mResolvedMethod.invoke(mResolvedContext, v);
4466            } catch (IllegalAccessException e) {
4467                throw new IllegalStateException(
4468                        "Could not execute non-public method for android:onClick", e);
4469            } catch (InvocationTargetException e) {
4470                throw new IllegalStateException(
4471                        "Could not execute method for android:onClick", e);
4472            }
4473        }
4474
4475        @NonNull
4476        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4477            while (context != null) {
4478                try {
4479                    if (!context.isRestricted()) {
4480                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4481                        if (method != null) {
4482                            mResolvedMethod = method;
4483                            mResolvedContext = context;
4484                            return;
4485                        }
4486                    }
4487                } catch (NoSuchMethodException e) {
4488                    // Failed to find method, keep searching up the hierarchy.
4489                }
4490
4491                if (context instanceof ContextWrapper) {
4492                    context = ((ContextWrapper) context).getBaseContext();
4493                } else {
4494                    // Can't search up the hierarchy, null out and fail.
4495                    context = null;
4496                }
4497            }
4498
4499            final int id = mHostView.getId();
4500            final String idText = id == NO_ID ? "" : " with id '"
4501                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4502            throw new IllegalStateException("Could not find method " + mMethodName
4503                    + "(View) in a parent or ancestor Context for android:onClick "
4504                    + "attribute defined on view " + mHostView.getClass() + idText);
4505        }
4506    }
4507
4508    /**
4509     * Non-public constructor for use in testing
4510     */
4511    View() {
4512        mResources = null;
4513        mRenderNode = RenderNode.create(getClass().getName(), this);
4514    }
4515
4516    private static SparseArray<String> getAttributeMap() {
4517        if (mAttributeMap == null) {
4518            mAttributeMap = new SparseArray<>();
4519        }
4520        return mAttributeMap;
4521    }
4522
4523    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4524        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4525        final int indexCount = t.getIndexCount();
4526        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4527
4528        int i = 0;
4529
4530        // Store raw XML attributes.
4531        for (int j = 0; j < attrsCount; ++j) {
4532            attributes[i] = attrs.getAttributeName(j);
4533            attributes[i + 1] = attrs.getAttributeValue(j);
4534            i += 2;
4535        }
4536
4537        // Store resolved styleable attributes.
4538        final Resources res = t.getResources();
4539        final SparseArray<String> attributeMap = getAttributeMap();
4540        for (int j = 0; j < indexCount; ++j) {
4541            final int index = t.getIndex(j);
4542            if (!t.hasValueOrEmpty(index)) {
4543                // Value is undefined. Skip it.
4544                continue;
4545            }
4546
4547            final int resourceId = t.getResourceId(index, 0);
4548            if (resourceId == 0) {
4549                // Value is not a reference. Skip it.
4550                continue;
4551            }
4552
4553            String resourceName = attributeMap.get(resourceId);
4554            if (resourceName == null) {
4555                try {
4556                    resourceName = res.getResourceName(resourceId);
4557                } catch (Resources.NotFoundException e) {
4558                    resourceName = "0x" + Integer.toHexString(resourceId);
4559                }
4560                attributeMap.put(resourceId, resourceName);
4561            }
4562
4563            attributes[i] = resourceName;
4564            attributes[i + 1] = t.getString(index);
4565            i += 2;
4566        }
4567
4568        // Trim to fit contents.
4569        final String[] trimmed = new String[i];
4570        System.arraycopy(attributes, 0, trimmed, 0, i);
4571        mAttributes = trimmed;
4572    }
4573
4574    public String toString() {
4575        StringBuilder out = new StringBuilder(128);
4576        out.append(getClass().getName());
4577        out.append('{');
4578        out.append(Integer.toHexString(System.identityHashCode(this)));
4579        out.append(' ');
4580        switch (mViewFlags&VISIBILITY_MASK) {
4581            case VISIBLE: out.append('V'); break;
4582            case INVISIBLE: out.append('I'); break;
4583            case GONE: out.append('G'); break;
4584            default: out.append('.'); break;
4585        }
4586        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4587        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4588        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4589        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4590        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4591        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4592        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4593        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4594        out.append(' ');
4595        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4596        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4597        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4598        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4599            out.append('p');
4600        } else {
4601            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4602        }
4603        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4604        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4605        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4606        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4607        out.append(' ');
4608        out.append(mLeft);
4609        out.append(',');
4610        out.append(mTop);
4611        out.append('-');
4612        out.append(mRight);
4613        out.append(',');
4614        out.append(mBottom);
4615        final int id = getId();
4616        if (id != NO_ID) {
4617            out.append(" #");
4618            out.append(Integer.toHexString(id));
4619            final Resources r = mResources;
4620            if (Resources.resourceHasPackage(id) && r != null) {
4621                try {
4622                    String pkgname;
4623                    switch (id&0xff000000) {
4624                        case 0x7f000000:
4625                            pkgname="app";
4626                            break;
4627                        case 0x01000000:
4628                            pkgname="android";
4629                            break;
4630                        default:
4631                            pkgname = r.getResourcePackageName(id);
4632                            break;
4633                    }
4634                    String typename = r.getResourceTypeName(id);
4635                    String entryname = r.getResourceEntryName(id);
4636                    out.append(" ");
4637                    out.append(pkgname);
4638                    out.append(":");
4639                    out.append(typename);
4640                    out.append("/");
4641                    out.append(entryname);
4642                } catch (Resources.NotFoundException e) {
4643                }
4644            }
4645        }
4646        out.append("}");
4647        return out.toString();
4648    }
4649
4650    /**
4651     * <p>
4652     * Initializes the fading edges from a given set of styled attributes. This
4653     * method should be called by subclasses that need fading edges and when an
4654     * instance of these subclasses is created programmatically rather than
4655     * being inflated from XML. This method is automatically called when the XML
4656     * is inflated.
4657     * </p>
4658     *
4659     * @param a the styled attributes set to initialize the fading edges from
4660     *
4661     * @removed
4662     */
4663    protected void initializeFadingEdge(TypedArray a) {
4664        // This method probably shouldn't have been included in the SDK to begin with.
4665        // It relies on 'a' having been initialized using an attribute filter array that is
4666        // not publicly available to the SDK. The old method has been renamed
4667        // to initializeFadingEdgeInternal and hidden for framework use only;
4668        // this one initializes using defaults to make it safe to call for apps.
4669
4670        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4671
4672        initializeFadingEdgeInternal(arr);
4673
4674        arr.recycle();
4675    }
4676
4677    /**
4678     * <p>
4679     * Initializes the fading edges from a given set of styled attributes. This
4680     * method should be called by subclasses that need fading edges and when an
4681     * instance of these subclasses is created programmatically rather than
4682     * being inflated from XML. This method is automatically called when the XML
4683     * is inflated.
4684     * </p>
4685     *
4686     * @param a the styled attributes set to initialize the fading edges from
4687     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4688     */
4689    protected void initializeFadingEdgeInternal(TypedArray a) {
4690        initScrollCache();
4691
4692        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4693                R.styleable.View_fadingEdgeLength,
4694                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4695    }
4696
4697    /**
4698     * Returns the size of the vertical faded edges used to indicate that more
4699     * content in this view is visible.
4700     *
4701     * @return The size in pixels of the vertical faded edge or 0 if vertical
4702     *         faded edges are not enabled for this view.
4703     * @attr ref android.R.styleable#View_fadingEdgeLength
4704     */
4705    public int getVerticalFadingEdgeLength() {
4706        if (isVerticalFadingEdgeEnabled()) {
4707            ScrollabilityCache cache = mScrollCache;
4708            if (cache != null) {
4709                return cache.fadingEdgeLength;
4710            }
4711        }
4712        return 0;
4713    }
4714
4715    /**
4716     * Set the size of the faded edge used to indicate that more content in this
4717     * view is available.  Will not change whether the fading edge is enabled; use
4718     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4719     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4720     * for the vertical or horizontal fading edges.
4721     *
4722     * @param length The size in pixels of the faded edge used to indicate that more
4723     *        content in this view is visible.
4724     */
4725    public void setFadingEdgeLength(int length) {
4726        initScrollCache();
4727        mScrollCache.fadingEdgeLength = length;
4728    }
4729
4730    /**
4731     * Returns the size of the horizontal faded edges used to indicate that more
4732     * content in this view is visible.
4733     *
4734     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4735     *         faded edges are not enabled for this view.
4736     * @attr ref android.R.styleable#View_fadingEdgeLength
4737     */
4738    public int getHorizontalFadingEdgeLength() {
4739        if (isHorizontalFadingEdgeEnabled()) {
4740            ScrollabilityCache cache = mScrollCache;
4741            if (cache != null) {
4742                return cache.fadingEdgeLength;
4743            }
4744        }
4745        return 0;
4746    }
4747
4748    /**
4749     * Returns the width of the vertical scrollbar.
4750     *
4751     * @return The width in pixels of the vertical scrollbar or 0 if there
4752     *         is no vertical scrollbar.
4753     */
4754    public int getVerticalScrollbarWidth() {
4755        ScrollabilityCache cache = mScrollCache;
4756        if (cache != null) {
4757            ScrollBarDrawable scrollBar = cache.scrollBar;
4758            if (scrollBar != null) {
4759                int size = scrollBar.getSize(true);
4760                if (size <= 0) {
4761                    size = cache.scrollBarSize;
4762                }
4763                return size;
4764            }
4765            return 0;
4766        }
4767        return 0;
4768    }
4769
4770    /**
4771     * Returns the height of the horizontal scrollbar.
4772     *
4773     * @return The height in pixels of the horizontal scrollbar or 0 if
4774     *         there is no horizontal scrollbar.
4775     */
4776    protected int getHorizontalScrollbarHeight() {
4777        ScrollabilityCache cache = mScrollCache;
4778        if (cache != null) {
4779            ScrollBarDrawable scrollBar = cache.scrollBar;
4780            if (scrollBar != null) {
4781                int size = scrollBar.getSize(false);
4782                if (size <= 0) {
4783                    size = cache.scrollBarSize;
4784                }
4785                return size;
4786            }
4787            return 0;
4788        }
4789        return 0;
4790    }
4791
4792    /**
4793     * <p>
4794     * Initializes the scrollbars from a given set of styled attributes. This
4795     * method should be called by subclasses that need scrollbars and when an
4796     * instance of these subclasses is created programmatically rather than
4797     * being inflated from XML. This method is automatically called when the XML
4798     * is inflated.
4799     * </p>
4800     *
4801     * @param a the styled attributes set to initialize the scrollbars from
4802     *
4803     * @removed
4804     */
4805    protected void initializeScrollbars(TypedArray a) {
4806        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4807        // using the View filter array which is not available to the SDK. As such, internal
4808        // framework usage now uses initializeScrollbarsInternal and we grab a default
4809        // TypedArray with the right filter instead here.
4810        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4811
4812        initializeScrollbarsInternal(arr);
4813
4814        // We ignored the method parameter. Recycle the one we actually did use.
4815        arr.recycle();
4816    }
4817
4818    /**
4819     * <p>
4820     * Initializes the scrollbars from a given set of styled attributes. This
4821     * method should be called by subclasses that need scrollbars and when an
4822     * instance of these subclasses is created programmatically rather than
4823     * being inflated from XML. This method is automatically called when the XML
4824     * is inflated.
4825     * </p>
4826     *
4827     * @param a the styled attributes set to initialize the scrollbars from
4828     * @hide
4829     */
4830    protected void initializeScrollbarsInternal(TypedArray a) {
4831        initScrollCache();
4832
4833        final ScrollabilityCache scrollabilityCache = mScrollCache;
4834
4835        if (scrollabilityCache.scrollBar == null) {
4836            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4837            scrollabilityCache.scrollBar.setCallback(this);
4838            scrollabilityCache.scrollBar.setState(getDrawableState());
4839        }
4840
4841        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4842
4843        if (!fadeScrollbars) {
4844            scrollabilityCache.state = ScrollabilityCache.ON;
4845        }
4846        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4847
4848
4849        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4850                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4851                        .getScrollBarFadeDuration());
4852        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4853                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4854                ViewConfiguration.getScrollDefaultDelay());
4855
4856
4857        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4858                com.android.internal.R.styleable.View_scrollbarSize,
4859                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4860
4861        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4862        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4863
4864        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4865        if (thumb != null) {
4866            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4867        }
4868
4869        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4870                false);
4871        if (alwaysDraw) {
4872            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4873        }
4874
4875        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4876        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4877
4878        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4879        if (thumb != null) {
4880            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4881        }
4882
4883        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4884                false);
4885        if (alwaysDraw) {
4886            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4887        }
4888
4889        // Apply layout direction to the new Drawables if needed
4890        final int layoutDirection = getLayoutDirection();
4891        if (track != null) {
4892            track.setLayoutDirection(layoutDirection);
4893        }
4894        if (thumb != null) {
4895            thumb.setLayoutDirection(layoutDirection);
4896        }
4897
4898        // Re-apply user/background padding so that scrollbar(s) get added
4899        resolvePadding();
4900    }
4901
4902    private void initializeScrollIndicatorsInternal() {
4903        // Some day maybe we'll break this into top/left/start/etc. and let the
4904        // client control it. Until then, you can have any scroll indicator you
4905        // want as long as it's a 1dp foreground-colored rectangle.
4906        if (mScrollIndicatorDrawable == null) {
4907            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4908        }
4909    }
4910
4911    /**
4912     * <p>
4913     * Initalizes the scrollability cache if necessary.
4914     * </p>
4915     */
4916    private void initScrollCache() {
4917        if (mScrollCache == null) {
4918            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4919        }
4920    }
4921
4922    private ScrollabilityCache getScrollCache() {
4923        initScrollCache();
4924        return mScrollCache;
4925    }
4926
4927    /**
4928     * Set the position of the vertical scroll bar. Should be one of
4929     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4930     * {@link #SCROLLBAR_POSITION_RIGHT}.
4931     *
4932     * @param position Where the vertical scroll bar should be positioned.
4933     */
4934    public void setVerticalScrollbarPosition(int position) {
4935        if (mVerticalScrollbarPosition != position) {
4936            mVerticalScrollbarPosition = position;
4937            computeOpaqueFlags();
4938            resolvePadding();
4939        }
4940    }
4941
4942    /**
4943     * @return The position where the vertical scroll bar will show, if applicable.
4944     * @see #setVerticalScrollbarPosition(int)
4945     */
4946    public int getVerticalScrollbarPosition() {
4947        return mVerticalScrollbarPosition;
4948    }
4949
4950    /**
4951     * Sets the state of all scroll indicators.
4952     * <p>
4953     * See {@link #setScrollIndicators(int, int)} for usage information.
4954     *
4955     * @param indicators a bitmask of indicators that should be enabled, or
4956     *                   {@code 0} to disable all indicators
4957     * @see #setScrollIndicators(int, int)
4958     * @see #getScrollIndicators()
4959     * @attr ref android.R.styleable#View_scrollIndicators
4960     */
4961    public void setScrollIndicators(@ScrollIndicators int indicators) {
4962        setScrollIndicators(indicators,
4963                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
4964    }
4965
4966    /**
4967     * Sets the state of the scroll indicators specified by the mask. To change
4968     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
4969     * <p>
4970     * When a scroll indicator is enabled, it will be displayed if the view
4971     * can scroll in the direction of the indicator.
4972     * <p>
4973     * Multiple indicator types may be enabled or disabled by passing the
4974     * logical OR of the desired types. If multiple types are specified, they
4975     * will all be set to the same enabled state.
4976     * <p>
4977     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
4978     *
4979     * @param indicators the indicator direction, or the logical OR of multiple
4980     *             indicator directions. One or more of:
4981     *             <ul>
4982     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
4983     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
4984     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
4985     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
4986     *               <li>{@link #SCROLL_INDICATOR_START}</li>
4987     *               <li>{@link #SCROLL_INDICATOR_END}</li>
4988     *             </ul>
4989     * @see #setScrollIndicators(int)
4990     * @see #getScrollIndicators()
4991     * @attr ref android.R.styleable#View_scrollIndicators
4992     */
4993    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
4994        // Shift and sanitize mask.
4995        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4996        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
4997
4998        // Shift and mask indicators.
4999        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5000        indicators &= mask;
5001
5002        // Merge with non-masked flags.
5003        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5004
5005        if (mPrivateFlags3 != updatedFlags) {
5006            mPrivateFlags3 = updatedFlags;
5007
5008            if (indicators != 0) {
5009                initializeScrollIndicatorsInternal();
5010            }
5011            invalidate();
5012        }
5013    }
5014
5015    /**
5016     * Returns a bitmask representing the enabled scroll indicators.
5017     * <p>
5018     * For example, if the top and left scroll indicators are enabled and all
5019     * other indicators are disabled, the return value will be
5020     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5021     * <p>
5022     * To check whether the bottom scroll indicator is enabled, use the value
5023     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5024     *
5025     * @return a bitmask representing the enabled scroll indicators
5026     */
5027    @ScrollIndicators
5028    public int getScrollIndicators() {
5029        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5030                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5031    }
5032
5033    ListenerInfo getListenerInfo() {
5034        if (mListenerInfo != null) {
5035            return mListenerInfo;
5036        }
5037        mListenerInfo = new ListenerInfo();
5038        return mListenerInfo;
5039    }
5040
5041    /**
5042     * Register a callback to be invoked when the scroll X or Y positions of
5043     * this view change.
5044     * <p>
5045     * <b>Note:</b> Some views handle scrolling independently from View and may
5046     * have their own separate listeners for scroll-type events. For example,
5047     * {@link android.widget.ListView ListView} allows clients to register an
5048     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5049     * to listen for changes in list scroll position.
5050     *
5051     * @param l The listener to notify when the scroll X or Y position changes.
5052     * @see android.view.View#getScrollX()
5053     * @see android.view.View#getScrollY()
5054     */
5055    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5056        getListenerInfo().mOnScrollChangeListener = l;
5057    }
5058
5059    /**
5060     * Register a callback to be invoked when focus of this view changed.
5061     *
5062     * @param l The callback that will run.
5063     */
5064    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5065        getListenerInfo().mOnFocusChangeListener = l;
5066    }
5067
5068    /**
5069     * Add a listener that will be called when the bounds of the view change due to
5070     * layout processing.
5071     *
5072     * @param listener The listener that will be called when layout bounds change.
5073     */
5074    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5075        ListenerInfo li = getListenerInfo();
5076        if (li.mOnLayoutChangeListeners == null) {
5077            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5078        }
5079        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5080            li.mOnLayoutChangeListeners.add(listener);
5081        }
5082    }
5083
5084    /**
5085     * Remove a listener for layout changes.
5086     *
5087     * @param listener The listener for layout bounds change.
5088     */
5089    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5090        ListenerInfo li = mListenerInfo;
5091        if (li == null || li.mOnLayoutChangeListeners == null) {
5092            return;
5093        }
5094        li.mOnLayoutChangeListeners.remove(listener);
5095    }
5096
5097    /**
5098     * Add a listener for attach state changes.
5099     *
5100     * This listener will be called whenever this view is attached or detached
5101     * from a window. Remove the listener using
5102     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5103     *
5104     * @param listener Listener to attach
5105     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5106     */
5107    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5108        ListenerInfo li = getListenerInfo();
5109        if (li.mOnAttachStateChangeListeners == null) {
5110            li.mOnAttachStateChangeListeners
5111                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5112        }
5113        li.mOnAttachStateChangeListeners.add(listener);
5114    }
5115
5116    /**
5117     * Remove a listener for attach state changes. The listener will receive no further
5118     * notification of window attach/detach events.
5119     *
5120     * @param listener Listener to remove
5121     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5122     */
5123    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5124        ListenerInfo li = mListenerInfo;
5125        if (li == null || li.mOnAttachStateChangeListeners == null) {
5126            return;
5127        }
5128        li.mOnAttachStateChangeListeners.remove(listener);
5129    }
5130
5131    /**
5132     * Returns the focus-change callback registered for this view.
5133     *
5134     * @return The callback, or null if one is not registered.
5135     */
5136    public OnFocusChangeListener getOnFocusChangeListener() {
5137        ListenerInfo li = mListenerInfo;
5138        return li != null ? li.mOnFocusChangeListener : null;
5139    }
5140
5141    /**
5142     * Register a callback to be invoked when this view is clicked. If this view is not
5143     * clickable, it becomes clickable.
5144     *
5145     * @param l The callback that will run
5146     *
5147     * @see #setClickable(boolean)
5148     */
5149    public void setOnClickListener(@Nullable OnClickListener l) {
5150        if (!isClickable()) {
5151            setClickable(true);
5152        }
5153        getListenerInfo().mOnClickListener = l;
5154    }
5155
5156    /**
5157     * Return whether this view has an attached OnClickListener.  Returns
5158     * true if there is a listener, false if there is none.
5159     */
5160    public boolean hasOnClickListeners() {
5161        ListenerInfo li = mListenerInfo;
5162        return (li != null && li.mOnClickListener != null);
5163    }
5164
5165    /**
5166     * Register a callback to be invoked when this view is clicked and held. If this view is not
5167     * long clickable, it becomes long clickable.
5168     *
5169     * @param l The callback that will run
5170     *
5171     * @see #setLongClickable(boolean)
5172     */
5173    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5174        if (!isLongClickable()) {
5175            setLongClickable(true);
5176        }
5177        getListenerInfo().mOnLongClickListener = l;
5178    }
5179
5180    /**
5181     * Register a callback to be invoked when this view is context clicked. If the view is not
5182     * context clickable, it becomes context clickable.
5183     *
5184     * @param l The callback that will run
5185     * @see #setContextClickable(boolean)
5186     */
5187    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5188        if (!isContextClickable()) {
5189            setContextClickable(true);
5190        }
5191        getListenerInfo().mOnContextClickListener = l;
5192    }
5193
5194    /**
5195     * Register a callback to be invoked when the context menu for this view is
5196     * being built. If this view is not long clickable, it becomes long clickable.
5197     *
5198     * @param l The callback that will run
5199     *
5200     */
5201    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5202        if (!isLongClickable()) {
5203            setLongClickable(true);
5204        }
5205        getListenerInfo().mOnCreateContextMenuListener = l;
5206    }
5207
5208    /**
5209     * Call this view's OnClickListener, if it is defined.  Performs all normal
5210     * actions associated with clicking: reporting accessibility event, playing
5211     * a sound, etc.
5212     *
5213     * @return True there was an assigned OnClickListener that was called, false
5214     *         otherwise is returned.
5215     */
5216    public boolean performClick() {
5217        final boolean result;
5218        final ListenerInfo li = mListenerInfo;
5219        if (li != null && li.mOnClickListener != null) {
5220            playSoundEffect(SoundEffectConstants.CLICK);
5221            li.mOnClickListener.onClick(this);
5222            result = true;
5223        } else {
5224            result = false;
5225        }
5226
5227        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5228        return result;
5229    }
5230
5231    /**
5232     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5233     * this only calls the listener, and does not do any associated clicking
5234     * actions like reporting an accessibility event.
5235     *
5236     * @return True there was an assigned OnClickListener that was called, false
5237     *         otherwise is returned.
5238     */
5239    public boolean callOnClick() {
5240        ListenerInfo li = mListenerInfo;
5241        if (li != null && li.mOnClickListener != null) {
5242            li.mOnClickListener.onClick(this);
5243            return true;
5244        }
5245        return false;
5246    }
5247
5248    /**
5249     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5250     * OnLongClickListener did not consume the event.
5251     *
5252     * @return True if one of the above receivers consumed the event, false otherwise.
5253     */
5254    public boolean performLongClick() {
5255        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5256
5257        boolean handled = false;
5258        ListenerInfo li = mListenerInfo;
5259        if (li != null && li.mOnLongClickListener != null) {
5260            handled = li.mOnLongClickListener.onLongClick(View.this);
5261        }
5262        if (!handled) {
5263            handled = showContextMenu();
5264        }
5265        if (handled) {
5266            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5267        }
5268        return handled;
5269    }
5270
5271    /**
5272     * Call this view's OnContextClickListener, if it is defined.
5273     *
5274     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5275     *         otherwise.
5276     */
5277    public boolean performContextClick() {
5278        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5279
5280        boolean handled = false;
5281        ListenerInfo li = mListenerInfo;
5282        if (li != null && li.mOnContextClickListener != null) {
5283            handled = li.mOnContextClickListener.onContextClick(View.this);
5284        }
5285        if (handled) {
5286            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5287        }
5288        return handled;
5289    }
5290
5291    /**
5292     * Performs button-related actions during a touch down event.
5293     *
5294     * @param event The event.
5295     * @return True if the down was consumed.
5296     *
5297     * @hide
5298     */
5299    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5300        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5301            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5302            showContextMenu(event.getX(), event.getY(), event.getMetaState());
5303            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5304            return true;
5305        }
5306        return false;
5307    }
5308
5309    /**
5310     * Bring up the context menu for this view.
5311     *
5312     * @return Whether a context menu was displayed.
5313     */
5314    public boolean showContextMenu() {
5315        return getParent().showContextMenuForChild(this);
5316    }
5317
5318    /**
5319     * Bring up the context menu for this view, referring to the item under the specified point.
5320     *
5321     * @param x The referenced x coordinate.
5322     * @param y The referenced y coordinate.
5323     * @param metaState The keyboard modifiers that were pressed.
5324     * @return Whether a context menu was displayed.
5325     *
5326     * @hide
5327     */
5328    public boolean showContextMenu(float x, float y, int metaState) {
5329        return showContextMenu();
5330    }
5331
5332    /**
5333     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5334     *
5335     * @param callback Callback that will control the lifecycle of the action mode
5336     * @return The new action mode if it is started, null otherwise
5337     *
5338     * @see ActionMode
5339     * @see #startActionMode(android.view.ActionMode.Callback, int)
5340     */
5341    public ActionMode startActionMode(ActionMode.Callback callback) {
5342        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5343    }
5344
5345    /**
5346     * Start an action mode with the given type.
5347     *
5348     * @param callback Callback that will control the lifecycle of the action mode
5349     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5350     * @return The new action mode if it is started, null otherwise
5351     *
5352     * @see ActionMode
5353     */
5354    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5355        ViewParent parent = getParent();
5356        if (parent == null) return null;
5357        try {
5358            return parent.startActionModeForChild(this, callback, type);
5359        } catch (AbstractMethodError ame) {
5360            // Older implementations of custom views might not implement this.
5361            return parent.startActionModeForChild(this, callback);
5362        }
5363    }
5364
5365    /**
5366     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5367     * Context, creating a unique View identifier to retrieve the result.
5368     *
5369     * @param intent The Intent to be started.
5370     * @param requestCode The request code to use.
5371     * @hide
5372     */
5373    public void startActivityForResult(Intent intent, int requestCode) {
5374        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5375        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5376    }
5377
5378    /**
5379     * If this View corresponds to the calling who, dispatches the activity result.
5380     * @param who The identifier for the targeted View to receive the result.
5381     * @param requestCode The integer request code originally supplied to
5382     *                    startActivityForResult(), allowing you to identify who this
5383     *                    result came from.
5384     * @param resultCode The integer result code returned by the child activity
5385     *                   through its setResult().
5386     * @param data An Intent, which can return result data to the caller
5387     *               (various data can be attached to Intent "extras").
5388     * @return {@code true} if the activity result was dispatched.
5389     * @hide
5390     */
5391    public boolean dispatchActivityResult(
5392            String who, int requestCode, int resultCode, Intent data) {
5393        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5394            onActivityResult(requestCode, resultCode, data);
5395            mStartActivityRequestWho = null;
5396            return true;
5397        }
5398        return false;
5399    }
5400
5401    /**
5402     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5403     *
5404     * @param requestCode The integer request code originally supplied to
5405     *                    startActivityForResult(), allowing you to identify who this
5406     *                    result came from.
5407     * @param resultCode The integer result code returned by the child activity
5408     *                   through its setResult().
5409     * @param data An Intent, which can return result data to the caller
5410     *               (various data can be attached to Intent "extras").
5411     * @hide
5412     */
5413    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5414        // Do nothing.
5415    }
5416
5417    /**
5418     * Register a callback to be invoked when a hardware key is pressed in this view.
5419     * Key presses in software input methods will generally not trigger the methods of
5420     * this listener.
5421     * @param l the key listener to attach to this view
5422     */
5423    public void setOnKeyListener(OnKeyListener l) {
5424        getListenerInfo().mOnKeyListener = l;
5425    }
5426
5427    /**
5428     * Register a callback to be invoked when a touch event is sent to this view.
5429     * @param l the touch listener to attach to this view
5430     */
5431    public void setOnTouchListener(OnTouchListener l) {
5432        getListenerInfo().mOnTouchListener = l;
5433    }
5434
5435    /**
5436     * Register a callback to be invoked when a generic motion event is sent to this view.
5437     * @param l the generic motion listener to attach to this view
5438     */
5439    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5440        getListenerInfo().mOnGenericMotionListener = l;
5441    }
5442
5443    /**
5444     * Register a callback to be invoked when a hover event is sent to this view.
5445     * @param l the hover listener to attach to this view
5446     */
5447    public void setOnHoverListener(OnHoverListener l) {
5448        getListenerInfo().mOnHoverListener = l;
5449    }
5450
5451    /**
5452     * Register a drag event listener callback object for this View. The parameter is
5453     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5454     * View, the system calls the
5455     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5456     * @param l An implementation of {@link android.view.View.OnDragListener}.
5457     */
5458    public void setOnDragListener(OnDragListener l) {
5459        getListenerInfo().mOnDragListener = l;
5460    }
5461
5462    /**
5463     * Give this view focus. This will cause
5464     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5465     *
5466     * Note: this does not check whether this {@link View} should get focus, it just
5467     * gives it focus no matter what.  It should only be called internally by framework
5468     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5469     *
5470     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5471     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5472     *        focus moved when requestFocus() is called. It may not always
5473     *        apply, in which case use the default View.FOCUS_DOWN.
5474     * @param previouslyFocusedRect The rectangle of the view that had focus
5475     *        prior in this View's coordinate system.
5476     */
5477    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5478        if (DBG) {
5479            System.out.println(this + " requestFocus()");
5480        }
5481
5482        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5483            mPrivateFlags |= PFLAG_FOCUSED;
5484
5485            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5486
5487            if (mParent != null) {
5488                mParent.requestChildFocus(this, this);
5489            }
5490
5491            if (mAttachInfo != null) {
5492                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5493            }
5494
5495            onFocusChanged(true, direction, previouslyFocusedRect);
5496            refreshDrawableState();
5497        }
5498    }
5499
5500    /**
5501     * Populates <code>outRect</code> with the hotspot bounds. By default,
5502     * the hotspot bounds are identical to the screen bounds.
5503     *
5504     * @param outRect rect to populate with hotspot bounds
5505     * @hide Only for internal use by views and widgets.
5506     */
5507    public void getHotspotBounds(Rect outRect) {
5508        final Drawable background = getBackground();
5509        if (background != null) {
5510            background.getHotspotBounds(outRect);
5511        } else {
5512            getBoundsOnScreen(outRect);
5513        }
5514    }
5515
5516    /**
5517     * Request that a rectangle of this view be visible on the screen,
5518     * scrolling if necessary just enough.
5519     *
5520     * <p>A View should call this if it maintains some notion of which part
5521     * of its content is interesting.  For example, a text editing view
5522     * should call this when its cursor moves.
5523     *
5524     * @param rectangle The rectangle.
5525     * @return Whether any parent scrolled.
5526     */
5527    public boolean requestRectangleOnScreen(Rect rectangle) {
5528        return requestRectangleOnScreen(rectangle, false);
5529    }
5530
5531    /**
5532     * Request that a rectangle of this view be visible on the screen,
5533     * scrolling if necessary just enough.
5534     *
5535     * <p>A View should call this if it maintains some notion of which part
5536     * of its content is interesting.  For example, a text editing view
5537     * should call this when its cursor moves.
5538     *
5539     * <p>When <code>immediate</code> is set to true, scrolling will not be
5540     * animated.
5541     *
5542     * @param rectangle The rectangle.
5543     * @param immediate True to forbid animated scrolling, false otherwise
5544     * @return Whether any parent scrolled.
5545     */
5546    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5547        if (mParent == null) {
5548            return false;
5549        }
5550
5551        View child = this;
5552
5553        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5554        position.set(rectangle);
5555
5556        ViewParent parent = mParent;
5557        boolean scrolled = false;
5558        while (parent != null) {
5559            rectangle.set((int) position.left, (int) position.top,
5560                    (int) position.right, (int) position.bottom);
5561
5562            scrolled |= parent.requestChildRectangleOnScreen(child,
5563                    rectangle, immediate);
5564
5565            if (!child.hasIdentityMatrix()) {
5566                child.getMatrix().mapRect(position);
5567            }
5568
5569            position.offset(child.mLeft, child.mTop);
5570
5571            if (!(parent instanceof View)) {
5572                break;
5573            }
5574
5575            View parentView = (View) parent;
5576
5577            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5578
5579            child = parentView;
5580            parent = child.getParent();
5581        }
5582
5583        return scrolled;
5584    }
5585
5586    /**
5587     * Called when this view wants to give up focus. If focus is cleared
5588     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5589     * <p>
5590     * <strong>Note:</strong> When a View clears focus the framework is trying
5591     * to give focus to the first focusable View from the top. Hence, if this
5592     * View is the first from the top that can take focus, then all callbacks
5593     * related to clearing focus will be invoked after which the framework will
5594     * give focus to this view.
5595     * </p>
5596     */
5597    public void clearFocus() {
5598        if (DBG) {
5599            System.out.println(this + " clearFocus()");
5600        }
5601
5602        clearFocusInternal(null, true, true);
5603    }
5604
5605    /**
5606     * Clears focus from the view, optionally propagating the change up through
5607     * the parent hierarchy and requesting that the root view place new focus.
5608     *
5609     * @param propagate whether to propagate the change up through the parent
5610     *            hierarchy
5611     * @param refocus when propagate is true, specifies whether to request the
5612     *            root view place new focus
5613     */
5614    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5615        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5616            mPrivateFlags &= ~PFLAG_FOCUSED;
5617
5618            if (propagate && mParent != null) {
5619                mParent.clearChildFocus(this);
5620            }
5621
5622            onFocusChanged(false, 0, null);
5623            refreshDrawableState();
5624
5625            if (propagate && (!refocus || !rootViewRequestFocus())) {
5626                notifyGlobalFocusCleared(this);
5627            }
5628        }
5629    }
5630
5631    void notifyGlobalFocusCleared(View oldFocus) {
5632        if (oldFocus != null && mAttachInfo != null) {
5633            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5634        }
5635    }
5636
5637    boolean rootViewRequestFocus() {
5638        final View root = getRootView();
5639        return root != null && root.requestFocus();
5640    }
5641
5642    /**
5643     * Called internally by the view system when a new view is getting focus.
5644     * This is what clears the old focus.
5645     * <p>
5646     * <b>NOTE:</b> The parent view's focused child must be updated manually
5647     * after calling this method. Otherwise, the view hierarchy may be left in
5648     * an inconstent state.
5649     */
5650    void unFocus(View focused) {
5651        if (DBG) {
5652            System.out.println(this + " unFocus()");
5653        }
5654
5655        clearFocusInternal(focused, false, false);
5656    }
5657
5658    /**
5659     * Returns true if this view has focus itself, or is the ancestor of the
5660     * view that has focus.
5661     *
5662     * @return True if this view has or contains focus, false otherwise.
5663     */
5664    @ViewDebug.ExportedProperty(category = "focus")
5665    public boolean hasFocus() {
5666        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5667    }
5668
5669    /**
5670     * Returns true if this view is focusable or if it contains a reachable View
5671     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5672     * is a View whose parents do not block descendants focus.
5673     *
5674     * Only {@link #VISIBLE} views are considered focusable.
5675     *
5676     * @return True if the view is focusable or if the view contains a focusable
5677     *         View, false otherwise.
5678     *
5679     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5680     * @see ViewGroup#getTouchscreenBlocksFocus()
5681     */
5682    public boolean hasFocusable() {
5683        if (!isFocusableInTouchMode()) {
5684            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5685                final ViewGroup g = (ViewGroup) p;
5686                if (g.shouldBlockFocusForTouchscreen()) {
5687                    return false;
5688                }
5689            }
5690        }
5691        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5692    }
5693
5694    /**
5695     * Called by the view system when the focus state of this view changes.
5696     * When the focus change event is caused by directional navigation, direction
5697     * and previouslyFocusedRect provide insight into where the focus is coming from.
5698     * When overriding, be sure to call up through to the super class so that
5699     * the standard focus handling will occur.
5700     *
5701     * @param gainFocus True if the View has focus; false otherwise.
5702     * @param direction The direction focus has moved when requestFocus()
5703     *                  is called to give this view focus. Values are
5704     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5705     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5706     *                  It may not always apply, in which case use the default.
5707     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5708     *        system, of the previously focused view.  If applicable, this will be
5709     *        passed in as finer grained information about where the focus is coming
5710     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5711     */
5712    @CallSuper
5713    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5714            @Nullable Rect previouslyFocusedRect) {
5715        if (gainFocus) {
5716            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5717        } else {
5718            notifyViewAccessibilityStateChangedIfNeeded(
5719                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5720        }
5721
5722        InputMethodManager imm = InputMethodManager.peekInstance();
5723        if (!gainFocus) {
5724            if (isPressed()) {
5725                setPressed(false);
5726            }
5727            if (imm != null && mAttachInfo != null
5728                    && mAttachInfo.mHasWindowFocus) {
5729                imm.focusOut(this);
5730            }
5731            onFocusLost();
5732        } else if (imm != null && mAttachInfo != null
5733                && mAttachInfo.mHasWindowFocus) {
5734            imm.focusIn(this);
5735        }
5736
5737        invalidate(true);
5738        ListenerInfo li = mListenerInfo;
5739        if (li != null && li.mOnFocusChangeListener != null) {
5740            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5741        }
5742
5743        if (mAttachInfo != null) {
5744            mAttachInfo.mKeyDispatchState.reset(this);
5745        }
5746    }
5747
5748    /**
5749     * Sends an accessibility event of the given type. If accessibility is
5750     * not enabled this method has no effect. The default implementation calls
5751     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5752     * to populate information about the event source (this View), then calls
5753     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5754     * populate the text content of the event source including its descendants,
5755     * and last calls
5756     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5757     * on its parent to request sending of the event to interested parties.
5758     * <p>
5759     * If an {@link AccessibilityDelegate} has been specified via calling
5760     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5761     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5762     * responsible for handling this call.
5763     * </p>
5764     *
5765     * @param eventType The type of the event to send, as defined by several types from
5766     * {@link android.view.accessibility.AccessibilityEvent}, such as
5767     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5768     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5769     *
5770     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5771     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5772     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5773     * @see AccessibilityDelegate
5774     */
5775    public void sendAccessibilityEvent(int eventType) {
5776        if (mAccessibilityDelegate != null) {
5777            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5778        } else {
5779            sendAccessibilityEventInternal(eventType);
5780        }
5781    }
5782
5783    /**
5784     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5785     * {@link AccessibilityEvent} to make an announcement which is related to some
5786     * sort of a context change for which none of the events representing UI transitions
5787     * is a good fit. For example, announcing a new page in a book. If accessibility
5788     * is not enabled this method does nothing.
5789     *
5790     * @param text The announcement text.
5791     */
5792    public void announceForAccessibility(CharSequence text) {
5793        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5794            AccessibilityEvent event = AccessibilityEvent.obtain(
5795                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5796            onInitializeAccessibilityEvent(event);
5797            event.getText().add(text);
5798            event.setContentDescription(null);
5799            mParent.requestSendAccessibilityEvent(this, event);
5800        }
5801    }
5802
5803    /**
5804     * @see #sendAccessibilityEvent(int)
5805     *
5806     * Note: Called from the default {@link AccessibilityDelegate}.
5807     *
5808     * @hide
5809     */
5810    public void sendAccessibilityEventInternal(int eventType) {
5811        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5812            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5813        }
5814    }
5815
5816    /**
5817     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5818     * takes as an argument an empty {@link AccessibilityEvent} and does not
5819     * perform a check whether accessibility is enabled.
5820     * <p>
5821     * If an {@link AccessibilityDelegate} has been specified via calling
5822     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5823     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5824     * is responsible for handling this call.
5825     * </p>
5826     *
5827     * @param event The event to send.
5828     *
5829     * @see #sendAccessibilityEvent(int)
5830     */
5831    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5832        if (mAccessibilityDelegate != null) {
5833            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5834        } else {
5835            sendAccessibilityEventUncheckedInternal(event);
5836        }
5837    }
5838
5839    /**
5840     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5841     *
5842     * Note: Called from the default {@link AccessibilityDelegate}.
5843     *
5844     * @hide
5845     */
5846    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5847        if (!isShown()) {
5848            return;
5849        }
5850        onInitializeAccessibilityEvent(event);
5851        // Only a subset of accessibility events populates text content.
5852        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5853            dispatchPopulateAccessibilityEvent(event);
5854        }
5855        // In the beginning we called #isShown(), so we know that getParent() is not null.
5856        getParent().requestSendAccessibilityEvent(this, event);
5857    }
5858
5859    /**
5860     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5861     * to its children for adding their text content to the event. Note that the
5862     * event text is populated in a separate dispatch path since we add to the
5863     * event not only the text of the source but also the text of all its descendants.
5864     * A typical implementation will call
5865     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5866     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5867     * on each child. Override this method if custom population of the event text
5868     * content is required.
5869     * <p>
5870     * If an {@link AccessibilityDelegate} has been specified via calling
5871     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5872     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5873     * is responsible for handling this call.
5874     * </p>
5875     * <p>
5876     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5877     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5878     * </p>
5879     *
5880     * @param event The event.
5881     *
5882     * @return True if the event population was completed.
5883     */
5884    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5885        if (mAccessibilityDelegate != null) {
5886            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5887        } else {
5888            return dispatchPopulateAccessibilityEventInternal(event);
5889        }
5890    }
5891
5892    /**
5893     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5894     *
5895     * Note: Called from the default {@link AccessibilityDelegate}.
5896     *
5897     * @hide
5898     */
5899    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5900        onPopulateAccessibilityEvent(event);
5901        return false;
5902    }
5903
5904    /**
5905     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5906     * giving a chance to this View to populate the accessibility event with its
5907     * text content. While this method is free to modify event
5908     * attributes other than text content, doing so should normally be performed in
5909     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5910     * <p>
5911     * Example: Adding formatted date string to an accessibility event in addition
5912     *          to the text added by the super implementation:
5913     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5914     *     super.onPopulateAccessibilityEvent(event);
5915     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5916     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5917     *         mCurrentDate.getTimeInMillis(), flags);
5918     *     event.getText().add(selectedDateUtterance);
5919     * }</pre>
5920     * <p>
5921     * If an {@link AccessibilityDelegate} has been specified via calling
5922     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5923     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5924     * is responsible for handling this call.
5925     * </p>
5926     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5927     * information to the event, in case the default implementation has basic information to add.
5928     * </p>
5929     *
5930     * @param event The accessibility event which to populate.
5931     *
5932     * @see #sendAccessibilityEvent(int)
5933     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5934     */
5935    @CallSuper
5936    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5937        if (mAccessibilityDelegate != null) {
5938            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5939        } else {
5940            onPopulateAccessibilityEventInternal(event);
5941        }
5942    }
5943
5944    /**
5945     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5946     *
5947     * Note: Called from the default {@link AccessibilityDelegate}.
5948     *
5949     * @hide
5950     */
5951    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5952    }
5953
5954    /**
5955     * Initializes an {@link AccessibilityEvent} with information about
5956     * this View which is the event source. In other words, the source of
5957     * an accessibility event is the view whose state change triggered firing
5958     * the event.
5959     * <p>
5960     * Example: Setting the password property of an event in addition
5961     *          to properties set by the super implementation:
5962     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5963     *     super.onInitializeAccessibilityEvent(event);
5964     *     event.setPassword(true);
5965     * }</pre>
5966     * <p>
5967     * If an {@link AccessibilityDelegate} has been specified via calling
5968     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5969     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5970     * is responsible for handling this call.
5971     * </p>
5972     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5973     * information to the event, in case the default implementation has basic information to add.
5974     * </p>
5975     * @param event The event to initialize.
5976     *
5977     * @see #sendAccessibilityEvent(int)
5978     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5979     */
5980    @CallSuper
5981    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5982        if (mAccessibilityDelegate != null) {
5983            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5984        } else {
5985            onInitializeAccessibilityEventInternal(event);
5986        }
5987    }
5988
5989    /**
5990     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5991     *
5992     * Note: Called from the default {@link AccessibilityDelegate}.
5993     *
5994     * @hide
5995     */
5996    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5997        event.setSource(this);
5998        event.setClassName(getAccessibilityClassName());
5999        event.setPackageName(getContext().getPackageName());
6000        event.setEnabled(isEnabled());
6001        event.setContentDescription(mContentDescription);
6002
6003        switch (event.getEventType()) {
6004            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6005                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6006                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6007                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6008                event.setItemCount(focusablesTempList.size());
6009                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6010                if (mAttachInfo != null) {
6011                    focusablesTempList.clear();
6012                }
6013            } break;
6014            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6015                CharSequence text = getIterableTextForAccessibility();
6016                if (text != null && text.length() > 0) {
6017                    event.setFromIndex(getAccessibilitySelectionStart());
6018                    event.setToIndex(getAccessibilitySelectionEnd());
6019                    event.setItemCount(text.length());
6020                }
6021            } break;
6022        }
6023    }
6024
6025    /**
6026     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6027     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6028     * This method is responsible for obtaining an accessibility node info from a
6029     * pool of reusable instances and calling
6030     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6031     * initialize the former.
6032     * <p>
6033     * Note: The client is responsible for recycling the obtained instance by calling
6034     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6035     * </p>
6036     *
6037     * @return A populated {@link AccessibilityNodeInfo}.
6038     *
6039     * @see AccessibilityNodeInfo
6040     */
6041    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6042        if (mAccessibilityDelegate != null) {
6043            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6044        } else {
6045            return createAccessibilityNodeInfoInternal();
6046        }
6047    }
6048
6049    /**
6050     * @see #createAccessibilityNodeInfo()
6051     *
6052     * @hide
6053     */
6054    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6055        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6056        if (provider != null) {
6057            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6058        } else {
6059            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6060            onInitializeAccessibilityNodeInfo(info);
6061            return info;
6062        }
6063    }
6064
6065    /**
6066     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6067     * The base implementation sets:
6068     * <ul>
6069     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6070     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6071     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6072     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6073     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6074     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6075     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6076     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6077     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6078     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6079     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6080     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6081     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6082     * </ul>
6083     * <p>
6084     * Subclasses should override this method, call the super implementation,
6085     * and set additional attributes.
6086     * </p>
6087     * <p>
6088     * If an {@link AccessibilityDelegate} has been specified via calling
6089     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6090     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6091     * is responsible for handling this call.
6092     * </p>
6093     *
6094     * @param info The instance to initialize.
6095     */
6096    @CallSuper
6097    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6098        if (mAccessibilityDelegate != null) {
6099            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6100        } else {
6101            onInitializeAccessibilityNodeInfoInternal(info);
6102        }
6103    }
6104
6105    /**
6106     * Gets the location of this view in screen coordinates.
6107     *
6108     * @param outRect The output location
6109     * @hide
6110     */
6111    public void getBoundsOnScreen(Rect outRect) {
6112        getBoundsOnScreen(outRect, false);
6113    }
6114
6115    /**
6116     * Gets the location of this view in screen coordinates.
6117     *
6118     * @param outRect The output location
6119     * @param clipToParent Whether to clip child bounds to the parent ones.
6120     * @hide
6121     */
6122    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6123        if (mAttachInfo == null) {
6124            return;
6125        }
6126
6127        RectF position = mAttachInfo.mTmpTransformRect;
6128        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6129
6130        if (!hasIdentityMatrix()) {
6131            getMatrix().mapRect(position);
6132        }
6133
6134        position.offset(mLeft, mTop);
6135
6136        ViewParent parent = mParent;
6137        while (parent instanceof View) {
6138            View parentView = (View) parent;
6139
6140            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6141
6142            if (clipToParent) {
6143                position.left = Math.max(position.left, 0);
6144                position.top = Math.max(position.top, 0);
6145                position.right = Math.min(position.right, parentView.getWidth());
6146                position.bottom = Math.min(position.bottom, parentView.getHeight());
6147            }
6148
6149            if (!parentView.hasIdentityMatrix()) {
6150                parentView.getMatrix().mapRect(position);
6151            }
6152
6153            position.offset(parentView.mLeft, parentView.mTop);
6154
6155            parent = parentView.mParent;
6156        }
6157
6158        if (parent instanceof ViewRootImpl) {
6159            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6160            position.offset(0, -viewRootImpl.mCurScrollY);
6161        }
6162
6163        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6164
6165        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6166                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6167    }
6168
6169    /**
6170     * Return the class name of this object to be used for accessibility purposes.
6171     * Subclasses should only override this if they are implementing something that
6172     * should be seen as a completely new class of view when used by accessibility,
6173     * unrelated to the class it is deriving from.  This is used to fill in
6174     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6175     */
6176    public CharSequence getAccessibilityClassName() {
6177        return View.class.getName();
6178    }
6179
6180    /**
6181     * Called when assist structure is being retrieved from a view as part of
6182     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6183     * @param structure Fill in with structured view data.  The default implementation
6184     * fills in all data that can be inferred from the view itself.
6185     */
6186    public void onProvideStructure(ViewStructure structure) {
6187        final int id = mID;
6188        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6189                && (id&0x0000ffff) != 0) {
6190            String pkg, type, entry;
6191            try {
6192                final Resources res = getResources();
6193                entry = res.getResourceEntryName(id);
6194                type = res.getResourceTypeName(id);
6195                pkg = res.getResourcePackageName(id);
6196            } catch (Resources.NotFoundException e) {
6197                entry = type = pkg = null;
6198            }
6199            structure.setId(id, pkg, type, entry);
6200        } else {
6201            structure.setId(id, null, null, null);
6202        }
6203        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6204        if (!hasIdentityMatrix()) {
6205            structure.setTransformation(getMatrix());
6206        }
6207        structure.setElevation(getZ());
6208        structure.setVisibility(getVisibility());
6209        structure.setEnabled(isEnabled());
6210        if (isClickable()) {
6211            structure.setClickable(true);
6212        }
6213        if (isFocusable()) {
6214            structure.setFocusable(true);
6215        }
6216        if (isFocused()) {
6217            structure.setFocused(true);
6218        }
6219        if (isAccessibilityFocused()) {
6220            structure.setAccessibilityFocused(true);
6221        }
6222        if (isSelected()) {
6223            structure.setSelected(true);
6224        }
6225        if (isActivated()) {
6226            structure.setActivated(true);
6227        }
6228        if (isLongClickable()) {
6229            structure.setLongClickable(true);
6230        }
6231        if (this instanceof Checkable) {
6232            structure.setCheckable(true);
6233            if (((Checkable)this).isChecked()) {
6234                structure.setChecked(true);
6235            }
6236        }
6237        if (isContextClickable()) {
6238            structure.setContextClickable(true);
6239        }
6240        structure.setClassName(getAccessibilityClassName().toString());
6241        structure.setContentDescription(getContentDescription());
6242    }
6243
6244    /**
6245     * Called when assist structure is being retrieved from a view as part of
6246     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6247     * generate additional virtual structure under this view.  The defaullt implementation
6248     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6249     * view's virtual accessibility nodes, if any.  You can override this for a more
6250     * optimal implementation providing this data.
6251     */
6252    public void onProvideVirtualStructure(ViewStructure structure) {
6253        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6254        if (provider != null) {
6255            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6256            structure.setChildCount(1);
6257            ViewStructure root = structure.newChild(0);
6258            populateVirtualStructure(root, provider, info);
6259            info.recycle();
6260        }
6261    }
6262
6263    private void populateVirtualStructure(ViewStructure structure,
6264            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6265        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6266                null, null, null);
6267        Rect rect = structure.getTempRect();
6268        info.getBoundsInParent(rect);
6269        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6270        structure.setVisibility(VISIBLE);
6271        structure.setEnabled(info.isEnabled());
6272        if (info.isClickable()) {
6273            structure.setClickable(true);
6274        }
6275        if (info.isFocusable()) {
6276            structure.setFocusable(true);
6277        }
6278        if (info.isFocused()) {
6279            structure.setFocused(true);
6280        }
6281        if (info.isAccessibilityFocused()) {
6282            structure.setAccessibilityFocused(true);
6283        }
6284        if (info.isSelected()) {
6285            structure.setSelected(true);
6286        }
6287        if (info.isLongClickable()) {
6288            structure.setLongClickable(true);
6289        }
6290        if (info.isCheckable()) {
6291            structure.setCheckable(true);
6292            if (info.isChecked()) {
6293                structure.setChecked(true);
6294            }
6295        }
6296        if (info.isContextClickable()) {
6297            structure.setContextClickable(true);
6298        }
6299        CharSequence cname = info.getClassName();
6300        structure.setClassName(cname != null ? cname.toString() : null);
6301        structure.setContentDescription(info.getContentDescription());
6302        if (info.getText() != null || info.getError() != null) {
6303            structure.setText(info.getText(), info.getTextSelectionStart(),
6304                    info.getTextSelectionEnd());
6305        }
6306        final int NCHILDREN = info.getChildCount();
6307        if (NCHILDREN > 0) {
6308            structure.setChildCount(NCHILDREN);
6309            for (int i=0; i<NCHILDREN; i++) {
6310                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6311                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6312                ViewStructure child = structure.newChild(i);
6313                populateVirtualStructure(child, provider, cinfo);
6314                cinfo.recycle();
6315            }
6316        }
6317    }
6318
6319    /**
6320     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6321     * implementation calls {@link #onProvideStructure} and
6322     * {@link #onProvideVirtualStructure}.
6323     */
6324    public void dispatchProvideStructure(ViewStructure structure) {
6325        if (!isAssistBlocked()) {
6326            onProvideStructure(structure);
6327            onProvideVirtualStructure(structure);
6328        } else {
6329            structure.setClassName(getAccessibilityClassName().toString());
6330            structure.setAssistBlocked(true);
6331        }
6332    }
6333
6334    /**
6335     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6336     *
6337     * Note: Called from the default {@link AccessibilityDelegate}.
6338     *
6339     * @hide
6340     */
6341    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6342        if (mAttachInfo == null) {
6343            return;
6344        }
6345
6346        Rect bounds = mAttachInfo.mTmpInvalRect;
6347
6348        getDrawingRect(bounds);
6349        info.setBoundsInParent(bounds);
6350
6351        getBoundsOnScreen(bounds, true);
6352        info.setBoundsInScreen(bounds);
6353
6354        ViewParent parent = getParentForAccessibility();
6355        if (parent instanceof View) {
6356            info.setParent((View) parent);
6357        }
6358
6359        if (mID != View.NO_ID) {
6360            View rootView = getRootView();
6361            if (rootView == null) {
6362                rootView = this;
6363            }
6364
6365            View label = rootView.findLabelForView(this, mID);
6366            if (label != null) {
6367                info.setLabeledBy(label);
6368            }
6369
6370            if ((mAttachInfo.mAccessibilityFetchFlags
6371                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6372                    && Resources.resourceHasPackage(mID)) {
6373                try {
6374                    String viewId = getResources().getResourceName(mID);
6375                    info.setViewIdResourceName(viewId);
6376                } catch (Resources.NotFoundException nfe) {
6377                    /* ignore */
6378                }
6379            }
6380        }
6381
6382        if (mLabelForId != View.NO_ID) {
6383            View rootView = getRootView();
6384            if (rootView == null) {
6385                rootView = this;
6386            }
6387            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6388            if (labeled != null) {
6389                info.setLabelFor(labeled);
6390            }
6391        }
6392
6393        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6394            View rootView = getRootView();
6395            if (rootView == null) {
6396                rootView = this;
6397            }
6398            View next = rootView.findViewInsideOutShouldExist(this,
6399                    mAccessibilityTraversalBeforeId);
6400            if (next != null && next.includeForAccessibility()) {
6401                info.setTraversalBefore(next);
6402            }
6403        }
6404
6405        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6406            View rootView = getRootView();
6407            if (rootView == null) {
6408                rootView = this;
6409            }
6410            View next = rootView.findViewInsideOutShouldExist(this,
6411                    mAccessibilityTraversalAfterId);
6412            if (next != null && next.includeForAccessibility()) {
6413                info.setTraversalAfter(next);
6414            }
6415        }
6416
6417        info.setVisibleToUser(isVisibleToUser());
6418
6419        info.setPackageName(mContext.getPackageName());
6420        info.setClassName(getAccessibilityClassName());
6421        info.setContentDescription(getContentDescription());
6422
6423        info.setEnabled(isEnabled());
6424        info.setClickable(isClickable());
6425        info.setFocusable(isFocusable());
6426        info.setFocused(isFocused());
6427        info.setAccessibilityFocused(isAccessibilityFocused());
6428        info.setSelected(isSelected());
6429        info.setLongClickable(isLongClickable());
6430        info.setContextClickable(isContextClickable());
6431        info.setLiveRegion(getAccessibilityLiveRegion());
6432
6433        // TODO: These make sense only if we are in an AdapterView but all
6434        // views can be selected. Maybe from accessibility perspective
6435        // we should report as selectable view in an AdapterView.
6436        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6437        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6438
6439        if (isFocusable()) {
6440            if (isFocused()) {
6441                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6442            } else {
6443                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6444            }
6445        }
6446
6447        if (!isAccessibilityFocused()) {
6448            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6449        } else {
6450            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6451        }
6452
6453        if (isClickable() && isEnabled()) {
6454            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6455        }
6456
6457        if (isLongClickable() && isEnabled()) {
6458            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6459        }
6460
6461        if (isContextClickable() && isEnabled()) {
6462            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6463        }
6464
6465        CharSequence text = getIterableTextForAccessibility();
6466        if (text != null && text.length() > 0) {
6467            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6468
6469            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6470            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6471            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6472            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6473                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6474                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6475        }
6476
6477        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6478    }
6479
6480    private View findLabelForView(View view, int labeledId) {
6481        if (mMatchLabelForPredicate == null) {
6482            mMatchLabelForPredicate = new MatchLabelForPredicate();
6483        }
6484        mMatchLabelForPredicate.mLabeledId = labeledId;
6485        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6486    }
6487
6488    /**
6489     * Computes whether this view is visible to the user. Such a view is
6490     * attached, visible, all its predecessors are visible, it is not clipped
6491     * entirely by its predecessors, and has an alpha greater than zero.
6492     *
6493     * @return Whether the view is visible on the screen.
6494     *
6495     * @hide
6496     */
6497    protected boolean isVisibleToUser() {
6498        return isVisibleToUser(null);
6499    }
6500
6501    /**
6502     * Computes whether the given portion of this view is visible to the user.
6503     * Such a view is attached, visible, all its predecessors are visible,
6504     * has an alpha greater than zero, and the specified portion is not
6505     * clipped entirely by its predecessors.
6506     *
6507     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6508     *                    <code>null</code>, and the entire view will be tested in this case.
6509     *                    When <code>true</code> is returned by the function, the actual visible
6510     *                    region will be stored in this parameter; that is, if boundInView is fully
6511     *                    contained within the view, no modification will be made, otherwise regions
6512     *                    outside of the visible area of the view will be clipped.
6513     *
6514     * @return Whether the specified portion of the view is visible on the screen.
6515     *
6516     * @hide
6517     */
6518    protected boolean isVisibleToUser(Rect boundInView) {
6519        if (mAttachInfo != null) {
6520            // Attached to invisible window means this view is not visible.
6521            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6522                return false;
6523            }
6524            // An invisible predecessor or one with alpha zero means
6525            // that this view is not visible to the user.
6526            Object current = this;
6527            while (current instanceof View) {
6528                View view = (View) current;
6529                // We have attach info so this view is attached and there is no
6530                // need to check whether we reach to ViewRootImpl on the way up.
6531                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6532                        view.getVisibility() != VISIBLE) {
6533                    return false;
6534                }
6535                current = view.mParent;
6536            }
6537            // Check if the view is entirely covered by its predecessors.
6538            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6539            Point offset = mAttachInfo.mPoint;
6540            if (!getGlobalVisibleRect(visibleRect, offset)) {
6541                return false;
6542            }
6543            // Check if the visible portion intersects the rectangle of interest.
6544            if (boundInView != null) {
6545                visibleRect.offset(-offset.x, -offset.y);
6546                return boundInView.intersect(visibleRect);
6547            }
6548            return true;
6549        }
6550        return false;
6551    }
6552
6553    /**
6554     * Returns the delegate for implementing accessibility support via
6555     * composition. For more details see {@link AccessibilityDelegate}.
6556     *
6557     * @return The delegate, or null if none set.
6558     *
6559     * @hide
6560     */
6561    public AccessibilityDelegate getAccessibilityDelegate() {
6562        return mAccessibilityDelegate;
6563    }
6564
6565    /**
6566     * Sets a delegate for implementing accessibility support via composition as
6567     * opposed to inheritance. The delegate's primary use is for implementing
6568     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6569     *
6570     * @param delegate The delegate instance.
6571     *
6572     * @see AccessibilityDelegate
6573     */
6574    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6575        mAccessibilityDelegate = delegate;
6576    }
6577
6578    /**
6579     * Gets the provider for managing a virtual view hierarchy rooted at this View
6580     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6581     * that explore the window content.
6582     * <p>
6583     * If this method returns an instance, this instance is responsible for managing
6584     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6585     * View including the one representing the View itself. Similarly the returned
6586     * instance is responsible for performing accessibility actions on any virtual
6587     * view or the root view itself.
6588     * </p>
6589     * <p>
6590     * If an {@link AccessibilityDelegate} has been specified via calling
6591     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6592     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6593     * is responsible for handling this call.
6594     * </p>
6595     *
6596     * @return The provider.
6597     *
6598     * @see AccessibilityNodeProvider
6599     */
6600    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6601        if (mAccessibilityDelegate != null) {
6602            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6603        } else {
6604            return null;
6605        }
6606    }
6607
6608    /**
6609     * Gets the unique identifier of this view on the screen for accessibility purposes.
6610     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6611     *
6612     * @return The view accessibility id.
6613     *
6614     * @hide
6615     */
6616    public int getAccessibilityViewId() {
6617        if (mAccessibilityViewId == NO_ID) {
6618            mAccessibilityViewId = sNextAccessibilityViewId++;
6619        }
6620        return mAccessibilityViewId;
6621    }
6622
6623    /**
6624     * Gets the unique identifier of the window in which this View reseides.
6625     *
6626     * @return The window accessibility id.
6627     *
6628     * @hide
6629     */
6630    public int getAccessibilityWindowId() {
6631        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6632                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6633    }
6634
6635    /**
6636     * Gets the {@link View} description. It briefly describes the view and is
6637     * primarily used for accessibility support. Set this property to enable
6638     * better accessibility support for your application. This is especially
6639     * true for views that do not have textual representation (For example,
6640     * ImageButton).
6641     *
6642     * @return The content description.
6643     *
6644     * @attr ref android.R.styleable#View_contentDescription
6645     */
6646    @ViewDebug.ExportedProperty(category = "accessibility")
6647    public CharSequence getContentDescription() {
6648        return mContentDescription;
6649    }
6650
6651    /**
6652     * Sets the {@link View} description. It briefly describes the view and is
6653     * primarily used for accessibility support. Set this property to enable
6654     * better accessibility support for your application. This is especially
6655     * true for views that do not have textual representation (For example,
6656     * ImageButton).
6657     *
6658     * @param contentDescription The content description.
6659     *
6660     * @attr ref android.R.styleable#View_contentDescription
6661     */
6662    @RemotableViewMethod
6663    public void setContentDescription(CharSequence contentDescription) {
6664        if (mContentDescription == null) {
6665            if (contentDescription == null) {
6666                return;
6667            }
6668        } else if (mContentDescription.equals(contentDescription)) {
6669            return;
6670        }
6671        mContentDescription = contentDescription;
6672        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6673        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6674            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6675            notifySubtreeAccessibilityStateChangedIfNeeded();
6676        } else {
6677            notifyViewAccessibilityStateChangedIfNeeded(
6678                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6679        }
6680    }
6681
6682    /**
6683     * Sets the id of a view before which this one is visited in accessibility traversal.
6684     * A screen-reader must visit the content of this view before the content of the one
6685     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6686     * will traverse the entire content of B before traversing the entire content of A,
6687     * regardles of what traversal strategy it is using.
6688     * <p>
6689     * Views that do not have specified before/after relationships are traversed in order
6690     * determined by the screen-reader.
6691     * </p>
6692     * <p>
6693     * Setting that this view is before a view that is not important for accessibility
6694     * or if this view is not important for accessibility will have no effect as the
6695     * screen-reader is not aware of unimportant views.
6696     * </p>
6697     *
6698     * @param beforeId The id of a view this one precedes in accessibility traversal.
6699     *
6700     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6701     *
6702     * @see #setImportantForAccessibility(int)
6703     */
6704    @RemotableViewMethod
6705    public void setAccessibilityTraversalBefore(int beforeId) {
6706        if (mAccessibilityTraversalBeforeId == beforeId) {
6707            return;
6708        }
6709        mAccessibilityTraversalBeforeId = beforeId;
6710        notifyViewAccessibilityStateChangedIfNeeded(
6711                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6712    }
6713
6714    /**
6715     * Gets the id of a view before which this one is visited in accessibility traversal.
6716     *
6717     * @return The id of a view this one precedes in accessibility traversal if
6718     *         specified, otherwise {@link #NO_ID}.
6719     *
6720     * @see #setAccessibilityTraversalBefore(int)
6721     */
6722    public int getAccessibilityTraversalBefore() {
6723        return mAccessibilityTraversalBeforeId;
6724    }
6725
6726    /**
6727     * Sets the id of a view after which this one is visited in accessibility traversal.
6728     * A screen-reader must visit the content of the other view before the content of this
6729     * one. For example, if view B is set to be after view A, then a screen-reader
6730     * will traverse the entire content of A before traversing the entire content of B,
6731     * regardles of what traversal strategy it is using.
6732     * <p>
6733     * Views that do not have specified before/after relationships are traversed in order
6734     * determined by the screen-reader.
6735     * </p>
6736     * <p>
6737     * Setting that this view is after a view that is not important for accessibility
6738     * or if this view is not important for accessibility will have no effect as the
6739     * screen-reader is not aware of unimportant views.
6740     * </p>
6741     *
6742     * @param afterId The id of a view this one succedees in accessibility traversal.
6743     *
6744     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6745     *
6746     * @see #setImportantForAccessibility(int)
6747     */
6748    @RemotableViewMethod
6749    public void setAccessibilityTraversalAfter(int afterId) {
6750        if (mAccessibilityTraversalAfterId == afterId) {
6751            return;
6752        }
6753        mAccessibilityTraversalAfterId = afterId;
6754        notifyViewAccessibilityStateChangedIfNeeded(
6755                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6756    }
6757
6758    /**
6759     * Gets the id of a view after which this one is visited in accessibility traversal.
6760     *
6761     * @return The id of a view this one succeedes in accessibility traversal if
6762     *         specified, otherwise {@link #NO_ID}.
6763     *
6764     * @see #setAccessibilityTraversalAfter(int)
6765     */
6766    public int getAccessibilityTraversalAfter() {
6767        return mAccessibilityTraversalAfterId;
6768    }
6769
6770    /**
6771     * Gets the id of a view for which this view serves as a label for
6772     * accessibility purposes.
6773     *
6774     * @return The labeled view id.
6775     */
6776    @ViewDebug.ExportedProperty(category = "accessibility")
6777    public int getLabelFor() {
6778        return mLabelForId;
6779    }
6780
6781    /**
6782     * Sets the id of a view for which this view serves as a label for
6783     * accessibility purposes.
6784     *
6785     * @param id The labeled view id.
6786     */
6787    @RemotableViewMethod
6788    public void setLabelFor(@IdRes int id) {
6789        if (mLabelForId == id) {
6790            return;
6791        }
6792        mLabelForId = id;
6793        if (mLabelForId != View.NO_ID
6794                && mID == View.NO_ID) {
6795            mID = generateViewId();
6796        }
6797        notifyViewAccessibilityStateChangedIfNeeded(
6798                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6799    }
6800
6801    /**
6802     * Invoked whenever this view loses focus, either by losing window focus or by losing
6803     * focus within its window. This method can be used to clear any state tied to the
6804     * focus. For instance, if a button is held pressed with the trackball and the window
6805     * loses focus, this method can be used to cancel the press.
6806     *
6807     * Subclasses of View overriding this method should always call super.onFocusLost().
6808     *
6809     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6810     * @see #onWindowFocusChanged(boolean)
6811     *
6812     * @hide pending API council approval
6813     */
6814    @CallSuper
6815    protected void onFocusLost() {
6816        resetPressedState();
6817    }
6818
6819    private void resetPressedState() {
6820        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6821            return;
6822        }
6823
6824        if (isPressed()) {
6825            setPressed(false);
6826
6827            if (!mHasPerformedLongPress) {
6828                removeLongPressCallback();
6829            }
6830        }
6831    }
6832
6833    /**
6834     * Returns true if this view has focus
6835     *
6836     * @return True if this view has focus, false otherwise.
6837     */
6838    @ViewDebug.ExportedProperty(category = "focus")
6839    public boolean isFocused() {
6840        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6841    }
6842
6843    /**
6844     * Find the view in the hierarchy rooted at this view that currently has
6845     * focus.
6846     *
6847     * @return The view that currently has focus, or null if no focused view can
6848     *         be found.
6849     */
6850    public View findFocus() {
6851        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6852    }
6853
6854    /**
6855     * Indicates whether this view is one of the set of scrollable containers in
6856     * its window.
6857     *
6858     * @return whether this view is one of the set of scrollable containers in
6859     * its window
6860     *
6861     * @attr ref android.R.styleable#View_isScrollContainer
6862     */
6863    public boolean isScrollContainer() {
6864        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6865    }
6866
6867    /**
6868     * Change whether this view is one of the set of scrollable containers in
6869     * its window.  This will be used to determine whether the window can
6870     * resize or must pan when a soft input area is open -- scrollable
6871     * containers allow the window to use resize mode since the container
6872     * will appropriately shrink.
6873     *
6874     * @attr ref android.R.styleable#View_isScrollContainer
6875     */
6876    public void setScrollContainer(boolean isScrollContainer) {
6877        if (isScrollContainer) {
6878            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6879                mAttachInfo.mScrollContainers.add(this);
6880                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6881            }
6882            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6883        } else {
6884            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6885                mAttachInfo.mScrollContainers.remove(this);
6886            }
6887            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6888        }
6889    }
6890
6891    /**
6892     * Returns the quality of the drawing cache.
6893     *
6894     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6895     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6896     *
6897     * @see #setDrawingCacheQuality(int)
6898     * @see #setDrawingCacheEnabled(boolean)
6899     * @see #isDrawingCacheEnabled()
6900     *
6901     * @attr ref android.R.styleable#View_drawingCacheQuality
6902     */
6903    @DrawingCacheQuality
6904    public int getDrawingCacheQuality() {
6905        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6906    }
6907
6908    /**
6909     * Set the drawing cache quality of this view. This value is used only when the
6910     * drawing cache is enabled
6911     *
6912     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6913     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6914     *
6915     * @see #getDrawingCacheQuality()
6916     * @see #setDrawingCacheEnabled(boolean)
6917     * @see #isDrawingCacheEnabled()
6918     *
6919     * @attr ref android.R.styleable#View_drawingCacheQuality
6920     */
6921    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6922        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6923    }
6924
6925    /**
6926     * Returns whether the screen should remain on, corresponding to the current
6927     * value of {@link #KEEP_SCREEN_ON}.
6928     *
6929     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6930     *
6931     * @see #setKeepScreenOn(boolean)
6932     *
6933     * @attr ref android.R.styleable#View_keepScreenOn
6934     */
6935    public boolean getKeepScreenOn() {
6936        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6937    }
6938
6939    /**
6940     * Controls whether the screen should remain on, modifying the
6941     * value of {@link #KEEP_SCREEN_ON}.
6942     *
6943     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6944     *
6945     * @see #getKeepScreenOn()
6946     *
6947     * @attr ref android.R.styleable#View_keepScreenOn
6948     */
6949    public void setKeepScreenOn(boolean keepScreenOn) {
6950        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6951    }
6952
6953    /**
6954     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6955     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6956     *
6957     * @attr ref android.R.styleable#View_nextFocusLeft
6958     */
6959    public int getNextFocusLeftId() {
6960        return mNextFocusLeftId;
6961    }
6962
6963    /**
6964     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6965     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6966     * decide automatically.
6967     *
6968     * @attr ref android.R.styleable#View_nextFocusLeft
6969     */
6970    public void setNextFocusLeftId(int nextFocusLeftId) {
6971        mNextFocusLeftId = nextFocusLeftId;
6972    }
6973
6974    /**
6975     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6976     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6977     *
6978     * @attr ref android.R.styleable#View_nextFocusRight
6979     */
6980    public int getNextFocusRightId() {
6981        return mNextFocusRightId;
6982    }
6983
6984    /**
6985     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6986     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6987     * decide automatically.
6988     *
6989     * @attr ref android.R.styleable#View_nextFocusRight
6990     */
6991    public void setNextFocusRightId(int nextFocusRightId) {
6992        mNextFocusRightId = nextFocusRightId;
6993    }
6994
6995    /**
6996     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6997     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6998     *
6999     * @attr ref android.R.styleable#View_nextFocusUp
7000     */
7001    public int getNextFocusUpId() {
7002        return mNextFocusUpId;
7003    }
7004
7005    /**
7006     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7007     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7008     * decide automatically.
7009     *
7010     * @attr ref android.R.styleable#View_nextFocusUp
7011     */
7012    public void setNextFocusUpId(int nextFocusUpId) {
7013        mNextFocusUpId = nextFocusUpId;
7014    }
7015
7016    /**
7017     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7018     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7019     *
7020     * @attr ref android.R.styleable#View_nextFocusDown
7021     */
7022    public int getNextFocusDownId() {
7023        return mNextFocusDownId;
7024    }
7025
7026    /**
7027     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7028     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7029     * decide automatically.
7030     *
7031     * @attr ref android.R.styleable#View_nextFocusDown
7032     */
7033    public void setNextFocusDownId(int nextFocusDownId) {
7034        mNextFocusDownId = nextFocusDownId;
7035    }
7036
7037    /**
7038     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7039     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7040     *
7041     * @attr ref android.R.styleable#View_nextFocusForward
7042     */
7043    public int getNextFocusForwardId() {
7044        return mNextFocusForwardId;
7045    }
7046
7047    /**
7048     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7049     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7050     * decide automatically.
7051     *
7052     * @attr ref android.R.styleable#View_nextFocusForward
7053     */
7054    public void setNextFocusForwardId(int nextFocusForwardId) {
7055        mNextFocusForwardId = nextFocusForwardId;
7056    }
7057
7058    /**
7059     * Returns the visibility of this view and all of its ancestors
7060     *
7061     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7062     */
7063    public boolean isShown() {
7064        View current = this;
7065        //noinspection ConstantConditions
7066        do {
7067            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7068                return false;
7069            }
7070            ViewParent parent = current.mParent;
7071            if (parent == null) {
7072                return false; // We are not attached to the view root
7073            }
7074            if (!(parent instanceof View)) {
7075                return true;
7076            }
7077            current = (View) parent;
7078        } while (current != null);
7079
7080        return false;
7081    }
7082
7083    /**
7084     * Called by the view hierarchy when the content insets for a window have
7085     * changed, to allow it to adjust its content to fit within those windows.
7086     * The content insets tell you the space that the status bar, input method,
7087     * and other system windows infringe on the application's window.
7088     *
7089     * <p>You do not normally need to deal with this function, since the default
7090     * window decoration given to applications takes care of applying it to the
7091     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7092     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7093     * and your content can be placed under those system elements.  You can then
7094     * use this method within your view hierarchy if you have parts of your UI
7095     * which you would like to ensure are not being covered.
7096     *
7097     * <p>The default implementation of this method simply applies the content
7098     * insets to the view's padding, consuming that content (modifying the
7099     * insets to be 0), and returning true.  This behavior is off by default, but can
7100     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7101     *
7102     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7103     * insets object is propagated down the hierarchy, so any changes made to it will
7104     * be seen by all following views (including potentially ones above in
7105     * the hierarchy since this is a depth-first traversal).  The first view
7106     * that returns true will abort the entire traversal.
7107     *
7108     * <p>The default implementation works well for a situation where it is
7109     * used with a container that covers the entire window, allowing it to
7110     * apply the appropriate insets to its content on all edges.  If you need
7111     * a more complicated layout (such as two different views fitting system
7112     * windows, one on the top of the window, and one on the bottom),
7113     * you can override the method and handle the insets however you would like.
7114     * Note that the insets provided by the framework are always relative to the
7115     * far edges of the window, not accounting for the location of the called view
7116     * within that window.  (In fact when this method is called you do not yet know
7117     * where the layout will place the view, as it is done before layout happens.)
7118     *
7119     * <p>Note: unlike many View methods, there is no dispatch phase to this
7120     * call.  If you are overriding it in a ViewGroup and want to allow the
7121     * call to continue to your children, you must be sure to call the super
7122     * implementation.
7123     *
7124     * <p>Here is a sample layout that makes use of fitting system windows
7125     * to have controls for a video view placed inside of the window decorations
7126     * that it hides and shows.  This can be used with code like the second
7127     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7128     *
7129     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7130     *
7131     * @param insets Current content insets of the window.  Prior to
7132     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7133     * the insets or else you and Android will be unhappy.
7134     *
7135     * @return {@code true} if this view applied the insets and it should not
7136     * continue propagating further down the hierarchy, {@code false} otherwise.
7137     * @see #getFitsSystemWindows()
7138     * @see #setFitsSystemWindows(boolean)
7139     * @see #setSystemUiVisibility(int)
7140     *
7141     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7142     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7143     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7144     * to implement handling their own insets.
7145     */
7146    protected boolean fitSystemWindows(Rect insets) {
7147        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7148            if (insets == null) {
7149                // Null insets by definition have already been consumed.
7150                // This call cannot apply insets since there are none to apply,
7151                // so return false.
7152                return false;
7153            }
7154            // If we're not in the process of dispatching the newer apply insets call,
7155            // that means we're not in the compatibility path. Dispatch into the newer
7156            // apply insets path and take things from there.
7157            try {
7158                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7159                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7160            } finally {
7161                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7162            }
7163        } else {
7164            // We're being called from the newer apply insets path.
7165            // Perform the standard fallback behavior.
7166            return fitSystemWindowsInt(insets);
7167        }
7168    }
7169
7170    private boolean fitSystemWindowsInt(Rect insets) {
7171        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7172            mUserPaddingStart = UNDEFINED_PADDING;
7173            mUserPaddingEnd = UNDEFINED_PADDING;
7174            Rect localInsets = sThreadLocal.get();
7175            if (localInsets == null) {
7176                localInsets = new Rect();
7177                sThreadLocal.set(localInsets);
7178            }
7179            boolean res = computeFitSystemWindows(insets, localInsets);
7180            mUserPaddingLeftInitial = localInsets.left;
7181            mUserPaddingRightInitial = localInsets.right;
7182            internalSetPadding(localInsets.left, localInsets.top,
7183                    localInsets.right, localInsets.bottom);
7184            return res;
7185        }
7186        return false;
7187    }
7188
7189    /**
7190     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7191     *
7192     * <p>This method should be overridden by views that wish to apply a policy different from or
7193     * in addition to the default behavior. Clients that wish to force a view subtree
7194     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7195     *
7196     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7197     * it will be called during dispatch instead of this method. The listener may optionally
7198     * call this method from its own implementation if it wishes to apply the view's default
7199     * insets policy in addition to its own.</p>
7200     *
7201     * <p>Implementations of this method should either return the insets parameter unchanged
7202     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7203     * that this view applied itself. This allows new inset types added in future platform
7204     * versions to pass through existing implementations unchanged without being erroneously
7205     * consumed.</p>
7206     *
7207     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7208     * property is set then the view will consume the system window insets and apply them
7209     * as padding for the view.</p>
7210     *
7211     * @param insets Insets to apply
7212     * @return The supplied insets with any applied insets consumed
7213     */
7214    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7215        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7216            // We weren't called from within a direct call to fitSystemWindows,
7217            // call into it as a fallback in case we're in a class that overrides it
7218            // and has logic to perform.
7219            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7220                return insets.consumeSystemWindowInsets();
7221            }
7222        } else {
7223            // We were called from within a direct call to fitSystemWindows.
7224            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7225                return insets.consumeSystemWindowInsets();
7226            }
7227        }
7228        return insets;
7229    }
7230
7231    /**
7232     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7233     * window insets to this view. The listener's
7234     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7235     * method will be called instead of the view's
7236     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7237     *
7238     * @param listener Listener to set
7239     *
7240     * @see #onApplyWindowInsets(WindowInsets)
7241     */
7242    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7243        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7244    }
7245
7246    /**
7247     * Request to apply the given window insets to this view or another view in its subtree.
7248     *
7249     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7250     * obscured by window decorations or overlays. This can include the status and navigation bars,
7251     * action bars, input methods and more. New inset categories may be added in the future.
7252     * The method returns the insets provided minus any that were applied by this view or its
7253     * children.</p>
7254     *
7255     * <p>Clients wishing to provide custom behavior should override the
7256     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7257     * {@link OnApplyWindowInsetsListener} via the
7258     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7259     * method.</p>
7260     *
7261     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7262     * </p>
7263     *
7264     * @param insets Insets to apply
7265     * @return The provided insets minus the insets that were consumed
7266     */
7267    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7268        try {
7269            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7270            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7271                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7272            } else {
7273                return onApplyWindowInsets(insets);
7274            }
7275        } finally {
7276            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7277        }
7278    }
7279
7280    /**
7281     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7282     * only available if the view is attached.
7283     *
7284     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7285     */
7286    public WindowInsets getRootWindowInsets() {
7287        if (mAttachInfo != null) {
7288            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7289        }
7290        return null;
7291    }
7292
7293    /**
7294     * @hide Compute the insets that should be consumed by this view and the ones
7295     * that should propagate to those under it.
7296     */
7297    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7298        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7299                || mAttachInfo == null
7300                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7301                        && !mAttachInfo.mOverscanRequested)) {
7302            outLocalInsets.set(inoutInsets);
7303            inoutInsets.set(0, 0, 0, 0);
7304            return true;
7305        } else {
7306            // The application wants to take care of fitting system window for
7307            // the content...  however we still need to take care of any overscan here.
7308            final Rect overscan = mAttachInfo.mOverscanInsets;
7309            outLocalInsets.set(overscan);
7310            inoutInsets.left -= overscan.left;
7311            inoutInsets.top -= overscan.top;
7312            inoutInsets.right -= overscan.right;
7313            inoutInsets.bottom -= overscan.bottom;
7314            return false;
7315        }
7316    }
7317
7318    /**
7319     * Compute insets that should be consumed by this view and the ones that should propagate
7320     * to those under it.
7321     *
7322     * @param in Insets currently being processed by this View, likely received as a parameter
7323     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7324     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7325     *                       by this view
7326     * @return Insets that should be passed along to views under this one
7327     */
7328    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7329        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7330                || mAttachInfo == null
7331                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7332            outLocalInsets.set(in.getSystemWindowInsets());
7333            return in.consumeSystemWindowInsets();
7334        } else {
7335            outLocalInsets.set(0, 0, 0, 0);
7336            return in;
7337        }
7338    }
7339
7340    /**
7341     * Sets whether or not this view should account for system screen decorations
7342     * such as the status bar and inset its content; that is, controlling whether
7343     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7344     * executed.  See that method for more details.
7345     *
7346     * <p>Note that if you are providing your own implementation of
7347     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7348     * flag to true -- your implementation will be overriding the default
7349     * implementation that checks this flag.
7350     *
7351     * @param fitSystemWindows If true, then the default implementation of
7352     * {@link #fitSystemWindows(Rect)} will be executed.
7353     *
7354     * @attr ref android.R.styleable#View_fitsSystemWindows
7355     * @see #getFitsSystemWindows()
7356     * @see #fitSystemWindows(Rect)
7357     * @see #setSystemUiVisibility(int)
7358     */
7359    public void setFitsSystemWindows(boolean fitSystemWindows) {
7360        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7361    }
7362
7363    /**
7364     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7365     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7366     * will be executed.
7367     *
7368     * @return {@code true} if the default implementation of
7369     * {@link #fitSystemWindows(Rect)} will be executed.
7370     *
7371     * @attr ref android.R.styleable#View_fitsSystemWindows
7372     * @see #setFitsSystemWindows(boolean)
7373     * @see #fitSystemWindows(Rect)
7374     * @see #setSystemUiVisibility(int)
7375     */
7376    @ViewDebug.ExportedProperty
7377    public boolean getFitsSystemWindows() {
7378        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7379    }
7380
7381    /** @hide */
7382    public boolean fitsSystemWindows() {
7383        return getFitsSystemWindows();
7384    }
7385
7386    /**
7387     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7388     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7389     */
7390    public void requestFitSystemWindows() {
7391        if (mParent != null) {
7392            mParent.requestFitSystemWindows();
7393        }
7394    }
7395
7396    /**
7397     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7398     */
7399    public void requestApplyInsets() {
7400        requestFitSystemWindows();
7401    }
7402
7403    /**
7404     * For use by PhoneWindow to make its own system window fitting optional.
7405     * @hide
7406     */
7407    public void makeOptionalFitsSystemWindows() {
7408        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7409    }
7410
7411    /**
7412     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7413     * treat them as such.
7414     * @hide
7415     */
7416    public void getOutsets(Rect outOutsetRect) {
7417        if (mAttachInfo != null) {
7418            outOutsetRect.set(mAttachInfo.mOutsets);
7419        } else {
7420            outOutsetRect.setEmpty();
7421        }
7422    }
7423
7424    /**
7425     * Returns the visibility status for this view.
7426     *
7427     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7428     * @attr ref android.R.styleable#View_visibility
7429     */
7430    @ViewDebug.ExportedProperty(mapping = {
7431        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7432        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7433        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7434    })
7435    @Visibility
7436    public int getVisibility() {
7437        return mViewFlags & VISIBILITY_MASK;
7438    }
7439
7440    /**
7441     * Set the enabled state of this view.
7442     *
7443     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7444     * @attr ref android.R.styleable#View_visibility
7445     */
7446    @RemotableViewMethod
7447    public void setVisibility(@Visibility int visibility) {
7448        setFlags(visibility, VISIBILITY_MASK);
7449    }
7450
7451    /**
7452     * Returns the enabled status for this view. The interpretation of the
7453     * enabled state varies by subclass.
7454     *
7455     * @return True if this view is enabled, false otherwise.
7456     */
7457    @ViewDebug.ExportedProperty
7458    public boolean isEnabled() {
7459        return (mViewFlags & ENABLED_MASK) == ENABLED;
7460    }
7461
7462    /**
7463     * Set the enabled state of this view. The interpretation of the enabled
7464     * state varies by subclass.
7465     *
7466     * @param enabled True if this view is enabled, false otherwise.
7467     */
7468    @RemotableViewMethod
7469    public void setEnabled(boolean enabled) {
7470        if (enabled == isEnabled()) return;
7471
7472        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7473
7474        /*
7475         * The View most likely has to change its appearance, so refresh
7476         * the drawable state.
7477         */
7478        refreshDrawableState();
7479
7480        // Invalidate too, since the default behavior for views is to be
7481        // be drawn at 50% alpha rather than to change the drawable.
7482        invalidate(true);
7483
7484        if (!enabled) {
7485            cancelPendingInputEvents();
7486        }
7487    }
7488
7489    /**
7490     * Set whether this view can receive the focus.
7491     *
7492     * Setting this to false will also ensure that this view is not focusable
7493     * in touch mode.
7494     *
7495     * @param focusable If true, this view can receive the focus.
7496     *
7497     * @see #setFocusableInTouchMode(boolean)
7498     * @attr ref android.R.styleable#View_focusable
7499     */
7500    public void setFocusable(boolean focusable) {
7501        if (!focusable) {
7502            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7503        }
7504        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7505    }
7506
7507    /**
7508     * Set whether this view can receive focus while in touch mode.
7509     *
7510     * Setting this to true will also ensure that this view is focusable.
7511     *
7512     * @param focusableInTouchMode If true, this view can receive the focus while
7513     *   in touch mode.
7514     *
7515     * @see #setFocusable(boolean)
7516     * @attr ref android.R.styleable#View_focusableInTouchMode
7517     */
7518    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7519        // Focusable in touch mode should always be set before the focusable flag
7520        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7521        // which, in touch mode, will not successfully request focus on this view
7522        // because the focusable in touch mode flag is not set
7523        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7524        if (focusableInTouchMode) {
7525            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7526        }
7527    }
7528
7529    /**
7530     * Set whether this view should have sound effects enabled for events such as
7531     * clicking and touching.
7532     *
7533     * <p>You may wish to disable sound effects for a view if you already play sounds,
7534     * for instance, a dial key that plays dtmf tones.
7535     *
7536     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7537     * @see #isSoundEffectsEnabled()
7538     * @see #playSoundEffect(int)
7539     * @attr ref android.R.styleable#View_soundEffectsEnabled
7540     */
7541    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7542        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7543    }
7544
7545    /**
7546     * @return whether this view should have sound effects enabled for events such as
7547     *     clicking and touching.
7548     *
7549     * @see #setSoundEffectsEnabled(boolean)
7550     * @see #playSoundEffect(int)
7551     * @attr ref android.R.styleable#View_soundEffectsEnabled
7552     */
7553    @ViewDebug.ExportedProperty
7554    public boolean isSoundEffectsEnabled() {
7555        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7556    }
7557
7558    /**
7559     * Set whether this view should have haptic feedback for events such as
7560     * long presses.
7561     *
7562     * <p>You may wish to disable haptic feedback if your view already controls
7563     * its own haptic feedback.
7564     *
7565     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7566     * @see #isHapticFeedbackEnabled()
7567     * @see #performHapticFeedback(int)
7568     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7569     */
7570    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7571        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7572    }
7573
7574    /**
7575     * @return whether this view should have haptic feedback enabled for events
7576     * long presses.
7577     *
7578     * @see #setHapticFeedbackEnabled(boolean)
7579     * @see #performHapticFeedback(int)
7580     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7581     */
7582    @ViewDebug.ExportedProperty
7583    public boolean isHapticFeedbackEnabled() {
7584        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7585    }
7586
7587    /**
7588     * Returns the layout direction for this view.
7589     *
7590     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7591     *   {@link #LAYOUT_DIRECTION_RTL},
7592     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7593     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7594     *
7595     * @attr ref android.R.styleable#View_layoutDirection
7596     *
7597     * @hide
7598     */
7599    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7600        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7601        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7602        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7603        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7604    })
7605    @LayoutDir
7606    public int getRawLayoutDirection() {
7607        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7608    }
7609
7610    /**
7611     * Set the layout direction for this view. This will propagate a reset of layout direction
7612     * resolution to the view's children and resolve layout direction for this view.
7613     *
7614     * @param layoutDirection the layout direction to set. Should be one of:
7615     *
7616     * {@link #LAYOUT_DIRECTION_LTR},
7617     * {@link #LAYOUT_DIRECTION_RTL},
7618     * {@link #LAYOUT_DIRECTION_INHERIT},
7619     * {@link #LAYOUT_DIRECTION_LOCALE}.
7620     *
7621     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7622     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7623     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7624     *
7625     * @attr ref android.R.styleable#View_layoutDirection
7626     */
7627    @RemotableViewMethod
7628    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7629        if (getRawLayoutDirection() != layoutDirection) {
7630            // Reset the current layout direction and the resolved one
7631            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7632            resetRtlProperties();
7633            // Set the new layout direction (filtered)
7634            mPrivateFlags2 |=
7635                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7636            // We need to resolve all RTL properties as they all depend on layout direction
7637            resolveRtlPropertiesIfNeeded();
7638            requestLayout();
7639            invalidate(true);
7640        }
7641    }
7642
7643    /**
7644     * Returns the resolved layout direction for this view.
7645     *
7646     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7647     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7648     *
7649     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7650     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7651     *
7652     * @attr ref android.R.styleable#View_layoutDirection
7653     */
7654    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7655        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7656        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7657    })
7658    @ResolvedLayoutDir
7659    public int getLayoutDirection() {
7660        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7661        if (targetSdkVersion < JELLY_BEAN_MR1) {
7662            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7663            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7664        }
7665        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7666                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7667    }
7668
7669    /**
7670     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7671     * layout attribute and/or the inherited value from the parent
7672     *
7673     * @return true if the layout is right-to-left.
7674     *
7675     * @hide
7676     */
7677    @ViewDebug.ExportedProperty(category = "layout")
7678    public boolean isLayoutRtl() {
7679        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7680    }
7681
7682    /**
7683     * Indicates whether the view is currently tracking transient state that the
7684     * app should not need to concern itself with saving and restoring, but that
7685     * the framework should take special note to preserve when possible.
7686     *
7687     * <p>A view with transient state cannot be trivially rebound from an external
7688     * data source, such as an adapter binding item views in a list. This may be
7689     * because the view is performing an animation, tracking user selection
7690     * of content, or similar.</p>
7691     *
7692     * @return true if the view has transient state
7693     */
7694    @ViewDebug.ExportedProperty(category = "layout")
7695    public boolean hasTransientState() {
7696        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7697    }
7698
7699    /**
7700     * Set whether this view is currently tracking transient state that the
7701     * framework should attempt to preserve when possible. This flag is reference counted,
7702     * so every call to setHasTransientState(true) should be paired with a later call
7703     * to setHasTransientState(false).
7704     *
7705     * <p>A view with transient state cannot be trivially rebound from an external
7706     * data source, such as an adapter binding item views in a list. This may be
7707     * because the view is performing an animation, tracking user selection
7708     * of content, or similar.</p>
7709     *
7710     * @param hasTransientState true if this view has transient state
7711     */
7712    public void setHasTransientState(boolean hasTransientState) {
7713        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7714                mTransientStateCount - 1;
7715        if (mTransientStateCount < 0) {
7716            mTransientStateCount = 0;
7717            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7718                    "unmatched pair of setHasTransientState calls");
7719        } else if ((hasTransientState && mTransientStateCount == 1) ||
7720                (!hasTransientState && mTransientStateCount == 0)) {
7721            // update flag if we've just incremented up from 0 or decremented down to 0
7722            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7723                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7724            if (mParent != null) {
7725                try {
7726                    mParent.childHasTransientStateChanged(this, hasTransientState);
7727                } catch (AbstractMethodError e) {
7728                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7729                            " does not fully implement ViewParent", e);
7730                }
7731            }
7732        }
7733    }
7734
7735    /**
7736     * Returns true if this view is currently attached to a window.
7737     */
7738    public boolean isAttachedToWindow() {
7739        return mAttachInfo != null;
7740    }
7741
7742    /**
7743     * Returns true if this view has been through at least one layout since it
7744     * was last attached to or detached from a window.
7745     */
7746    public boolean isLaidOut() {
7747        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7748    }
7749
7750    /**
7751     * If this view doesn't do any drawing on its own, set this flag to
7752     * allow further optimizations. By default, this flag is not set on
7753     * View, but could be set on some View subclasses such as ViewGroup.
7754     *
7755     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7756     * you should clear this flag.
7757     *
7758     * @param willNotDraw whether or not this View draw on its own
7759     */
7760    public void setWillNotDraw(boolean willNotDraw) {
7761        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7762    }
7763
7764    /**
7765     * Returns whether or not this View draws on its own.
7766     *
7767     * @return true if this view has nothing to draw, false otherwise
7768     */
7769    @ViewDebug.ExportedProperty(category = "drawing")
7770    public boolean willNotDraw() {
7771        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7772    }
7773
7774    /**
7775     * When a View's drawing cache is enabled, drawing is redirected to an
7776     * offscreen bitmap. Some views, like an ImageView, must be able to
7777     * bypass this mechanism if they already draw a single bitmap, to avoid
7778     * unnecessary usage of the memory.
7779     *
7780     * @param willNotCacheDrawing true if this view does not cache its
7781     *        drawing, false otherwise
7782     */
7783    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7784        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7785    }
7786
7787    /**
7788     * Returns whether or not this View can cache its drawing or not.
7789     *
7790     * @return true if this view does not cache its drawing, false otherwise
7791     */
7792    @ViewDebug.ExportedProperty(category = "drawing")
7793    public boolean willNotCacheDrawing() {
7794        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7795    }
7796
7797    /**
7798     * Indicates whether this view reacts to click events or not.
7799     *
7800     * @return true if the view is clickable, false otherwise
7801     *
7802     * @see #setClickable(boolean)
7803     * @attr ref android.R.styleable#View_clickable
7804     */
7805    @ViewDebug.ExportedProperty
7806    public boolean isClickable() {
7807        return (mViewFlags & CLICKABLE) == CLICKABLE;
7808    }
7809
7810    /**
7811     * Enables or disables click events for this view. When a view
7812     * is clickable it will change its state to "pressed" on every click.
7813     * Subclasses should set the view clickable to visually react to
7814     * user's clicks.
7815     *
7816     * @param clickable true to make the view clickable, false otherwise
7817     *
7818     * @see #isClickable()
7819     * @attr ref android.R.styleable#View_clickable
7820     */
7821    public void setClickable(boolean clickable) {
7822        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7823    }
7824
7825    /**
7826     * Indicates whether this view reacts to long click events or not.
7827     *
7828     * @return true if the view is long clickable, false otherwise
7829     *
7830     * @see #setLongClickable(boolean)
7831     * @attr ref android.R.styleable#View_longClickable
7832     */
7833    public boolean isLongClickable() {
7834        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7835    }
7836
7837    /**
7838     * Enables or disables long click events for this view. When a view is long
7839     * clickable it reacts to the user holding down the button for a longer
7840     * duration than a tap. This event can either launch the listener or a
7841     * context menu.
7842     *
7843     * @param longClickable true to make the view long clickable, false otherwise
7844     * @see #isLongClickable()
7845     * @attr ref android.R.styleable#View_longClickable
7846     */
7847    public void setLongClickable(boolean longClickable) {
7848        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7849    }
7850
7851    /**
7852     * Indicates whether this view reacts to context clicks or not.
7853     *
7854     * @return true if the view is context clickable, false otherwise
7855     * @see #setContextClickable(boolean)
7856     * @attr ref android.R.styleable#View_contextClickable
7857     */
7858    public boolean isContextClickable() {
7859        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
7860    }
7861
7862    /**
7863     * Enables or disables context clicking for this view. This event can launch the listener.
7864     *
7865     * @param contextClickable true to make the view react to a context click, false otherwise
7866     * @see #isContextClickable()
7867     * @attr ref android.R.styleable#View_contextClickable
7868     */
7869    public void setContextClickable(boolean contextClickable) {
7870        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
7871    }
7872
7873    /**
7874     * Sets the pressed state for this view and provides a touch coordinate for
7875     * animation hinting.
7876     *
7877     * @param pressed Pass true to set the View's internal state to "pressed",
7878     *            or false to reverts the View's internal state from a
7879     *            previously set "pressed" state.
7880     * @param x The x coordinate of the touch that caused the press
7881     * @param y The y coordinate of the touch that caused the press
7882     */
7883    private void setPressed(boolean pressed, float x, float y) {
7884        if (pressed) {
7885            drawableHotspotChanged(x, y);
7886        }
7887
7888        setPressed(pressed);
7889    }
7890
7891    /**
7892     * Sets the pressed state for this view.
7893     *
7894     * @see #isClickable()
7895     * @see #setClickable(boolean)
7896     *
7897     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7898     *        the View's internal state from a previously set "pressed" state.
7899     */
7900    public void setPressed(boolean pressed) {
7901        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7902
7903        if (pressed) {
7904            mPrivateFlags |= PFLAG_PRESSED;
7905        } else {
7906            mPrivateFlags &= ~PFLAG_PRESSED;
7907        }
7908
7909        if (needsRefresh) {
7910            refreshDrawableState();
7911        }
7912        dispatchSetPressed(pressed);
7913    }
7914
7915    /**
7916     * Dispatch setPressed to all of this View's children.
7917     *
7918     * @see #setPressed(boolean)
7919     *
7920     * @param pressed The new pressed state
7921     */
7922    protected void dispatchSetPressed(boolean pressed) {
7923    }
7924
7925    /**
7926     * Indicates whether the view is currently in pressed state. Unless
7927     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7928     * the pressed state.
7929     *
7930     * @see #setPressed(boolean)
7931     * @see #isClickable()
7932     * @see #setClickable(boolean)
7933     *
7934     * @return true if the view is currently pressed, false otherwise
7935     */
7936    @ViewDebug.ExportedProperty
7937    public boolean isPressed() {
7938        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7939    }
7940
7941    /**
7942     * @hide
7943     * Indicates whether this view will participate in data collection through
7944     * {@link ViewStructure}.  If true, it will not provide any data
7945     * for itself or its children.  If false, the normal data collection will be allowed.
7946     *
7947     * @return Returns false if assist data collection is not blocked, else true.
7948     *
7949     * @see #setAssistBlocked(boolean)
7950     * @attr ref android.R.styleable#View_assistBlocked
7951     */
7952    public boolean isAssistBlocked() {
7953        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7954    }
7955
7956    /**
7957     * @hide
7958     * Controls whether assist data collection from this view and its children is enabled
7959     * (that is, whether {@link #onProvideStructure} and
7960     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
7961     * allowing normal assist collection.  Setting this to false will disable assist collection.
7962     *
7963     * @param enabled Set to true to <em>disable</em> assist data collection, or false
7964     * (the default) to allow it.
7965     *
7966     * @see #isAssistBlocked()
7967     * @see #onProvideStructure
7968     * @see #onProvideVirtualStructure
7969     * @attr ref android.R.styleable#View_assistBlocked
7970     */
7971    public void setAssistBlocked(boolean enabled) {
7972        if (enabled) {
7973            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7974        } else {
7975            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7976        }
7977    }
7978
7979    /**
7980     * Indicates whether this view will save its state (that is,
7981     * whether its {@link #onSaveInstanceState} method will be called).
7982     *
7983     * @return Returns true if the view state saving is enabled, else false.
7984     *
7985     * @see #setSaveEnabled(boolean)
7986     * @attr ref android.R.styleable#View_saveEnabled
7987     */
7988    public boolean isSaveEnabled() {
7989        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7990    }
7991
7992    /**
7993     * Controls whether the saving of this view's state is
7994     * enabled (that is, whether its {@link #onSaveInstanceState} method
7995     * will be called).  Note that even if freezing is enabled, the
7996     * view still must have an id assigned to it (via {@link #setId(int)})
7997     * for its state to be saved.  This flag can only disable the
7998     * saving of this view; any child views may still have their state saved.
7999     *
8000     * @param enabled Set to false to <em>disable</em> state saving, or true
8001     * (the default) to allow it.
8002     *
8003     * @see #isSaveEnabled()
8004     * @see #setId(int)
8005     * @see #onSaveInstanceState()
8006     * @attr ref android.R.styleable#View_saveEnabled
8007     */
8008    public void setSaveEnabled(boolean enabled) {
8009        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8010    }
8011
8012    /**
8013     * Gets whether the framework should discard touches when the view's
8014     * window is obscured by another visible window.
8015     * Refer to the {@link View} security documentation for more details.
8016     *
8017     * @return True if touch filtering is enabled.
8018     *
8019     * @see #setFilterTouchesWhenObscured(boolean)
8020     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8021     */
8022    @ViewDebug.ExportedProperty
8023    public boolean getFilterTouchesWhenObscured() {
8024        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8025    }
8026
8027    /**
8028     * Sets whether the framework should discard touches when the view's
8029     * window is obscured by another visible window.
8030     * Refer to the {@link View} security documentation for more details.
8031     *
8032     * @param enabled True if touch filtering should be enabled.
8033     *
8034     * @see #getFilterTouchesWhenObscured
8035     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8036     */
8037    public void setFilterTouchesWhenObscured(boolean enabled) {
8038        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8039                FILTER_TOUCHES_WHEN_OBSCURED);
8040    }
8041
8042    /**
8043     * Indicates whether the entire hierarchy under this view will save its
8044     * state when a state saving traversal occurs from its parent.  The default
8045     * is true; if false, these views will not be saved unless
8046     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8047     *
8048     * @return Returns true if the view state saving from parent is enabled, else false.
8049     *
8050     * @see #setSaveFromParentEnabled(boolean)
8051     */
8052    public boolean isSaveFromParentEnabled() {
8053        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8054    }
8055
8056    /**
8057     * Controls whether the entire hierarchy under this view will save its
8058     * state when a state saving traversal occurs from its parent.  The default
8059     * is true; if false, these views will not be saved unless
8060     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8061     *
8062     * @param enabled Set to false to <em>disable</em> state saving, or true
8063     * (the default) to allow it.
8064     *
8065     * @see #isSaveFromParentEnabled()
8066     * @see #setId(int)
8067     * @see #onSaveInstanceState()
8068     */
8069    public void setSaveFromParentEnabled(boolean enabled) {
8070        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8071    }
8072
8073
8074    /**
8075     * Returns whether this View is able to take focus.
8076     *
8077     * @return True if this view can take focus, or false otherwise.
8078     * @attr ref android.R.styleable#View_focusable
8079     */
8080    @ViewDebug.ExportedProperty(category = "focus")
8081    public final boolean isFocusable() {
8082        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8083    }
8084
8085    /**
8086     * When a view is focusable, it may not want to take focus when in touch mode.
8087     * For example, a button would like focus when the user is navigating via a D-pad
8088     * so that the user can click on it, but once the user starts touching the screen,
8089     * the button shouldn't take focus
8090     * @return Whether the view is focusable in touch mode.
8091     * @attr ref android.R.styleable#View_focusableInTouchMode
8092     */
8093    @ViewDebug.ExportedProperty
8094    public final boolean isFocusableInTouchMode() {
8095        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8096    }
8097
8098    /**
8099     * Find the nearest view in the specified direction that can take focus.
8100     * This does not actually give focus to that view.
8101     *
8102     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8103     *
8104     * @return The nearest focusable in the specified direction, or null if none
8105     *         can be found.
8106     */
8107    public View focusSearch(@FocusRealDirection int direction) {
8108        if (mParent != null) {
8109            return mParent.focusSearch(this, direction);
8110        } else {
8111            return null;
8112        }
8113    }
8114
8115    /**
8116     * This method is the last chance for the focused view and its ancestors to
8117     * respond to an arrow key. This is called when the focused view did not
8118     * consume the key internally, nor could the view system find a new view in
8119     * the requested direction to give focus to.
8120     *
8121     * @param focused The currently focused view.
8122     * @param direction The direction focus wants to move. One of FOCUS_UP,
8123     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8124     * @return True if the this view consumed this unhandled move.
8125     */
8126    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8127        return false;
8128    }
8129
8130    /**
8131     * If a user manually specified the next view id for a particular direction,
8132     * use the root to look up the view.
8133     * @param root The root view of the hierarchy containing this view.
8134     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8135     * or FOCUS_BACKWARD.
8136     * @return The user specified next view, or null if there is none.
8137     */
8138    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8139        switch (direction) {
8140            case FOCUS_LEFT:
8141                if (mNextFocusLeftId == View.NO_ID) return null;
8142                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8143            case FOCUS_RIGHT:
8144                if (mNextFocusRightId == View.NO_ID) return null;
8145                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8146            case FOCUS_UP:
8147                if (mNextFocusUpId == View.NO_ID) return null;
8148                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8149            case FOCUS_DOWN:
8150                if (mNextFocusDownId == View.NO_ID) return null;
8151                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8152            case FOCUS_FORWARD:
8153                if (mNextFocusForwardId == View.NO_ID) return null;
8154                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8155            case FOCUS_BACKWARD: {
8156                if (mID == View.NO_ID) return null;
8157                final int id = mID;
8158                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8159                    @Override
8160                    public boolean apply(View t) {
8161                        return t.mNextFocusForwardId == id;
8162                    }
8163                });
8164            }
8165        }
8166        return null;
8167    }
8168
8169    private View findViewInsideOutShouldExist(View root, int id) {
8170        if (mMatchIdPredicate == null) {
8171            mMatchIdPredicate = new MatchIdPredicate();
8172        }
8173        mMatchIdPredicate.mId = id;
8174        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8175        if (result == null) {
8176            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8177        }
8178        return result;
8179    }
8180
8181    /**
8182     * Find and return all focusable views that are descendants of this view,
8183     * possibly including this view if it is focusable itself.
8184     *
8185     * @param direction The direction of the focus
8186     * @return A list of focusable views
8187     */
8188    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8189        ArrayList<View> result = new ArrayList<View>(24);
8190        addFocusables(result, direction);
8191        return result;
8192    }
8193
8194    /**
8195     * Add any focusable views that are descendants of this view (possibly
8196     * including this view if it is focusable itself) to views.  If we are in touch mode,
8197     * only add views that are also focusable in touch mode.
8198     *
8199     * @param views Focusable views found so far
8200     * @param direction The direction of the focus
8201     */
8202    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8203        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8204    }
8205
8206    /**
8207     * Adds any focusable views that are descendants of this view (possibly
8208     * including this view if it is focusable itself) to views. This method
8209     * adds all focusable views regardless if we are in touch mode or
8210     * only views focusable in touch mode if we are in touch mode or
8211     * only views that can take accessibility focus if accessibility is enabled
8212     * depending on the focusable mode parameter.
8213     *
8214     * @param views Focusable views found so far or null if all we are interested is
8215     *        the number of focusables.
8216     * @param direction The direction of the focus.
8217     * @param focusableMode The type of focusables to be added.
8218     *
8219     * @see #FOCUSABLES_ALL
8220     * @see #FOCUSABLES_TOUCH_MODE
8221     */
8222    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8223            @FocusableMode int focusableMode) {
8224        if (views == null) {
8225            return;
8226        }
8227        if (!isFocusable()) {
8228            return;
8229        }
8230        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8231                && isInTouchMode() && !isFocusableInTouchMode()) {
8232            return;
8233        }
8234        views.add(this);
8235    }
8236
8237    /**
8238     * Finds the Views that contain given text. The containment is case insensitive.
8239     * The search is performed by either the text that the View renders or the content
8240     * description that describes the view for accessibility purposes and the view does
8241     * not render or both. Clients can specify how the search is to be performed via
8242     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8243     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8244     *
8245     * @param outViews The output list of matching Views.
8246     * @param searched The text to match against.
8247     *
8248     * @see #FIND_VIEWS_WITH_TEXT
8249     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8250     * @see #setContentDescription(CharSequence)
8251     */
8252    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8253            @FindViewFlags int flags) {
8254        if (getAccessibilityNodeProvider() != null) {
8255            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8256                outViews.add(this);
8257            }
8258        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8259                && (searched != null && searched.length() > 0)
8260                && (mContentDescription != null && mContentDescription.length() > 0)) {
8261            String searchedLowerCase = searched.toString().toLowerCase();
8262            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8263            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8264                outViews.add(this);
8265            }
8266        }
8267    }
8268
8269    /**
8270     * Find and return all touchable views that are descendants of this view,
8271     * possibly including this view if it is touchable itself.
8272     *
8273     * @return A list of touchable views
8274     */
8275    public ArrayList<View> getTouchables() {
8276        ArrayList<View> result = new ArrayList<View>();
8277        addTouchables(result);
8278        return result;
8279    }
8280
8281    /**
8282     * Add any touchable views that are descendants of this view (possibly
8283     * including this view if it is touchable itself) to views.
8284     *
8285     * @param views Touchable views found so far
8286     */
8287    public void addTouchables(ArrayList<View> views) {
8288        final int viewFlags = mViewFlags;
8289
8290        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8291                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8292                && (viewFlags & ENABLED_MASK) == ENABLED) {
8293            views.add(this);
8294        }
8295    }
8296
8297    /**
8298     * Returns whether this View is accessibility focused.
8299     *
8300     * @return True if this View is accessibility focused.
8301     */
8302    public boolean isAccessibilityFocused() {
8303        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8304    }
8305
8306    /**
8307     * Call this to try to give accessibility focus to this view.
8308     *
8309     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8310     * returns false or the view is no visible or the view already has accessibility
8311     * focus.
8312     *
8313     * See also {@link #focusSearch(int)}, which is what you call to say that you
8314     * have focus, and you want your parent to look for the next one.
8315     *
8316     * @return Whether this view actually took accessibility focus.
8317     *
8318     * @hide
8319     */
8320    public boolean requestAccessibilityFocus() {
8321        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8322        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8323            return false;
8324        }
8325        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8326            return false;
8327        }
8328        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8329            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8330            ViewRootImpl viewRootImpl = getViewRootImpl();
8331            if (viewRootImpl != null) {
8332                viewRootImpl.setAccessibilityFocus(this, null);
8333            }
8334            invalidate();
8335            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8336            return true;
8337        }
8338        return false;
8339    }
8340
8341    /**
8342     * Call this to try to clear accessibility focus of this view.
8343     *
8344     * See also {@link #focusSearch(int)}, which is what you call to say that you
8345     * have focus, and you want your parent to look for the next one.
8346     *
8347     * @hide
8348     */
8349    public void clearAccessibilityFocus() {
8350        clearAccessibilityFocusNoCallbacks();
8351        // Clear the global reference of accessibility focus if this
8352        // view or any of its descendants had accessibility focus.
8353        ViewRootImpl viewRootImpl = getViewRootImpl();
8354        if (viewRootImpl != null) {
8355            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8356            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8357                viewRootImpl.setAccessibilityFocus(null, null);
8358            }
8359        }
8360    }
8361
8362    private void sendAccessibilityHoverEvent(int eventType) {
8363        // Since we are not delivering to a client accessibility events from not
8364        // important views (unless the clinet request that) we need to fire the
8365        // event from the deepest view exposed to the client. As a consequence if
8366        // the user crosses a not exposed view the client will see enter and exit
8367        // of the exposed predecessor followed by and enter and exit of that same
8368        // predecessor when entering and exiting the not exposed descendant. This
8369        // is fine since the client has a clear idea which view is hovered at the
8370        // price of a couple more events being sent. This is a simple and
8371        // working solution.
8372        View source = this;
8373        while (true) {
8374            if (source.includeForAccessibility()) {
8375                source.sendAccessibilityEvent(eventType);
8376                return;
8377            }
8378            ViewParent parent = source.getParent();
8379            if (parent instanceof View) {
8380                source = (View) parent;
8381            } else {
8382                return;
8383            }
8384        }
8385    }
8386
8387    /**
8388     * Clears accessibility focus without calling any callback methods
8389     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8390     * is used for clearing accessibility focus when giving this focus to
8391     * another view.
8392     */
8393    void clearAccessibilityFocusNoCallbacks() {
8394        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8395            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8396            invalidate();
8397            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8398        }
8399    }
8400
8401    /**
8402     * Call this to try to give focus to a specific view or to one of its
8403     * descendants.
8404     *
8405     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8406     * false), or if it is focusable and it is not focusable in touch mode
8407     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8408     *
8409     * See also {@link #focusSearch(int)}, which is what you call to say that you
8410     * have focus, and you want your parent to look for the next one.
8411     *
8412     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8413     * {@link #FOCUS_DOWN} and <code>null</code>.
8414     *
8415     * @return Whether this view or one of its descendants actually took focus.
8416     */
8417    public final boolean requestFocus() {
8418        return requestFocus(View.FOCUS_DOWN);
8419    }
8420
8421    /**
8422     * Call this to try to give focus to a specific view or to one of its
8423     * descendants and give it a hint about what direction focus is heading.
8424     *
8425     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8426     * false), or if it is focusable and it is not focusable in touch mode
8427     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8428     *
8429     * See also {@link #focusSearch(int)}, which is what you call to say that you
8430     * have focus, and you want your parent to look for the next one.
8431     *
8432     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8433     * <code>null</code> set for the previously focused rectangle.
8434     *
8435     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8436     * @return Whether this view or one of its descendants actually took focus.
8437     */
8438    public final boolean requestFocus(int direction) {
8439        return requestFocus(direction, null);
8440    }
8441
8442    /**
8443     * Call this to try to give focus to a specific view or to one of its descendants
8444     * and give it hints about the direction and a specific rectangle that the focus
8445     * is coming from.  The rectangle can help give larger views a finer grained hint
8446     * about where focus is coming from, and therefore, where to show selection, or
8447     * forward focus change internally.
8448     *
8449     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8450     * false), or if it is focusable and it is not focusable in touch mode
8451     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8452     *
8453     * A View will not take focus if it is not visible.
8454     *
8455     * A View will not take focus if one of its parents has
8456     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8457     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8458     *
8459     * See also {@link #focusSearch(int)}, which is what you call to say that you
8460     * have focus, and you want your parent to look for the next one.
8461     *
8462     * You may wish to override this method if your custom {@link View} has an internal
8463     * {@link View} that it wishes to forward the request to.
8464     *
8465     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8466     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8467     *        to give a finer grained hint about where focus is coming from.  May be null
8468     *        if there is no hint.
8469     * @return Whether this view or one of its descendants actually took focus.
8470     */
8471    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8472        return requestFocusNoSearch(direction, previouslyFocusedRect);
8473    }
8474
8475    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8476        // need to be focusable
8477        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8478                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8479            return false;
8480        }
8481
8482        // need to be focusable in touch mode if in touch mode
8483        if (isInTouchMode() &&
8484            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8485               return false;
8486        }
8487
8488        // need to not have any parents blocking us
8489        if (hasAncestorThatBlocksDescendantFocus()) {
8490            return false;
8491        }
8492
8493        handleFocusGainInternal(direction, previouslyFocusedRect);
8494        return true;
8495    }
8496
8497    /**
8498     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8499     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8500     * touch mode to request focus when they are touched.
8501     *
8502     * @return Whether this view or one of its descendants actually took focus.
8503     *
8504     * @see #isInTouchMode()
8505     *
8506     */
8507    public final boolean requestFocusFromTouch() {
8508        // Leave touch mode if we need to
8509        if (isInTouchMode()) {
8510            ViewRootImpl viewRoot = getViewRootImpl();
8511            if (viewRoot != null) {
8512                viewRoot.ensureTouchMode(false);
8513            }
8514        }
8515        return requestFocus(View.FOCUS_DOWN);
8516    }
8517
8518    /**
8519     * @return Whether any ancestor of this view blocks descendant focus.
8520     */
8521    private boolean hasAncestorThatBlocksDescendantFocus() {
8522        final boolean focusableInTouchMode = isFocusableInTouchMode();
8523        ViewParent ancestor = mParent;
8524        while (ancestor instanceof ViewGroup) {
8525            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8526            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8527                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8528                return true;
8529            } else {
8530                ancestor = vgAncestor.getParent();
8531            }
8532        }
8533        return false;
8534    }
8535
8536    /**
8537     * Gets the mode for determining whether this View is important for accessibility
8538     * which is if it fires accessibility events and if it is reported to
8539     * accessibility services that query the screen.
8540     *
8541     * @return The mode for determining whether a View is important for accessibility.
8542     *
8543     * @attr ref android.R.styleable#View_importantForAccessibility
8544     *
8545     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8546     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8547     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8548     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8549     */
8550    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8551            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8552            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8553            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8554            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8555                    to = "noHideDescendants")
8556        })
8557    public int getImportantForAccessibility() {
8558        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8559                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8560    }
8561
8562    /**
8563     * Sets the live region mode for this view. This indicates to accessibility
8564     * services whether they should automatically notify the user about changes
8565     * to the view's content description or text, or to the content descriptions
8566     * or text of the view's children (where applicable).
8567     * <p>
8568     * For example, in a login screen with a TextView that displays an "incorrect
8569     * password" notification, that view should be marked as a live region with
8570     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8571     * <p>
8572     * To disable change notifications for this view, use
8573     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8574     * mode for most views.
8575     * <p>
8576     * To indicate that the user should be notified of changes, use
8577     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8578     * <p>
8579     * If the view's changes should interrupt ongoing speech and notify the user
8580     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8581     *
8582     * @param mode The live region mode for this view, one of:
8583     *        <ul>
8584     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8585     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8586     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8587     *        </ul>
8588     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8589     */
8590    public void setAccessibilityLiveRegion(int mode) {
8591        if (mode != getAccessibilityLiveRegion()) {
8592            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8593            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8594                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8595            notifyViewAccessibilityStateChangedIfNeeded(
8596                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8597        }
8598    }
8599
8600    /**
8601     * Gets the live region mode for this View.
8602     *
8603     * @return The live region mode for the view.
8604     *
8605     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8606     *
8607     * @see #setAccessibilityLiveRegion(int)
8608     */
8609    public int getAccessibilityLiveRegion() {
8610        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8611                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8612    }
8613
8614    /**
8615     * Sets how to determine whether this view is important for accessibility
8616     * which is if it fires accessibility events and if it is reported to
8617     * accessibility services that query the screen.
8618     *
8619     * @param mode How to determine whether this view is important for accessibility.
8620     *
8621     * @attr ref android.R.styleable#View_importantForAccessibility
8622     *
8623     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8624     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8625     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8626     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8627     */
8628    public void setImportantForAccessibility(int mode) {
8629        final int oldMode = getImportantForAccessibility();
8630        if (mode != oldMode) {
8631            // If we're moving between AUTO and another state, we might not need
8632            // to send a subtree changed notification. We'll store the computed
8633            // importance, since we'll need to check it later to make sure.
8634            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8635                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8636            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8637            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8638            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8639                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8640            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8641                notifySubtreeAccessibilityStateChangedIfNeeded();
8642            } else {
8643                notifyViewAccessibilityStateChangedIfNeeded(
8644                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8645            }
8646        }
8647    }
8648
8649    /**
8650     * Computes whether this view should be exposed for accessibility. In
8651     * general, views that are interactive or provide information are exposed
8652     * while views that serve only as containers are hidden.
8653     * <p>
8654     * If an ancestor of this view has importance
8655     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8656     * returns <code>false</code>.
8657     * <p>
8658     * Otherwise, the value is computed according to the view's
8659     * {@link #getImportantForAccessibility()} value:
8660     * <ol>
8661     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8662     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8663     * </code>
8664     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8665     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8666     * view satisfies any of the following:
8667     * <ul>
8668     * <li>Is actionable, e.g. {@link #isClickable()},
8669     * {@link #isLongClickable()}, or {@link #isFocusable()}
8670     * <li>Has an {@link AccessibilityDelegate}
8671     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8672     * {@link OnKeyListener}, etc.
8673     * <li>Is an accessibility live region, e.g.
8674     * {@link #getAccessibilityLiveRegion()} is not
8675     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8676     * </ul>
8677     * </ol>
8678     *
8679     * @return Whether the view is exposed for accessibility.
8680     * @see #setImportantForAccessibility(int)
8681     * @see #getImportantForAccessibility()
8682     */
8683    public boolean isImportantForAccessibility() {
8684        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8685                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8686        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8687                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8688            return false;
8689        }
8690
8691        // Check parent mode to ensure we're not hidden.
8692        ViewParent parent = mParent;
8693        while (parent instanceof View) {
8694            if (((View) parent).getImportantForAccessibility()
8695                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8696                return false;
8697            }
8698            parent = parent.getParent();
8699        }
8700
8701        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8702                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8703                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8704    }
8705
8706    /**
8707     * Gets the parent for accessibility purposes. Note that the parent for
8708     * accessibility is not necessary the immediate parent. It is the first
8709     * predecessor that is important for accessibility.
8710     *
8711     * @return The parent for accessibility purposes.
8712     */
8713    public ViewParent getParentForAccessibility() {
8714        if (mParent instanceof View) {
8715            View parentView = (View) mParent;
8716            if (parentView.includeForAccessibility()) {
8717                return mParent;
8718            } else {
8719                return mParent.getParentForAccessibility();
8720            }
8721        }
8722        return null;
8723    }
8724
8725    /**
8726     * Adds the children of this View relevant for accessibility to the given list
8727     * as output. Since some Views are not important for accessibility the added
8728     * child views are not necessarily direct children of this view, rather they are
8729     * the first level of descendants important for accessibility.
8730     *
8731     * @param outChildren The output list that will receive children for accessibility.
8732     */
8733    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8734
8735    }
8736
8737    /**
8738     * Whether to regard this view for accessibility. A view is regarded for
8739     * accessibility if it is important for accessibility or the querying
8740     * accessibility service has explicitly requested that view not
8741     * important for accessibility are regarded.
8742     *
8743     * @return Whether to regard the view for accessibility.
8744     *
8745     * @hide
8746     */
8747    public boolean includeForAccessibility() {
8748        if (mAttachInfo != null) {
8749            return (mAttachInfo.mAccessibilityFetchFlags
8750                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8751                    || isImportantForAccessibility();
8752        }
8753        return false;
8754    }
8755
8756    /**
8757     * Returns whether the View is considered actionable from
8758     * accessibility perspective. Such view are important for
8759     * accessibility.
8760     *
8761     * @return True if the view is actionable for accessibility.
8762     *
8763     * @hide
8764     */
8765    public boolean isActionableForAccessibility() {
8766        return (isClickable() || isLongClickable() || isFocusable());
8767    }
8768
8769    /**
8770     * Returns whether the View has registered callbacks which makes it
8771     * important for accessibility.
8772     *
8773     * @return True if the view is actionable for accessibility.
8774     */
8775    private boolean hasListenersForAccessibility() {
8776        ListenerInfo info = getListenerInfo();
8777        return mTouchDelegate != null || info.mOnKeyListener != null
8778                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8779                || info.mOnHoverListener != null || info.mOnDragListener != null;
8780    }
8781
8782    /**
8783     * Notifies that the accessibility state of this view changed. The change
8784     * is local to this view and does not represent structural changes such
8785     * as children and parent. For example, the view became focusable. The
8786     * notification is at at most once every
8787     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8788     * to avoid unnecessary load to the system. Also once a view has a pending
8789     * notification this method is a NOP until the notification has been sent.
8790     *
8791     * @hide
8792     */
8793    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8794        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8795            return;
8796        }
8797        if (mSendViewStateChangedAccessibilityEvent == null) {
8798            mSendViewStateChangedAccessibilityEvent =
8799                    new SendViewStateChangedAccessibilityEvent();
8800        }
8801        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8802    }
8803
8804    /**
8805     * Notifies that the accessibility state of this view changed. The change
8806     * is *not* local to this view and does represent structural changes such
8807     * as children and parent. For example, the view size changed. The
8808     * notification is at at most once every
8809     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8810     * to avoid unnecessary load to the system. Also once a view has a pending
8811     * notification this method is a NOP until the notification has been sent.
8812     *
8813     * @hide
8814     */
8815    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8816        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8817            return;
8818        }
8819        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8820            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8821            if (mParent != null) {
8822                try {
8823                    mParent.notifySubtreeAccessibilityStateChanged(
8824                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8825                } catch (AbstractMethodError e) {
8826                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8827                            " does not fully implement ViewParent", e);
8828                }
8829            }
8830        }
8831    }
8832
8833    /**
8834     * Change the visibility of the View without triggering any other changes. This is
8835     * important for transitions, where visibility changes should not adjust focus or
8836     * trigger a new layout. This is only used when the visibility has already been changed
8837     * and we need a transient value during an animation. When the animation completes,
8838     * the original visibility value is always restored.
8839     *
8840     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8841     * @hide
8842     */
8843    public void setTransitionVisibility(@Visibility int visibility) {
8844        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
8845    }
8846
8847    /**
8848     * Reset the flag indicating the accessibility state of the subtree rooted
8849     * at this view changed.
8850     */
8851    void resetSubtreeAccessibilityStateChanged() {
8852        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8853    }
8854
8855    /**
8856     * Report an accessibility action to this view's parents for delegated processing.
8857     *
8858     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8859     * call this method to delegate an accessibility action to a supporting parent. If the parent
8860     * returns true from its
8861     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8862     * method this method will return true to signify that the action was consumed.</p>
8863     *
8864     * <p>This method is useful for implementing nested scrolling child views. If
8865     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8866     * a custom view implementation may invoke this method to allow a parent to consume the
8867     * scroll first. If this method returns true the custom view should skip its own scrolling
8868     * behavior.</p>
8869     *
8870     * @param action Accessibility action to delegate
8871     * @param arguments Optional action arguments
8872     * @return true if the action was consumed by a parent
8873     */
8874    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8875        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8876            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8877                return true;
8878            }
8879        }
8880        return false;
8881    }
8882
8883    /**
8884     * Performs the specified accessibility action on the view. For
8885     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8886     * <p>
8887     * If an {@link AccessibilityDelegate} has been specified via calling
8888     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8889     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8890     * is responsible for handling this call.
8891     * </p>
8892     *
8893     * <p>The default implementation will delegate
8894     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8895     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8896     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8897     *
8898     * @param action The action to perform.
8899     * @param arguments Optional action arguments.
8900     * @return Whether the action was performed.
8901     */
8902    public boolean performAccessibilityAction(int action, Bundle arguments) {
8903      if (mAccessibilityDelegate != null) {
8904          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8905      } else {
8906          return performAccessibilityActionInternal(action, arguments);
8907      }
8908    }
8909
8910   /**
8911    * @see #performAccessibilityAction(int, Bundle)
8912    *
8913    * Note: Called from the default {@link AccessibilityDelegate}.
8914    *
8915    * @hide
8916    */
8917    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8918        if (isNestedScrollingEnabled()
8919                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8920                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
8921                || action == R.id.accessibilityActionScrollUp
8922                || action == R.id.accessibilityActionScrollLeft
8923                || action == R.id.accessibilityActionScrollDown
8924                || action == R.id.accessibilityActionScrollRight)) {
8925            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8926                return true;
8927            }
8928        }
8929
8930        switch (action) {
8931            case AccessibilityNodeInfo.ACTION_CLICK: {
8932                if (isClickable()) {
8933                    performClick();
8934                    return true;
8935                }
8936            } break;
8937            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8938                if (isLongClickable()) {
8939                    performLongClick();
8940                    return true;
8941                }
8942            } break;
8943            case AccessibilityNodeInfo.ACTION_FOCUS: {
8944                if (!hasFocus()) {
8945                    // Get out of touch mode since accessibility
8946                    // wants to move focus around.
8947                    getViewRootImpl().ensureTouchMode(false);
8948                    return requestFocus();
8949                }
8950            } break;
8951            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8952                if (hasFocus()) {
8953                    clearFocus();
8954                    return !isFocused();
8955                }
8956            } break;
8957            case AccessibilityNodeInfo.ACTION_SELECT: {
8958                if (!isSelected()) {
8959                    setSelected(true);
8960                    return isSelected();
8961                }
8962            } break;
8963            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8964                if (isSelected()) {
8965                    setSelected(false);
8966                    return !isSelected();
8967                }
8968            } break;
8969            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8970                if (!isAccessibilityFocused()) {
8971                    return requestAccessibilityFocus();
8972                }
8973            } break;
8974            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8975                if (isAccessibilityFocused()) {
8976                    clearAccessibilityFocus();
8977                    return true;
8978                }
8979            } break;
8980            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8981                if (arguments != null) {
8982                    final int granularity = arguments.getInt(
8983                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8984                    final boolean extendSelection = arguments.getBoolean(
8985                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8986                    return traverseAtGranularity(granularity, true, extendSelection);
8987                }
8988            } break;
8989            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8990                if (arguments != null) {
8991                    final int granularity = arguments.getInt(
8992                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8993                    final boolean extendSelection = arguments.getBoolean(
8994                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8995                    return traverseAtGranularity(granularity, false, extendSelection);
8996                }
8997            } break;
8998            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8999                CharSequence text = getIterableTextForAccessibility();
9000                if (text == null) {
9001                    return false;
9002                }
9003                final int start = (arguments != null) ? arguments.getInt(
9004                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9005                final int end = (arguments != null) ? arguments.getInt(
9006                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9007                // Only cursor position can be specified (selection length == 0)
9008                if ((getAccessibilitySelectionStart() != start
9009                        || getAccessibilitySelectionEnd() != end)
9010                        && (start == end)) {
9011                    setAccessibilitySelection(start, end);
9012                    notifyViewAccessibilityStateChangedIfNeeded(
9013                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9014                    return true;
9015                }
9016            } break;
9017            case R.id.accessibilityActionShowOnScreen: {
9018                if (mAttachInfo != null) {
9019                    final Rect r = mAttachInfo.mTmpInvalRect;
9020                    getDrawingRect(r);
9021                    return requestRectangleOnScreen(r, true);
9022                }
9023            } break;
9024            case R.id.accessibilityActionContextClick: {
9025                if (isContextClickable()) {
9026                    performContextClick();
9027                    return true;
9028                }
9029            } break;
9030        }
9031        return false;
9032    }
9033
9034    private boolean traverseAtGranularity(int granularity, boolean forward,
9035            boolean extendSelection) {
9036        CharSequence text = getIterableTextForAccessibility();
9037        if (text == null || text.length() == 0) {
9038            return false;
9039        }
9040        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9041        if (iterator == null) {
9042            return false;
9043        }
9044        int current = getAccessibilitySelectionEnd();
9045        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9046            current = forward ? 0 : text.length();
9047        }
9048        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9049        if (range == null) {
9050            return false;
9051        }
9052        final int segmentStart = range[0];
9053        final int segmentEnd = range[1];
9054        int selectionStart;
9055        int selectionEnd;
9056        if (extendSelection && isAccessibilitySelectionExtendable()) {
9057            selectionStart = getAccessibilitySelectionStart();
9058            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9059                selectionStart = forward ? segmentStart : segmentEnd;
9060            }
9061            selectionEnd = forward ? segmentEnd : segmentStart;
9062        } else {
9063            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9064        }
9065        setAccessibilitySelection(selectionStart, selectionEnd);
9066        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9067                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9068        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9069        return true;
9070    }
9071
9072    /**
9073     * Gets the text reported for accessibility purposes.
9074     *
9075     * @return The accessibility text.
9076     *
9077     * @hide
9078     */
9079    public CharSequence getIterableTextForAccessibility() {
9080        return getContentDescription();
9081    }
9082
9083    /**
9084     * Gets whether accessibility selection can be extended.
9085     *
9086     * @return If selection is extensible.
9087     *
9088     * @hide
9089     */
9090    public boolean isAccessibilitySelectionExtendable() {
9091        return false;
9092    }
9093
9094    /**
9095     * @hide
9096     */
9097    public int getAccessibilitySelectionStart() {
9098        return mAccessibilityCursorPosition;
9099    }
9100
9101    /**
9102     * @hide
9103     */
9104    public int getAccessibilitySelectionEnd() {
9105        return getAccessibilitySelectionStart();
9106    }
9107
9108    /**
9109     * @hide
9110     */
9111    public void setAccessibilitySelection(int start, int end) {
9112        if (start ==  end && end == mAccessibilityCursorPosition) {
9113            return;
9114        }
9115        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9116            mAccessibilityCursorPosition = start;
9117        } else {
9118            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9119        }
9120        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9121    }
9122
9123    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9124            int fromIndex, int toIndex) {
9125        if (mParent == null) {
9126            return;
9127        }
9128        AccessibilityEvent event = AccessibilityEvent.obtain(
9129                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9130        onInitializeAccessibilityEvent(event);
9131        onPopulateAccessibilityEvent(event);
9132        event.setFromIndex(fromIndex);
9133        event.setToIndex(toIndex);
9134        event.setAction(action);
9135        event.setMovementGranularity(granularity);
9136        mParent.requestSendAccessibilityEvent(this, event);
9137    }
9138
9139    /**
9140     * @hide
9141     */
9142    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9143        switch (granularity) {
9144            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9145                CharSequence text = getIterableTextForAccessibility();
9146                if (text != null && text.length() > 0) {
9147                    CharacterTextSegmentIterator iterator =
9148                        CharacterTextSegmentIterator.getInstance(
9149                                mContext.getResources().getConfiguration().locale);
9150                    iterator.initialize(text.toString());
9151                    return iterator;
9152                }
9153            } break;
9154            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9155                CharSequence text = getIterableTextForAccessibility();
9156                if (text != null && text.length() > 0) {
9157                    WordTextSegmentIterator iterator =
9158                        WordTextSegmentIterator.getInstance(
9159                                mContext.getResources().getConfiguration().locale);
9160                    iterator.initialize(text.toString());
9161                    return iterator;
9162                }
9163            } break;
9164            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9165                CharSequence text = getIterableTextForAccessibility();
9166                if (text != null && text.length() > 0) {
9167                    ParagraphTextSegmentIterator iterator =
9168                        ParagraphTextSegmentIterator.getInstance();
9169                    iterator.initialize(text.toString());
9170                    return iterator;
9171                }
9172            } break;
9173        }
9174        return null;
9175    }
9176
9177    /**
9178     * @hide
9179     */
9180    public void dispatchStartTemporaryDetach() {
9181        onStartTemporaryDetach();
9182    }
9183
9184    /**
9185     * This is called when a container is going to temporarily detach a child, with
9186     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9187     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9188     * {@link #onDetachedFromWindow()} when the container is done.
9189     */
9190    public void onStartTemporaryDetach() {
9191        removeUnsetPressCallback();
9192        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9193    }
9194
9195    /**
9196     * @hide
9197     */
9198    public void dispatchFinishTemporaryDetach() {
9199        onFinishTemporaryDetach();
9200    }
9201
9202    /**
9203     * Called after {@link #onStartTemporaryDetach} when the container is done
9204     * changing the view.
9205     */
9206    public void onFinishTemporaryDetach() {
9207    }
9208
9209    /**
9210     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9211     * for this view's window.  Returns null if the view is not currently attached
9212     * to the window.  Normally you will not need to use this directly, but
9213     * just use the standard high-level event callbacks like
9214     * {@link #onKeyDown(int, KeyEvent)}.
9215     */
9216    public KeyEvent.DispatcherState getKeyDispatcherState() {
9217        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9218    }
9219
9220    /**
9221     * Dispatch a key event before it is processed by any input method
9222     * associated with the view hierarchy.  This can be used to intercept
9223     * key events in special situations before the IME consumes them; a
9224     * typical example would be handling the BACK key to update the application's
9225     * UI instead of allowing the IME to see it and close itself.
9226     *
9227     * @param event The key event to be dispatched.
9228     * @return True if the event was handled, false otherwise.
9229     */
9230    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9231        return onKeyPreIme(event.getKeyCode(), event);
9232    }
9233
9234    /**
9235     * Dispatch a key event to the next view on the focus path. This path runs
9236     * from the top of the view tree down to the currently focused view. If this
9237     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9238     * the next node down the focus path. This method also fires any key
9239     * listeners.
9240     *
9241     * @param event The key event to be dispatched.
9242     * @return True if the event was handled, false otherwise.
9243     */
9244    public boolean dispatchKeyEvent(KeyEvent event) {
9245        if (mInputEventConsistencyVerifier != null) {
9246            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9247        }
9248
9249        // Give any attached key listener a first crack at the event.
9250        //noinspection SimplifiableIfStatement
9251        ListenerInfo li = mListenerInfo;
9252        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9253                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9254            return true;
9255        }
9256
9257        if (event.dispatch(this, mAttachInfo != null
9258                ? mAttachInfo.mKeyDispatchState : null, this)) {
9259            return true;
9260        }
9261
9262        if (mInputEventConsistencyVerifier != null) {
9263            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9264        }
9265        return false;
9266    }
9267
9268    /**
9269     * Dispatches a key shortcut event.
9270     *
9271     * @param event The key event to be dispatched.
9272     * @return True if the event was handled by the view, false otherwise.
9273     */
9274    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9275        return onKeyShortcut(event.getKeyCode(), event);
9276    }
9277
9278    /**
9279     * Pass the touch screen motion event down to the target view, or this
9280     * view if it is the target.
9281     *
9282     * @param event The motion event to be dispatched.
9283     * @return True if the event was handled by the view, false otherwise.
9284     */
9285    public boolean dispatchTouchEvent(MotionEvent event) {
9286        // If the event should be handled by accessibility focus first.
9287        if (event.isTargetAccessibilityFocus()) {
9288            // We don't have focus or no virtual descendant has it, do not handle the event.
9289            if (!isAccessibilityFocusedViewOrHost()) {
9290                return false;
9291            }
9292            // We have focus and got the event, then use normal event dispatch.
9293            event.setTargetAccessibilityFocus(false);
9294        }
9295
9296        boolean result = false;
9297
9298        if (mInputEventConsistencyVerifier != null) {
9299            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9300        }
9301
9302        final int actionMasked = event.getActionMasked();
9303        if (actionMasked == MotionEvent.ACTION_DOWN) {
9304            // Defensive cleanup for new gesture
9305            stopNestedScroll();
9306        }
9307
9308        if (onFilterTouchEventForSecurity(event)) {
9309            //noinspection SimplifiableIfStatement
9310            ListenerInfo li = mListenerInfo;
9311            if (li != null && li.mOnTouchListener != null
9312                    && (mViewFlags & ENABLED_MASK) == ENABLED
9313                    && li.mOnTouchListener.onTouch(this, event)) {
9314                result = true;
9315            }
9316
9317            if (!result && onTouchEvent(event)) {
9318                result = true;
9319            }
9320        }
9321
9322        if (!result && mInputEventConsistencyVerifier != null) {
9323            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9324        }
9325
9326        // Clean up after nested scrolls if this is the end of a gesture;
9327        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9328        // of the gesture.
9329        if (actionMasked == MotionEvent.ACTION_UP ||
9330                actionMasked == MotionEvent.ACTION_CANCEL ||
9331                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9332            stopNestedScroll();
9333        }
9334
9335        return result;
9336    }
9337
9338    boolean isAccessibilityFocusedViewOrHost() {
9339        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9340                .getAccessibilityFocusedHost() == this);
9341    }
9342
9343    /**
9344     * Filter the touch event to apply security policies.
9345     *
9346     * @param event The motion event to be filtered.
9347     * @return True if the event should be dispatched, false if the event should be dropped.
9348     *
9349     * @see #getFilterTouchesWhenObscured
9350     */
9351    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9352        //noinspection RedundantIfStatement
9353        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9354                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9355            // Window is obscured, drop this touch.
9356            return false;
9357        }
9358        return true;
9359    }
9360
9361    /**
9362     * Pass a trackball motion event down to the focused view.
9363     *
9364     * @param event The motion event to be dispatched.
9365     * @return True if the event was handled by the view, false otherwise.
9366     */
9367    public boolean dispatchTrackballEvent(MotionEvent event) {
9368        if (mInputEventConsistencyVerifier != null) {
9369            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9370        }
9371
9372        return onTrackballEvent(event);
9373    }
9374
9375    /**
9376     * Dispatch a generic motion event.
9377     * <p>
9378     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9379     * are delivered to the view under the pointer.  All other generic motion events are
9380     * delivered to the focused view.  Hover events are handled specially and are delivered
9381     * to {@link #onHoverEvent(MotionEvent)}.
9382     * </p>
9383     *
9384     * @param event The motion event to be dispatched.
9385     * @return True if the event was handled by the view, false otherwise.
9386     */
9387    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9388        if (mInputEventConsistencyVerifier != null) {
9389            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9390        }
9391
9392        final int source = event.getSource();
9393        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9394            final int action = event.getAction();
9395            if (action == MotionEvent.ACTION_HOVER_ENTER
9396                    || action == MotionEvent.ACTION_HOVER_MOVE
9397                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9398                if (dispatchHoverEvent(event)) {
9399                    return true;
9400                }
9401            } else if (dispatchGenericPointerEvent(event)) {
9402                return true;
9403            }
9404        } else if (dispatchGenericFocusedEvent(event)) {
9405            return true;
9406        }
9407
9408        if (dispatchGenericMotionEventInternal(event)) {
9409            return true;
9410        }
9411
9412        if (mInputEventConsistencyVerifier != null) {
9413            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9414        }
9415        return false;
9416    }
9417
9418    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9419        //noinspection SimplifiableIfStatement
9420        ListenerInfo li = mListenerInfo;
9421        if (li != null && li.mOnGenericMotionListener != null
9422                && (mViewFlags & ENABLED_MASK) == ENABLED
9423                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9424            return true;
9425        }
9426
9427        if (onGenericMotionEvent(event)) {
9428            return true;
9429        }
9430
9431        final int actionButton = event.getActionButton();
9432        switch (event.getActionMasked()) {
9433            case MotionEvent.ACTION_BUTTON_PRESS:
9434                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9435                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9436                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9437                    if (performContextClick()) {
9438                        mInContextButtonPress = true;
9439                        setPressed(true, event.getX(), event.getY());
9440                        removeTapCallback();
9441                        removeLongPressCallback();
9442                        return true;
9443                    }
9444                }
9445                break;
9446
9447            case MotionEvent.ACTION_BUTTON_RELEASE:
9448                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9449                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9450                    mInContextButtonPress = false;
9451                    mIgnoreNextUpEvent = true;
9452                }
9453                break;
9454        }
9455
9456        if (mInputEventConsistencyVerifier != null) {
9457            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9458        }
9459        return false;
9460    }
9461
9462    /**
9463     * Dispatch a hover event.
9464     * <p>
9465     * Do not call this method directly.
9466     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9467     * </p>
9468     *
9469     * @param event The motion event to be dispatched.
9470     * @return True if the event was handled by the view, false otherwise.
9471     */
9472    protected boolean dispatchHoverEvent(MotionEvent event) {
9473        ListenerInfo li = mListenerInfo;
9474        //noinspection SimplifiableIfStatement
9475        if (li != null && li.mOnHoverListener != null
9476                && (mViewFlags & ENABLED_MASK) == ENABLED
9477                && li.mOnHoverListener.onHover(this, event)) {
9478            return true;
9479        }
9480
9481        return onHoverEvent(event);
9482    }
9483
9484    /**
9485     * Returns true if the view has a child to which it has recently sent
9486     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9487     * it does not have a hovered child, then it must be the innermost hovered view.
9488     * @hide
9489     */
9490    protected boolean hasHoveredChild() {
9491        return false;
9492    }
9493
9494    /**
9495     * Dispatch a generic motion event to the view under the first pointer.
9496     * <p>
9497     * Do not call this method directly.
9498     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9499     * </p>
9500     *
9501     * @param event The motion event to be dispatched.
9502     * @return True if the event was handled by the view, false otherwise.
9503     */
9504    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9505        return false;
9506    }
9507
9508    /**
9509     * Dispatch a generic motion event to the currently focused view.
9510     * <p>
9511     * Do not call this method directly.
9512     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9513     * </p>
9514     *
9515     * @param event The motion event to be dispatched.
9516     * @return True if the event was handled by the view, false otherwise.
9517     */
9518    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9519        return false;
9520    }
9521
9522    /**
9523     * Dispatch a pointer event.
9524     * <p>
9525     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9526     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9527     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9528     * and should not be expected to handle other pointing device features.
9529     * </p>
9530     *
9531     * @param event The motion event to be dispatched.
9532     * @return True if the event was handled by the view, false otherwise.
9533     * @hide
9534     */
9535    public final boolean dispatchPointerEvent(MotionEvent event) {
9536        if (event.isTouchEvent()) {
9537            return dispatchTouchEvent(event);
9538        } else {
9539            return dispatchGenericMotionEvent(event);
9540        }
9541    }
9542
9543    /**
9544     * Called when the window containing this view gains or loses window focus.
9545     * ViewGroups should override to route to their children.
9546     *
9547     * @param hasFocus True if the window containing this view now has focus,
9548     *        false otherwise.
9549     */
9550    public void dispatchWindowFocusChanged(boolean hasFocus) {
9551        onWindowFocusChanged(hasFocus);
9552    }
9553
9554    /**
9555     * Called when the window containing this view gains or loses focus.  Note
9556     * that this is separate from view focus: to receive key events, both
9557     * your view and its window must have focus.  If a window is displayed
9558     * on top of yours that takes input focus, then your own window will lose
9559     * focus but the view focus will remain unchanged.
9560     *
9561     * @param hasWindowFocus True if the window containing this view now has
9562     *        focus, false otherwise.
9563     */
9564    public void onWindowFocusChanged(boolean hasWindowFocus) {
9565        InputMethodManager imm = InputMethodManager.peekInstance();
9566        if (!hasWindowFocus) {
9567            if (isPressed()) {
9568                setPressed(false);
9569            }
9570            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9571                imm.focusOut(this);
9572            }
9573            removeLongPressCallback();
9574            removeTapCallback();
9575            onFocusLost();
9576        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9577            imm.focusIn(this);
9578        }
9579        refreshDrawableState();
9580    }
9581
9582    /**
9583     * Returns true if this view is in a window that currently has window focus.
9584     * Note that this is not the same as the view itself having focus.
9585     *
9586     * @return True if this view is in a window that currently has window focus.
9587     */
9588    public boolean hasWindowFocus() {
9589        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9590    }
9591
9592    /**
9593     * Dispatch a view visibility change down the view hierarchy.
9594     * ViewGroups should override to route to their children.
9595     * @param changedView The view whose visibility changed. Could be 'this' or
9596     * an ancestor view.
9597     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9598     * {@link #INVISIBLE} or {@link #GONE}.
9599     */
9600    protected void dispatchVisibilityChanged(@NonNull View changedView,
9601            @Visibility int visibility) {
9602        onVisibilityChanged(changedView, visibility);
9603    }
9604
9605    /**
9606     * Called when the visibility of the view or an ancestor of the view has
9607     * changed.
9608     *
9609     * @param changedView The view whose visibility changed. May be
9610     *                    {@code this} or an ancestor view.
9611     * @param visibility The new visibility, one of {@link #VISIBLE},
9612     *                   {@link #INVISIBLE} or {@link #GONE}.
9613     */
9614    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9615        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9616        if (visible && mAttachInfo != null) {
9617            initialAwakenScrollBars();
9618        }
9619
9620        final Drawable dr = mBackground;
9621        if (dr != null && visible != dr.isVisible()) {
9622            dr.setVisible(visible, false);
9623        }
9624        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9625        if (fg != null && visible != fg.isVisible()) {
9626            fg.setVisible(visible, false);
9627        }
9628    }
9629
9630    /**
9631     * Dispatch a hint about whether this view is displayed. For instance, when
9632     * a View moves out of the screen, it might receives a display hint indicating
9633     * the view is not displayed. Applications should not <em>rely</em> on this hint
9634     * as there is no guarantee that they will receive one.
9635     *
9636     * @param hint A hint about whether or not this view is displayed:
9637     * {@link #VISIBLE} or {@link #INVISIBLE}.
9638     */
9639    public void dispatchDisplayHint(@Visibility int hint) {
9640        onDisplayHint(hint);
9641    }
9642
9643    /**
9644     * Gives this view a hint about whether is displayed or not. For instance, when
9645     * a View moves out of the screen, it might receives a display hint indicating
9646     * the view is not displayed. Applications should not <em>rely</em> on this hint
9647     * as there is no guarantee that they will receive one.
9648     *
9649     * @param hint A hint about whether or not this view is displayed:
9650     * {@link #VISIBLE} or {@link #INVISIBLE}.
9651     */
9652    protected void onDisplayHint(@Visibility int hint) {
9653    }
9654
9655    /**
9656     * Dispatch a window visibility change down the view hierarchy.
9657     * ViewGroups should override to route to their children.
9658     *
9659     * @param visibility The new visibility of the window.
9660     *
9661     * @see #onWindowVisibilityChanged(int)
9662     */
9663    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9664        onWindowVisibilityChanged(visibility);
9665    }
9666
9667    /**
9668     * Called when the window containing has change its visibility
9669     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9670     * that this tells you whether or not your window is being made visible
9671     * to the window manager; this does <em>not</em> tell you whether or not
9672     * your window is obscured by other windows on the screen, even if it
9673     * is itself visible.
9674     *
9675     * @param visibility The new visibility of the window.
9676     */
9677    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9678        if (visibility == VISIBLE) {
9679            initialAwakenScrollBars();
9680        }
9681    }
9682
9683    /**
9684     * Returns the current visibility of the window this view is attached to
9685     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9686     *
9687     * @return Returns the current visibility of the view's window.
9688     */
9689    @Visibility
9690    public int getWindowVisibility() {
9691        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9692    }
9693
9694    /**
9695     * Retrieve the overall visible display size in which the window this view is
9696     * attached to has been positioned in.  This takes into account screen
9697     * decorations above the window, for both cases where the window itself
9698     * is being position inside of them or the window is being placed under
9699     * then and covered insets are used for the window to position its content
9700     * inside.  In effect, this tells you the available area where content can
9701     * be placed and remain visible to users.
9702     *
9703     * <p>This function requires an IPC back to the window manager to retrieve
9704     * the requested information, so should not be used in performance critical
9705     * code like drawing.
9706     *
9707     * @param outRect Filled in with the visible display frame.  If the view
9708     * is not attached to a window, this is simply the raw display size.
9709     */
9710    public void getWindowVisibleDisplayFrame(Rect outRect) {
9711        if (mAttachInfo != null) {
9712            try {
9713                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9714            } catch (RemoteException e) {
9715                return;
9716            }
9717            // XXX This is really broken, and probably all needs to be done
9718            // in the window manager, and we need to know more about whether
9719            // we want the area behind or in front of the IME.
9720            final Rect insets = mAttachInfo.mVisibleInsets;
9721            outRect.left += insets.left;
9722            outRect.top += insets.top;
9723            outRect.right -= insets.right;
9724            outRect.bottom -= insets.bottom;
9725            return;
9726        }
9727        // The view is not attached to a display so we don't have a context.
9728        // Make a best guess about the display size.
9729        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9730        d.getRectSize(outRect);
9731    }
9732
9733    /**
9734     * Dispatch a notification about a resource configuration change down
9735     * the view hierarchy.
9736     * ViewGroups should override to route to their children.
9737     *
9738     * @param newConfig The new resource configuration.
9739     *
9740     * @see #onConfigurationChanged(android.content.res.Configuration)
9741     */
9742    public void dispatchConfigurationChanged(Configuration newConfig) {
9743        onConfigurationChanged(newConfig);
9744    }
9745
9746    /**
9747     * Called when the current configuration of the resources being used
9748     * by the application have changed.  You can use this to decide when
9749     * to reload resources that can changed based on orientation and other
9750     * configuration characteristics.  You only need to use this if you are
9751     * not relying on the normal {@link android.app.Activity} mechanism of
9752     * recreating the activity instance upon a configuration change.
9753     *
9754     * @param newConfig The new resource configuration.
9755     */
9756    protected void onConfigurationChanged(Configuration newConfig) {
9757    }
9758
9759    /**
9760     * Private function to aggregate all per-view attributes in to the view
9761     * root.
9762     */
9763    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9764        performCollectViewAttributes(attachInfo, visibility);
9765    }
9766
9767    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9768        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9769            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9770                attachInfo.mKeepScreenOn = true;
9771            }
9772            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9773            ListenerInfo li = mListenerInfo;
9774            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9775                attachInfo.mHasSystemUiListeners = true;
9776            }
9777        }
9778    }
9779
9780    void needGlobalAttributesUpdate(boolean force) {
9781        final AttachInfo ai = mAttachInfo;
9782        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9783            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9784                    || ai.mHasSystemUiListeners) {
9785                ai.mRecomputeGlobalAttributes = true;
9786            }
9787        }
9788    }
9789
9790    /**
9791     * Returns whether the device is currently in touch mode.  Touch mode is entered
9792     * once the user begins interacting with the device by touch, and affects various
9793     * things like whether focus is always visible to the user.
9794     *
9795     * @return Whether the device is in touch mode.
9796     */
9797    @ViewDebug.ExportedProperty
9798    public boolean isInTouchMode() {
9799        if (mAttachInfo != null) {
9800            return mAttachInfo.mInTouchMode;
9801        } else {
9802            return ViewRootImpl.isInTouchMode();
9803        }
9804    }
9805
9806    /**
9807     * Returns the context the view is running in, through which it can
9808     * access the current theme, resources, etc.
9809     *
9810     * @return The view's Context.
9811     */
9812    @ViewDebug.CapturedViewProperty
9813    public final Context getContext() {
9814        return mContext;
9815    }
9816
9817    /**
9818     * Handle a key event before it is processed by any input method
9819     * associated with the view hierarchy.  This can be used to intercept
9820     * key events in special situations before the IME consumes them; a
9821     * typical example would be handling the BACK key to update the application's
9822     * UI instead of allowing the IME to see it and close itself.
9823     *
9824     * @param keyCode The value in event.getKeyCode().
9825     * @param event Description of the key event.
9826     * @return If you handled the event, return true. If you want to allow the
9827     *         event to be handled by the next receiver, return false.
9828     */
9829    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9830        return false;
9831    }
9832
9833    /**
9834     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9835     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9836     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9837     * is released, if the view is enabled and clickable.
9838     *
9839     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9840     * although some may elect to do so in some situations. Do not rely on this to
9841     * catch software key presses.
9842     *
9843     * @param keyCode A key code that represents the button pressed, from
9844     *                {@link android.view.KeyEvent}.
9845     * @param event   The KeyEvent object that defines the button action.
9846     */
9847    public boolean onKeyDown(int keyCode, KeyEvent event) {
9848        boolean result = false;
9849
9850        if (KeyEvent.isConfirmKey(keyCode)) {
9851            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9852                return true;
9853            }
9854            // Long clickable items don't necessarily have to be clickable
9855            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9856                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9857                    (event.getRepeatCount() == 0)) {
9858                setPressed(true);
9859                checkForLongClick(0);
9860                return true;
9861            }
9862        }
9863        return result;
9864    }
9865
9866    /**
9867     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9868     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9869     * the event).
9870     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9871     * although some may elect to do so in some situations. Do not rely on this to
9872     * catch software key presses.
9873     */
9874    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9875        return false;
9876    }
9877
9878    /**
9879     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9880     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9881     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9882     * {@link KeyEvent#KEYCODE_ENTER} is released.
9883     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9884     * although some may elect to do so in some situations. Do not rely on this to
9885     * catch software key presses.
9886     *
9887     * @param keyCode A key code that represents the button pressed, from
9888     *                {@link android.view.KeyEvent}.
9889     * @param event   The KeyEvent object that defines the button action.
9890     */
9891    public boolean onKeyUp(int keyCode, KeyEvent event) {
9892        if (KeyEvent.isConfirmKey(keyCode)) {
9893            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9894                return true;
9895            }
9896            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9897                setPressed(false);
9898
9899                if (!mHasPerformedLongPress) {
9900                    // This is a tap, so remove the longpress check
9901                    removeLongPressCallback();
9902                    return performClick();
9903                }
9904            }
9905        }
9906        return false;
9907    }
9908
9909    /**
9910     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9911     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9912     * the event).
9913     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9914     * although some may elect to do so in some situations. Do not rely on this to
9915     * catch software key presses.
9916     *
9917     * @param keyCode     A key code that represents the button pressed, from
9918     *                    {@link android.view.KeyEvent}.
9919     * @param repeatCount The number of times the action was made.
9920     * @param event       The KeyEvent object that defines the button action.
9921     */
9922    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9923        return false;
9924    }
9925
9926    /**
9927     * Called on the focused view when a key shortcut event is not handled.
9928     * Override this method to implement local key shortcuts for the View.
9929     * Key shortcuts can also be implemented by setting the
9930     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9931     *
9932     * @param keyCode The value in event.getKeyCode().
9933     * @param event Description of the key event.
9934     * @return If you handled the event, return true. If you want to allow the
9935     *         event to be handled by the next receiver, return false.
9936     */
9937    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9938        return false;
9939    }
9940
9941    /**
9942     * Check whether the called view is a text editor, in which case it
9943     * would make sense to automatically display a soft input window for
9944     * it.  Subclasses should override this if they implement
9945     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9946     * a call on that method would return a non-null InputConnection, and
9947     * they are really a first-class editor that the user would normally
9948     * start typing on when the go into a window containing your view.
9949     *
9950     * <p>The default implementation always returns false.  This does
9951     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9952     * will not be called or the user can not otherwise perform edits on your
9953     * view; it is just a hint to the system that this is not the primary
9954     * purpose of this view.
9955     *
9956     * @return Returns true if this view is a text editor, else false.
9957     */
9958    public boolean onCheckIsTextEditor() {
9959        return false;
9960    }
9961
9962    /**
9963     * Create a new InputConnection for an InputMethod to interact
9964     * with the view.  The default implementation returns null, since it doesn't
9965     * support input methods.  You can override this to implement such support.
9966     * This is only needed for views that take focus and text input.
9967     *
9968     * <p>When implementing this, you probably also want to implement
9969     * {@link #onCheckIsTextEditor()} to indicate you will return a
9970     * non-null InputConnection.</p>
9971     *
9972     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9973     * object correctly and in its entirety, so that the connected IME can rely
9974     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9975     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9976     * must be filled in with the correct cursor position for IMEs to work correctly
9977     * with your application.</p>
9978     *
9979     * @param outAttrs Fill in with attribute information about the connection.
9980     */
9981    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9982        return null;
9983    }
9984
9985    /**
9986     * Called by the {@link android.view.inputmethod.InputMethodManager}
9987     * when a view who is not the current
9988     * input connection target is trying to make a call on the manager.  The
9989     * default implementation returns false; you can override this to return
9990     * true for certain views if you are performing InputConnection proxying
9991     * to them.
9992     * @param view The View that is making the InputMethodManager call.
9993     * @return Return true to allow the call, false to reject.
9994     */
9995    public boolean checkInputConnectionProxy(View view) {
9996        return false;
9997    }
9998
9999    /**
10000     * Show the context menu for this view. It is not safe to hold on to the
10001     * menu after returning from this method.
10002     *
10003     * You should normally not overload this method. Overload
10004     * {@link #onCreateContextMenu(ContextMenu)} or define an
10005     * {@link OnCreateContextMenuListener} to add items to the context menu.
10006     *
10007     * @param menu The context menu to populate
10008     */
10009    public void createContextMenu(ContextMenu menu) {
10010        ContextMenuInfo menuInfo = getContextMenuInfo();
10011
10012        // Sets the current menu info so all items added to menu will have
10013        // my extra info set.
10014        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10015
10016        onCreateContextMenu(menu);
10017        ListenerInfo li = mListenerInfo;
10018        if (li != null && li.mOnCreateContextMenuListener != null) {
10019            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10020        }
10021
10022        // Clear the extra information so subsequent items that aren't mine don't
10023        // have my extra info.
10024        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10025
10026        if (mParent != null) {
10027            mParent.createContextMenu(menu);
10028        }
10029    }
10030
10031    /**
10032     * Views should implement this if they have extra information to associate
10033     * with the context menu. The return result is supplied as a parameter to
10034     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10035     * callback.
10036     *
10037     * @return Extra information about the item for which the context menu
10038     *         should be shown. This information will vary across different
10039     *         subclasses of View.
10040     */
10041    protected ContextMenuInfo getContextMenuInfo() {
10042        return null;
10043    }
10044
10045    /**
10046     * Views should implement this if the view itself is going to add items to
10047     * the context menu.
10048     *
10049     * @param menu the context menu to populate
10050     */
10051    protected void onCreateContextMenu(ContextMenu menu) {
10052    }
10053
10054    /**
10055     * Implement this method to handle trackball motion events.  The
10056     * <em>relative</em> movement of the trackball since the last event
10057     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10058     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10059     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10060     * they will often be fractional values, representing the more fine-grained
10061     * movement information available from a trackball).
10062     *
10063     * @param event The motion event.
10064     * @return True if the event was handled, false otherwise.
10065     */
10066    public boolean onTrackballEvent(MotionEvent event) {
10067        return false;
10068    }
10069
10070    /**
10071     * Implement this method to handle generic motion events.
10072     * <p>
10073     * Generic motion events describe joystick movements, mouse hovers, track pad
10074     * touches, scroll wheel movements and other input events.  The
10075     * {@link MotionEvent#getSource() source} of the motion event specifies
10076     * the class of input that was received.  Implementations of this method
10077     * must examine the bits in the source before processing the event.
10078     * The following code example shows how this is done.
10079     * </p><p>
10080     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10081     * are delivered to the view under the pointer.  All other generic motion events are
10082     * delivered to the focused view.
10083     * </p>
10084     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10085     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10086     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10087     *             // process the joystick movement...
10088     *             return true;
10089     *         }
10090     *     }
10091     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10092     *         switch (event.getAction()) {
10093     *             case MotionEvent.ACTION_HOVER_MOVE:
10094     *                 // process the mouse hover movement...
10095     *                 return true;
10096     *             case MotionEvent.ACTION_SCROLL:
10097     *                 // process the scroll wheel movement...
10098     *                 return true;
10099     *         }
10100     *     }
10101     *     return super.onGenericMotionEvent(event);
10102     * }</pre>
10103     *
10104     * @param event The generic motion event being processed.
10105     * @return True if the event was handled, false otherwise.
10106     */
10107    public boolean onGenericMotionEvent(MotionEvent event) {
10108        return false;
10109    }
10110
10111    /**
10112     * Implement this method to handle hover events.
10113     * <p>
10114     * This method is called whenever a pointer is hovering into, over, or out of the
10115     * bounds of a view and the view is not currently being touched.
10116     * Hover events are represented as pointer events with action
10117     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10118     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10119     * </p>
10120     * <ul>
10121     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10122     * when the pointer enters the bounds of the view.</li>
10123     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10124     * when the pointer has already entered the bounds of the view and has moved.</li>
10125     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10126     * when the pointer has exited the bounds of the view or when the pointer is
10127     * about to go down due to a button click, tap, or similar user action that
10128     * causes the view to be touched.</li>
10129     * </ul>
10130     * <p>
10131     * The view should implement this method to return true to indicate that it is
10132     * handling the hover event, such as by changing its drawable state.
10133     * </p><p>
10134     * The default implementation calls {@link #setHovered} to update the hovered state
10135     * of the view when a hover enter or hover exit event is received, if the view
10136     * is enabled and is clickable.  The default implementation also sends hover
10137     * accessibility events.
10138     * </p>
10139     *
10140     * @param event The motion event that describes the hover.
10141     * @return True if the view handled the hover event.
10142     *
10143     * @see #isHovered
10144     * @see #setHovered
10145     * @see #onHoverChanged
10146     */
10147    public boolean onHoverEvent(MotionEvent event) {
10148        // The root view may receive hover (or touch) events that are outside the bounds of
10149        // the window.  This code ensures that we only send accessibility events for
10150        // hovers that are actually within the bounds of the root view.
10151        final int action = event.getActionMasked();
10152        if (!mSendingHoverAccessibilityEvents) {
10153            if ((action == MotionEvent.ACTION_HOVER_ENTER
10154                    || action == MotionEvent.ACTION_HOVER_MOVE)
10155                    && !hasHoveredChild()
10156                    && pointInView(event.getX(), event.getY())) {
10157                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10158                mSendingHoverAccessibilityEvents = true;
10159            }
10160        } else {
10161            if (action == MotionEvent.ACTION_HOVER_EXIT
10162                    || (action == MotionEvent.ACTION_MOVE
10163                            && !pointInView(event.getX(), event.getY()))) {
10164                mSendingHoverAccessibilityEvents = false;
10165                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10166            }
10167        }
10168
10169        if (isHoverable()) {
10170            switch (action) {
10171                case MotionEvent.ACTION_HOVER_ENTER:
10172                    setHovered(true);
10173                    break;
10174                case MotionEvent.ACTION_HOVER_EXIT:
10175                    setHovered(false);
10176                    break;
10177            }
10178
10179            // Dispatch the event to onGenericMotionEvent before returning true.
10180            // This is to provide compatibility with existing applications that
10181            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10182            // break because of the new default handling for hoverable views
10183            // in onHoverEvent.
10184            // Note that onGenericMotionEvent will be called by default when
10185            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10186            dispatchGenericMotionEventInternal(event);
10187            // The event was already handled by calling setHovered(), so always
10188            // return true.
10189            return true;
10190        }
10191
10192        return false;
10193    }
10194
10195    /**
10196     * Returns true if the view should handle {@link #onHoverEvent}
10197     * by calling {@link #setHovered} to change its hovered state.
10198     *
10199     * @return True if the view is hoverable.
10200     */
10201    private boolean isHoverable() {
10202        final int viewFlags = mViewFlags;
10203        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10204            return false;
10205        }
10206
10207        return (viewFlags & CLICKABLE) == CLICKABLE
10208                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10209                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10210    }
10211
10212    /**
10213     * Returns true if the view is currently hovered.
10214     *
10215     * @return True if the view is currently hovered.
10216     *
10217     * @see #setHovered
10218     * @see #onHoverChanged
10219     */
10220    @ViewDebug.ExportedProperty
10221    public boolean isHovered() {
10222        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10223    }
10224
10225    /**
10226     * Sets whether the view is currently hovered.
10227     * <p>
10228     * Calling this method also changes the drawable state of the view.  This
10229     * enables the view to react to hover by using different drawable resources
10230     * to change its appearance.
10231     * </p><p>
10232     * The {@link #onHoverChanged} method is called when the hovered state changes.
10233     * </p>
10234     *
10235     * @param hovered True if the view is hovered.
10236     *
10237     * @see #isHovered
10238     * @see #onHoverChanged
10239     */
10240    public void setHovered(boolean hovered) {
10241        if (hovered) {
10242            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10243                mPrivateFlags |= PFLAG_HOVERED;
10244                refreshDrawableState();
10245                onHoverChanged(true);
10246            }
10247        } else {
10248            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10249                mPrivateFlags &= ~PFLAG_HOVERED;
10250                refreshDrawableState();
10251                onHoverChanged(false);
10252            }
10253        }
10254    }
10255
10256    /**
10257     * Implement this method to handle hover state changes.
10258     * <p>
10259     * This method is called whenever the hover state changes as a result of a
10260     * call to {@link #setHovered}.
10261     * </p>
10262     *
10263     * @param hovered The current hover state, as returned by {@link #isHovered}.
10264     *
10265     * @see #isHovered
10266     * @see #setHovered
10267     */
10268    public void onHoverChanged(boolean hovered) {
10269    }
10270
10271    /**
10272     * Implement this method to handle touch screen motion events.
10273     * <p>
10274     * If this method is used to detect click actions, it is recommended that
10275     * the actions be performed by implementing and calling
10276     * {@link #performClick()}. This will ensure consistent system behavior,
10277     * including:
10278     * <ul>
10279     * <li>obeying click sound preferences
10280     * <li>dispatching OnClickListener calls
10281     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10282     * accessibility features are enabled
10283     * </ul>
10284     *
10285     * @param event The motion event.
10286     * @return True if the event was handled, false otherwise.
10287     */
10288    public boolean onTouchEvent(MotionEvent event) {
10289        final float x = event.getX();
10290        final float y = event.getY();
10291        final int viewFlags = mViewFlags;
10292        final int action = event.getAction();
10293
10294        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10295            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10296                setPressed(false);
10297            }
10298            // A disabled view that is clickable still consumes the touch
10299            // events, it just doesn't respond to them.
10300            return (((viewFlags & CLICKABLE) == CLICKABLE
10301                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10302                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10303        }
10304
10305        if (mTouchDelegate != null) {
10306            if (mTouchDelegate.onTouchEvent(event)) {
10307                return true;
10308            }
10309        }
10310
10311        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10312                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10313                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10314            switch (action) {
10315                case MotionEvent.ACTION_UP:
10316                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10317                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10318                        // take focus if we don't have it already and we should in
10319                        // touch mode.
10320                        boolean focusTaken = false;
10321                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10322                            focusTaken = requestFocus();
10323                        }
10324
10325                        if (prepressed) {
10326                            // The button is being released before we actually
10327                            // showed it as pressed.  Make it show the pressed
10328                            // state now (before scheduling the click) to ensure
10329                            // the user sees it.
10330                            setPressed(true, x, y);
10331                       }
10332
10333                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10334                            // This is a tap, so remove the longpress check
10335                            removeLongPressCallback();
10336
10337                            // Only perform take click actions if we were in the pressed state
10338                            if (!focusTaken) {
10339                                // Use a Runnable and post this rather than calling
10340                                // performClick directly. This lets other visual state
10341                                // of the view update before click actions start.
10342                                if (mPerformClick == null) {
10343                                    mPerformClick = new PerformClick();
10344                                }
10345                                if (!post(mPerformClick)) {
10346                                    performClick();
10347                                }
10348                            }
10349                        }
10350
10351                        if (mUnsetPressedState == null) {
10352                            mUnsetPressedState = new UnsetPressedState();
10353                        }
10354
10355                        if (prepressed) {
10356                            postDelayed(mUnsetPressedState,
10357                                    ViewConfiguration.getPressedStateDuration());
10358                        } else if (!post(mUnsetPressedState)) {
10359                            // If the post failed, unpress right now
10360                            mUnsetPressedState.run();
10361                        }
10362
10363                        removeTapCallback();
10364                    }
10365                    mIgnoreNextUpEvent = false;
10366                    break;
10367
10368                case MotionEvent.ACTION_DOWN:
10369                    mHasPerformedLongPress = false;
10370
10371                    if (performButtonActionOnTouchDown(event)) {
10372                        break;
10373                    }
10374
10375                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10376                    boolean isInScrollingContainer = isInScrollingContainer();
10377
10378                    // For views inside a scrolling container, delay the pressed feedback for
10379                    // a short period in case this is a scroll.
10380                    if (isInScrollingContainer) {
10381                        mPrivateFlags |= PFLAG_PREPRESSED;
10382                        if (mPendingCheckForTap == null) {
10383                            mPendingCheckForTap = new CheckForTap();
10384                        }
10385                        mPendingCheckForTap.x = event.getX();
10386                        mPendingCheckForTap.y = event.getY();
10387                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10388                    } else {
10389                        // Not inside a scrolling container, so show the feedback right away
10390                        setPressed(true, x, y);
10391                        checkForLongClick(0);
10392                    }
10393                    break;
10394
10395                case MotionEvent.ACTION_CANCEL:
10396                    setPressed(false);
10397                    removeTapCallback();
10398                    removeLongPressCallback();
10399                    mInContextButtonPress = false;
10400                    mHasPerformedLongPress = false;
10401                    mIgnoreNextUpEvent = false;
10402                    break;
10403
10404                case MotionEvent.ACTION_MOVE:
10405                    drawableHotspotChanged(x, y);
10406
10407                    // Be lenient about moving outside of buttons
10408                    if (!pointInView(x, y, mTouchSlop)) {
10409                        // Outside button
10410                        removeTapCallback();
10411                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10412                            // Remove any future long press/tap checks
10413                            removeLongPressCallback();
10414
10415                            setPressed(false);
10416                        }
10417                    }
10418                    break;
10419            }
10420
10421            return true;
10422        }
10423
10424        return false;
10425    }
10426
10427    /**
10428     * @hide
10429     */
10430    public boolean isInScrollingContainer() {
10431        ViewParent p = getParent();
10432        while (p != null && p instanceof ViewGroup) {
10433            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10434                return true;
10435            }
10436            p = p.getParent();
10437        }
10438        return false;
10439    }
10440
10441    /**
10442     * Remove the longpress detection timer.
10443     */
10444    private void removeLongPressCallback() {
10445        if (mPendingCheckForLongPress != null) {
10446          removeCallbacks(mPendingCheckForLongPress);
10447        }
10448    }
10449
10450    /**
10451     * Remove the pending click action
10452     */
10453    private void removePerformClickCallback() {
10454        if (mPerformClick != null) {
10455            removeCallbacks(mPerformClick);
10456        }
10457    }
10458
10459    /**
10460     * Remove the prepress detection timer.
10461     */
10462    private void removeUnsetPressCallback() {
10463        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10464            setPressed(false);
10465            removeCallbacks(mUnsetPressedState);
10466        }
10467    }
10468
10469    /**
10470     * Remove the tap detection timer.
10471     */
10472    private void removeTapCallback() {
10473        if (mPendingCheckForTap != null) {
10474            mPrivateFlags &= ~PFLAG_PREPRESSED;
10475            removeCallbacks(mPendingCheckForTap);
10476        }
10477    }
10478
10479    /**
10480     * Cancels a pending long press.  Your subclass can use this if you
10481     * want the context menu to come up if the user presses and holds
10482     * at the same place, but you don't want it to come up if they press
10483     * and then move around enough to cause scrolling.
10484     */
10485    public void cancelLongPress() {
10486        removeLongPressCallback();
10487
10488        /*
10489         * The prepressed state handled by the tap callback is a display
10490         * construct, but the tap callback will post a long press callback
10491         * less its own timeout. Remove it here.
10492         */
10493        removeTapCallback();
10494    }
10495
10496    /**
10497     * Remove the pending callback for sending a
10498     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10499     */
10500    private void removeSendViewScrolledAccessibilityEventCallback() {
10501        if (mSendViewScrolledAccessibilityEvent != null) {
10502            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10503            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10504        }
10505    }
10506
10507    /**
10508     * Sets the TouchDelegate for this View.
10509     */
10510    public void setTouchDelegate(TouchDelegate delegate) {
10511        mTouchDelegate = delegate;
10512    }
10513
10514    /**
10515     * Gets the TouchDelegate for this View.
10516     */
10517    public TouchDelegate getTouchDelegate() {
10518        return mTouchDelegate;
10519    }
10520
10521    /**
10522     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10523     *
10524     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10525     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10526     * available. This method should only be called for touch events.
10527     *
10528     * <p class="note">This api is not intended for most applications. Buffered dispatch
10529     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10530     * streams will not improve your input latency. Side effects include: increased latency,
10531     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10532     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10533     * you.</p>
10534     */
10535    public final void requestUnbufferedDispatch(MotionEvent event) {
10536        final int action = event.getAction();
10537        if (mAttachInfo == null
10538                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10539                || !event.isTouchEvent()) {
10540            return;
10541        }
10542        mAttachInfo.mUnbufferedDispatchRequested = true;
10543    }
10544
10545    /**
10546     * Set flags controlling behavior of this view.
10547     *
10548     * @param flags Constant indicating the value which should be set
10549     * @param mask Constant indicating the bit range that should be changed
10550     */
10551    void setFlags(int flags, int mask) {
10552        final boolean accessibilityEnabled =
10553                AccessibilityManager.getInstance(mContext).isEnabled();
10554        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10555
10556        int old = mViewFlags;
10557        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10558
10559        int changed = mViewFlags ^ old;
10560        if (changed == 0) {
10561            return;
10562        }
10563        int privateFlags = mPrivateFlags;
10564
10565        /* Check if the FOCUSABLE bit has changed */
10566        if (((changed & FOCUSABLE_MASK) != 0) &&
10567                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10568            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10569                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10570                /* Give up focus if we are no longer focusable */
10571                clearFocus();
10572            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10573                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10574                /*
10575                 * Tell the view system that we are now available to take focus
10576                 * if no one else already has it.
10577                 */
10578                if (mParent != null) mParent.focusableViewAvailable(this);
10579            }
10580        }
10581
10582        final int newVisibility = flags & VISIBILITY_MASK;
10583        if (newVisibility == VISIBLE) {
10584            if ((changed & VISIBILITY_MASK) != 0) {
10585                /*
10586                 * If this view is becoming visible, invalidate it in case it changed while
10587                 * it was not visible. Marking it drawn ensures that the invalidation will
10588                 * go through.
10589                 */
10590                mPrivateFlags |= PFLAG_DRAWN;
10591                invalidate(true);
10592
10593                needGlobalAttributesUpdate(true);
10594
10595                // a view becoming visible is worth notifying the parent
10596                // about in case nothing has focus.  even if this specific view
10597                // isn't focusable, it may contain something that is, so let
10598                // the root view try to give this focus if nothing else does.
10599                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10600                    mParent.focusableViewAvailable(this);
10601                }
10602            }
10603        }
10604
10605        /* Check if the GONE bit has changed */
10606        if ((changed & GONE) != 0) {
10607            needGlobalAttributesUpdate(false);
10608            requestLayout();
10609
10610            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10611                if (hasFocus()) clearFocus();
10612                clearAccessibilityFocus();
10613                destroyDrawingCache();
10614                if (mParent instanceof View) {
10615                    // GONE views noop invalidation, so invalidate the parent
10616                    ((View) mParent).invalidate(true);
10617                }
10618                // Mark the view drawn to ensure that it gets invalidated properly the next
10619                // time it is visible and gets invalidated
10620                mPrivateFlags |= PFLAG_DRAWN;
10621            }
10622            if (mAttachInfo != null) {
10623                mAttachInfo.mViewVisibilityChanged = true;
10624            }
10625        }
10626
10627        /* Check if the VISIBLE bit has changed */
10628        if ((changed & INVISIBLE) != 0) {
10629            needGlobalAttributesUpdate(false);
10630            /*
10631             * If this view is becoming invisible, set the DRAWN flag so that
10632             * the next invalidate() will not be skipped.
10633             */
10634            mPrivateFlags |= PFLAG_DRAWN;
10635
10636            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10637                // root view becoming invisible shouldn't clear focus and accessibility focus
10638                if (getRootView() != this) {
10639                    if (hasFocus()) clearFocus();
10640                    clearAccessibilityFocus();
10641                }
10642            }
10643            if (mAttachInfo != null) {
10644                mAttachInfo.mViewVisibilityChanged = true;
10645            }
10646        }
10647
10648        if ((changed & VISIBILITY_MASK) != 0) {
10649            // If the view is invisible, cleanup its display list to free up resources
10650            if (newVisibility != VISIBLE && mAttachInfo != null) {
10651                cleanupDraw();
10652            }
10653
10654            if (mParent instanceof ViewGroup) {
10655                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10656                        (changed & VISIBILITY_MASK), newVisibility);
10657                ((View) mParent).invalidate(true);
10658            } else if (mParent != null) {
10659                mParent.invalidateChild(this, null);
10660            }
10661
10662            if (mAttachInfo != null) {
10663                dispatchVisibilityChanged(this, newVisibility);
10664                notifySubtreeAccessibilityStateChangedIfNeeded();
10665            }
10666        }
10667
10668        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10669            destroyDrawingCache();
10670        }
10671
10672        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10673            destroyDrawingCache();
10674            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10675            invalidateParentCaches();
10676        }
10677
10678        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10679            destroyDrawingCache();
10680            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10681        }
10682
10683        if ((changed & DRAW_MASK) != 0) {
10684            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10685                if (mBackground != null
10686                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10687                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10688                } else {
10689                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10690                }
10691            } else {
10692                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10693            }
10694            requestLayout();
10695            invalidate(true);
10696        }
10697
10698        if ((changed & KEEP_SCREEN_ON) != 0) {
10699            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10700                mParent.recomputeViewAttributes(this);
10701            }
10702        }
10703
10704        if (accessibilityEnabled) {
10705            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10706                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10707                    || (changed & CONTEXT_CLICKABLE) != 0) {
10708                if (oldIncludeForAccessibility != includeForAccessibility()) {
10709                    notifySubtreeAccessibilityStateChangedIfNeeded();
10710                } else {
10711                    notifyViewAccessibilityStateChangedIfNeeded(
10712                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10713                }
10714            } else if ((changed & ENABLED_MASK) != 0) {
10715                notifyViewAccessibilityStateChangedIfNeeded(
10716                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10717            }
10718        }
10719    }
10720
10721    /**
10722     * Change the view's z order in the tree, so it's on top of other sibling
10723     * views. This ordering change may affect layout, if the parent container
10724     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10725     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10726     * method should be followed by calls to {@link #requestLayout()} and
10727     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10728     * with the new child ordering.
10729     *
10730     * @see ViewGroup#bringChildToFront(View)
10731     */
10732    public void bringToFront() {
10733        if (mParent != null) {
10734            mParent.bringChildToFront(this);
10735        }
10736    }
10737
10738    /**
10739     * This is called in response to an internal scroll in this view (i.e., the
10740     * view scrolled its own contents). This is typically as a result of
10741     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10742     * called.
10743     *
10744     * @param l Current horizontal scroll origin.
10745     * @param t Current vertical scroll origin.
10746     * @param oldl Previous horizontal scroll origin.
10747     * @param oldt Previous vertical scroll origin.
10748     */
10749    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10750        notifySubtreeAccessibilityStateChangedIfNeeded();
10751
10752        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10753            postSendViewScrolledAccessibilityEventCallback();
10754        }
10755
10756        mBackgroundSizeChanged = true;
10757        if (mForegroundInfo != null) {
10758            mForegroundInfo.mBoundsChanged = true;
10759        }
10760
10761        final AttachInfo ai = mAttachInfo;
10762        if (ai != null) {
10763            ai.mViewScrollChanged = true;
10764        }
10765
10766        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10767            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10768        }
10769    }
10770
10771    /**
10772     * Interface definition for a callback to be invoked when the scroll
10773     * X or Y positions of a view change.
10774     * <p>
10775     * <b>Note:</b> Some views handle scrolling independently from View and may
10776     * have their own separate listeners for scroll-type events. For example,
10777     * {@link android.widget.ListView ListView} allows clients to register an
10778     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10779     * to listen for changes in list scroll position.
10780     *
10781     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10782     */
10783    public interface OnScrollChangeListener {
10784        /**
10785         * Called when the scroll position of a view changes.
10786         *
10787         * @param v The view whose scroll position has changed.
10788         * @param scrollX Current horizontal scroll origin.
10789         * @param scrollY Current vertical scroll origin.
10790         * @param oldScrollX Previous horizontal scroll origin.
10791         * @param oldScrollY Previous vertical scroll origin.
10792         */
10793        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10794    }
10795
10796    /**
10797     * Interface definition for a callback to be invoked when the layout bounds of a view
10798     * changes due to layout processing.
10799     */
10800    public interface OnLayoutChangeListener {
10801        /**
10802         * Called when the layout bounds of a view changes due to layout processing.
10803         *
10804         * @param v The view whose bounds have changed.
10805         * @param left The new value of the view's left property.
10806         * @param top The new value of the view's top property.
10807         * @param right The new value of the view's right property.
10808         * @param bottom The new value of the view's bottom property.
10809         * @param oldLeft The previous value of the view's left property.
10810         * @param oldTop The previous value of the view's top property.
10811         * @param oldRight The previous value of the view's right property.
10812         * @param oldBottom The previous value of the view's bottom property.
10813         */
10814        void onLayoutChange(View v, int left, int top, int right, int bottom,
10815            int oldLeft, int oldTop, int oldRight, int oldBottom);
10816    }
10817
10818    /**
10819     * This is called during layout when the size of this view has changed. If
10820     * you were just added to the view hierarchy, you're called with the old
10821     * values of 0.
10822     *
10823     * @param w Current width of this view.
10824     * @param h Current height of this view.
10825     * @param oldw Old width of this view.
10826     * @param oldh Old height of this view.
10827     */
10828    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10829    }
10830
10831    /**
10832     * Called by draw to draw the child views. This may be overridden
10833     * by derived classes to gain control just before its children are drawn
10834     * (but after its own view has been drawn).
10835     * @param canvas the canvas on which to draw the view
10836     */
10837    protected void dispatchDraw(Canvas canvas) {
10838
10839    }
10840
10841    /**
10842     * Gets the parent of this view. Note that the parent is a
10843     * ViewParent and not necessarily a View.
10844     *
10845     * @return Parent of this view.
10846     */
10847    public final ViewParent getParent() {
10848        return mParent;
10849    }
10850
10851    /**
10852     * Set the horizontal scrolled position of your view. This will cause a call to
10853     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10854     * invalidated.
10855     * @param value the x position to scroll to
10856     */
10857    public void setScrollX(int value) {
10858        scrollTo(value, mScrollY);
10859    }
10860
10861    /**
10862     * Set the vertical scrolled position of your view. This will cause a call to
10863     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10864     * invalidated.
10865     * @param value the y position to scroll to
10866     */
10867    public void setScrollY(int value) {
10868        scrollTo(mScrollX, value);
10869    }
10870
10871    /**
10872     * Return the scrolled left position of this view. This is the left edge of
10873     * the displayed part of your view. You do not need to draw any pixels
10874     * farther left, since those are outside of the frame of your view on
10875     * screen.
10876     *
10877     * @return The left edge of the displayed part of your view, in pixels.
10878     */
10879    public final int getScrollX() {
10880        return mScrollX;
10881    }
10882
10883    /**
10884     * Return the scrolled top position of this view. This is the top edge of
10885     * the displayed part of your view. You do not need to draw any pixels above
10886     * it, since those are outside of the frame of your view on screen.
10887     *
10888     * @return The top edge of the displayed part of your view, in pixels.
10889     */
10890    public final int getScrollY() {
10891        return mScrollY;
10892    }
10893
10894    /**
10895     * Return the width of the your view.
10896     *
10897     * @return The width of your view, in pixels.
10898     */
10899    @ViewDebug.ExportedProperty(category = "layout")
10900    public final int getWidth() {
10901        return mRight - mLeft;
10902    }
10903
10904    /**
10905     * Return the height of your view.
10906     *
10907     * @return The height of your view, in pixels.
10908     */
10909    @ViewDebug.ExportedProperty(category = "layout")
10910    public final int getHeight() {
10911        return mBottom - mTop;
10912    }
10913
10914    /**
10915     * Return the visible drawing bounds of your view. Fills in the output
10916     * rectangle with the values from getScrollX(), getScrollY(),
10917     * getWidth(), and getHeight(). These bounds do not account for any
10918     * transformation properties currently set on the view, such as
10919     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10920     *
10921     * @param outRect The (scrolled) drawing bounds of the view.
10922     */
10923    public void getDrawingRect(Rect outRect) {
10924        outRect.left = mScrollX;
10925        outRect.top = mScrollY;
10926        outRect.right = mScrollX + (mRight - mLeft);
10927        outRect.bottom = mScrollY + (mBottom - mTop);
10928    }
10929
10930    /**
10931     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10932     * raw width component (that is the result is masked by
10933     * {@link #MEASURED_SIZE_MASK}).
10934     *
10935     * @return The raw measured width of this view.
10936     */
10937    public final int getMeasuredWidth() {
10938        return mMeasuredWidth & MEASURED_SIZE_MASK;
10939    }
10940
10941    /**
10942     * Return the full width measurement information for this view as computed
10943     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10944     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10945     * This should be used during measurement and layout calculations only. Use
10946     * {@link #getWidth()} to see how wide a view is after layout.
10947     *
10948     * @return The measured width of this view as a bit mask.
10949     */
10950    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10951            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10952                    name = "MEASURED_STATE_TOO_SMALL"),
10953    })
10954    public final int getMeasuredWidthAndState() {
10955        return mMeasuredWidth;
10956    }
10957
10958    /**
10959     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10960     * raw width component (that is the result is masked by
10961     * {@link #MEASURED_SIZE_MASK}).
10962     *
10963     * @return The raw measured height of this view.
10964     */
10965    public final int getMeasuredHeight() {
10966        return mMeasuredHeight & MEASURED_SIZE_MASK;
10967    }
10968
10969    /**
10970     * Return the full height measurement information for this view as computed
10971     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10972     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10973     * This should be used during measurement and layout calculations only. Use
10974     * {@link #getHeight()} to see how wide a view is after layout.
10975     *
10976     * @return The measured width of this view as a bit mask.
10977     */
10978    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10979            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10980                    name = "MEASURED_STATE_TOO_SMALL"),
10981    })
10982    public final int getMeasuredHeightAndState() {
10983        return mMeasuredHeight;
10984    }
10985
10986    /**
10987     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10988     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10989     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10990     * and the height component is at the shifted bits
10991     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10992     */
10993    public final int getMeasuredState() {
10994        return (mMeasuredWidth&MEASURED_STATE_MASK)
10995                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10996                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10997    }
10998
10999    /**
11000     * The transform matrix of this view, which is calculated based on the current
11001     * rotation, scale, and pivot properties.
11002     *
11003     * @see #getRotation()
11004     * @see #getScaleX()
11005     * @see #getScaleY()
11006     * @see #getPivotX()
11007     * @see #getPivotY()
11008     * @return The current transform matrix for the view
11009     */
11010    public Matrix getMatrix() {
11011        ensureTransformationInfo();
11012        final Matrix matrix = mTransformationInfo.mMatrix;
11013        mRenderNode.getMatrix(matrix);
11014        return matrix;
11015    }
11016
11017    /**
11018     * Returns true if the transform matrix is the identity matrix.
11019     * Recomputes the matrix if necessary.
11020     *
11021     * @return True if the transform matrix is the identity matrix, false otherwise.
11022     */
11023    final boolean hasIdentityMatrix() {
11024        return mRenderNode.hasIdentityMatrix();
11025    }
11026
11027    void ensureTransformationInfo() {
11028        if (mTransformationInfo == null) {
11029            mTransformationInfo = new TransformationInfo();
11030        }
11031    }
11032
11033   /**
11034     * Utility method to retrieve the inverse of the current mMatrix property.
11035     * We cache the matrix to avoid recalculating it when transform properties
11036     * have not changed.
11037     *
11038     * @return The inverse of the current matrix of this view.
11039     * @hide
11040     */
11041    public final Matrix getInverseMatrix() {
11042        ensureTransformationInfo();
11043        if (mTransformationInfo.mInverseMatrix == null) {
11044            mTransformationInfo.mInverseMatrix = new Matrix();
11045        }
11046        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11047        mRenderNode.getInverseMatrix(matrix);
11048        return matrix;
11049    }
11050
11051    /**
11052     * Gets the distance along the Z axis from the camera to this view.
11053     *
11054     * @see #setCameraDistance(float)
11055     *
11056     * @return The distance along the Z axis.
11057     */
11058    public float getCameraDistance() {
11059        final float dpi = mResources.getDisplayMetrics().densityDpi;
11060        return -(mRenderNode.getCameraDistance() * dpi);
11061    }
11062
11063    /**
11064     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11065     * views are drawn) from the camera to this view. The camera's distance
11066     * affects 3D transformations, for instance rotations around the X and Y
11067     * axis. If the rotationX or rotationY properties are changed and this view is
11068     * large (more than half the size of the screen), it is recommended to always
11069     * use a camera distance that's greater than the height (X axis rotation) or
11070     * the width (Y axis rotation) of this view.</p>
11071     *
11072     * <p>The distance of the camera from the view plane can have an affect on the
11073     * perspective distortion of the view when it is rotated around the x or y axis.
11074     * For example, a large distance will result in a large viewing angle, and there
11075     * will not be much perspective distortion of the view as it rotates. A short
11076     * distance may cause much more perspective distortion upon rotation, and can
11077     * also result in some drawing artifacts if the rotated view ends up partially
11078     * behind the camera (which is why the recommendation is to use a distance at
11079     * least as far as the size of the view, if the view is to be rotated.)</p>
11080     *
11081     * <p>The distance is expressed in "depth pixels." The default distance depends
11082     * on the screen density. For instance, on a medium density display, the
11083     * default distance is 1280. On a high density display, the default distance
11084     * is 1920.</p>
11085     *
11086     * <p>If you want to specify a distance that leads to visually consistent
11087     * results across various densities, use the following formula:</p>
11088     * <pre>
11089     * float scale = context.getResources().getDisplayMetrics().density;
11090     * view.setCameraDistance(distance * scale);
11091     * </pre>
11092     *
11093     * <p>The density scale factor of a high density display is 1.5,
11094     * and 1920 = 1280 * 1.5.</p>
11095     *
11096     * @param distance The distance in "depth pixels", if negative the opposite
11097     *        value is used
11098     *
11099     * @see #setRotationX(float)
11100     * @see #setRotationY(float)
11101     */
11102    public void setCameraDistance(float distance) {
11103        final float dpi = mResources.getDisplayMetrics().densityDpi;
11104
11105        invalidateViewProperty(true, false);
11106        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11107        invalidateViewProperty(false, false);
11108
11109        invalidateParentIfNeededAndWasQuickRejected();
11110    }
11111
11112    /**
11113     * The degrees that the view is rotated around the pivot point.
11114     *
11115     * @see #setRotation(float)
11116     * @see #getPivotX()
11117     * @see #getPivotY()
11118     *
11119     * @return The degrees of rotation.
11120     */
11121    @ViewDebug.ExportedProperty(category = "drawing")
11122    public float getRotation() {
11123        return mRenderNode.getRotation();
11124    }
11125
11126    /**
11127     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11128     * result in clockwise rotation.
11129     *
11130     * @param rotation The degrees of rotation.
11131     *
11132     * @see #getRotation()
11133     * @see #getPivotX()
11134     * @see #getPivotY()
11135     * @see #setRotationX(float)
11136     * @see #setRotationY(float)
11137     *
11138     * @attr ref android.R.styleable#View_rotation
11139     */
11140    public void setRotation(float rotation) {
11141        if (rotation != getRotation()) {
11142            // Double-invalidation is necessary to capture view's old and new areas
11143            invalidateViewProperty(true, false);
11144            mRenderNode.setRotation(rotation);
11145            invalidateViewProperty(false, true);
11146
11147            invalidateParentIfNeededAndWasQuickRejected();
11148            notifySubtreeAccessibilityStateChangedIfNeeded();
11149        }
11150    }
11151
11152    /**
11153     * The degrees that the view is rotated around the vertical axis through the pivot point.
11154     *
11155     * @see #getPivotX()
11156     * @see #getPivotY()
11157     * @see #setRotationY(float)
11158     *
11159     * @return The degrees of Y rotation.
11160     */
11161    @ViewDebug.ExportedProperty(category = "drawing")
11162    public float getRotationY() {
11163        return mRenderNode.getRotationY();
11164    }
11165
11166    /**
11167     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11168     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11169     * down the y axis.
11170     *
11171     * When rotating large views, it is recommended to adjust the camera distance
11172     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11173     *
11174     * @param rotationY The degrees of Y rotation.
11175     *
11176     * @see #getRotationY()
11177     * @see #getPivotX()
11178     * @see #getPivotY()
11179     * @see #setRotation(float)
11180     * @see #setRotationX(float)
11181     * @see #setCameraDistance(float)
11182     *
11183     * @attr ref android.R.styleable#View_rotationY
11184     */
11185    public void setRotationY(float rotationY) {
11186        if (rotationY != getRotationY()) {
11187            invalidateViewProperty(true, false);
11188            mRenderNode.setRotationY(rotationY);
11189            invalidateViewProperty(false, true);
11190
11191            invalidateParentIfNeededAndWasQuickRejected();
11192            notifySubtreeAccessibilityStateChangedIfNeeded();
11193        }
11194    }
11195
11196    /**
11197     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11198     *
11199     * @see #getPivotX()
11200     * @see #getPivotY()
11201     * @see #setRotationX(float)
11202     *
11203     * @return The degrees of X rotation.
11204     */
11205    @ViewDebug.ExportedProperty(category = "drawing")
11206    public float getRotationX() {
11207        return mRenderNode.getRotationX();
11208    }
11209
11210    /**
11211     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11212     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11213     * x axis.
11214     *
11215     * When rotating large views, it is recommended to adjust the camera distance
11216     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11217     *
11218     * @param rotationX The degrees of X rotation.
11219     *
11220     * @see #getRotationX()
11221     * @see #getPivotX()
11222     * @see #getPivotY()
11223     * @see #setRotation(float)
11224     * @see #setRotationY(float)
11225     * @see #setCameraDistance(float)
11226     *
11227     * @attr ref android.R.styleable#View_rotationX
11228     */
11229    public void setRotationX(float rotationX) {
11230        if (rotationX != getRotationX()) {
11231            invalidateViewProperty(true, false);
11232            mRenderNode.setRotationX(rotationX);
11233            invalidateViewProperty(false, true);
11234
11235            invalidateParentIfNeededAndWasQuickRejected();
11236            notifySubtreeAccessibilityStateChangedIfNeeded();
11237        }
11238    }
11239
11240    /**
11241     * The amount that the view is scaled in x around the pivot point, as a proportion of
11242     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11243     *
11244     * <p>By default, this is 1.0f.
11245     *
11246     * @see #getPivotX()
11247     * @see #getPivotY()
11248     * @return The scaling factor.
11249     */
11250    @ViewDebug.ExportedProperty(category = "drawing")
11251    public float getScaleX() {
11252        return mRenderNode.getScaleX();
11253    }
11254
11255    /**
11256     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11257     * the view's unscaled width. A value of 1 means that no scaling is applied.
11258     *
11259     * @param scaleX The scaling factor.
11260     * @see #getPivotX()
11261     * @see #getPivotY()
11262     *
11263     * @attr ref android.R.styleable#View_scaleX
11264     */
11265    public void setScaleX(float scaleX) {
11266        if (scaleX != getScaleX()) {
11267            invalidateViewProperty(true, false);
11268            mRenderNode.setScaleX(scaleX);
11269            invalidateViewProperty(false, true);
11270
11271            invalidateParentIfNeededAndWasQuickRejected();
11272            notifySubtreeAccessibilityStateChangedIfNeeded();
11273        }
11274    }
11275
11276    /**
11277     * The amount that the view is scaled in y around the pivot point, as a proportion of
11278     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11279     *
11280     * <p>By default, this is 1.0f.
11281     *
11282     * @see #getPivotX()
11283     * @see #getPivotY()
11284     * @return The scaling factor.
11285     */
11286    @ViewDebug.ExportedProperty(category = "drawing")
11287    public float getScaleY() {
11288        return mRenderNode.getScaleY();
11289    }
11290
11291    /**
11292     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11293     * the view's unscaled width. A value of 1 means that no scaling is applied.
11294     *
11295     * @param scaleY The scaling factor.
11296     * @see #getPivotX()
11297     * @see #getPivotY()
11298     *
11299     * @attr ref android.R.styleable#View_scaleY
11300     */
11301    public void setScaleY(float scaleY) {
11302        if (scaleY != getScaleY()) {
11303            invalidateViewProperty(true, false);
11304            mRenderNode.setScaleY(scaleY);
11305            invalidateViewProperty(false, true);
11306
11307            invalidateParentIfNeededAndWasQuickRejected();
11308            notifySubtreeAccessibilityStateChangedIfNeeded();
11309        }
11310    }
11311
11312    /**
11313     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11314     * and {@link #setScaleX(float) scaled}.
11315     *
11316     * @see #getRotation()
11317     * @see #getScaleX()
11318     * @see #getScaleY()
11319     * @see #getPivotY()
11320     * @return The x location of the pivot point.
11321     *
11322     * @attr ref android.R.styleable#View_transformPivotX
11323     */
11324    @ViewDebug.ExportedProperty(category = "drawing")
11325    public float getPivotX() {
11326        return mRenderNode.getPivotX();
11327    }
11328
11329    /**
11330     * Sets the x location of the point around which the view is
11331     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11332     * By default, the pivot point is centered on the object.
11333     * Setting this property disables this behavior and causes the view to use only the
11334     * explicitly set pivotX and pivotY values.
11335     *
11336     * @param pivotX The x location of the pivot point.
11337     * @see #getRotation()
11338     * @see #getScaleX()
11339     * @see #getScaleY()
11340     * @see #getPivotY()
11341     *
11342     * @attr ref android.R.styleable#View_transformPivotX
11343     */
11344    public void setPivotX(float pivotX) {
11345        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11346            invalidateViewProperty(true, false);
11347            mRenderNode.setPivotX(pivotX);
11348            invalidateViewProperty(false, true);
11349
11350            invalidateParentIfNeededAndWasQuickRejected();
11351        }
11352    }
11353
11354    /**
11355     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11356     * and {@link #setScaleY(float) scaled}.
11357     *
11358     * @see #getRotation()
11359     * @see #getScaleX()
11360     * @see #getScaleY()
11361     * @see #getPivotY()
11362     * @return The y location of the pivot point.
11363     *
11364     * @attr ref android.R.styleable#View_transformPivotY
11365     */
11366    @ViewDebug.ExportedProperty(category = "drawing")
11367    public float getPivotY() {
11368        return mRenderNode.getPivotY();
11369    }
11370
11371    /**
11372     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11373     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11374     * Setting this property disables this behavior and causes the view to use only the
11375     * explicitly set pivotX and pivotY values.
11376     *
11377     * @param pivotY The y location of the pivot point.
11378     * @see #getRotation()
11379     * @see #getScaleX()
11380     * @see #getScaleY()
11381     * @see #getPivotY()
11382     *
11383     * @attr ref android.R.styleable#View_transformPivotY
11384     */
11385    public void setPivotY(float pivotY) {
11386        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11387            invalidateViewProperty(true, false);
11388            mRenderNode.setPivotY(pivotY);
11389            invalidateViewProperty(false, true);
11390
11391            invalidateParentIfNeededAndWasQuickRejected();
11392        }
11393    }
11394
11395    /**
11396     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11397     * completely transparent and 1 means the view is completely opaque.
11398     *
11399     * <p>By default this is 1.0f.
11400     * @return The opacity of the view.
11401     */
11402    @ViewDebug.ExportedProperty(category = "drawing")
11403    public float getAlpha() {
11404        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11405    }
11406
11407    /**
11408     * Returns whether this View has content which overlaps.
11409     *
11410     * <p>This function, intended to be overridden by specific View types, is an optimization when
11411     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11412     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11413     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11414     * directly. An example of overlapping rendering is a TextView with a background image, such as
11415     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11416     * ImageView with only the foreground image. The default implementation returns true; subclasses
11417     * should override if they have cases which can be optimized.</p>
11418     *
11419     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11420     * necessitates that a View return true if it uses the methods internally without passing the
11421     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11422     *
11423     * @return true if the content in this view might overlap, false otherwise.
11424     */
11425    @ViewDebug.ExportedProperty(category = "drawing")
11426    public boolean hasOverlappingRendering() {
11427        return true;
11428    }
11429
11430    /**
11431     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11432     * completely transparent and 1 means the view is completely opaque.
11433     *
11434     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11435     * can have significant performance implications, especially for large views. It is best to use
11436     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11437     *
11438     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11439     * strongly recommended for performance reasons to either override
11440     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11441     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11442     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11443     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11444     * of rendering cost, even for simple or small views. Starting with
11445     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11446     * applied to the view at the rendering level.</p>
11447     *
11448     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11449     * responsible for applying the opacity itself.</p>
11450     *
11451     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11452     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11453     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11454     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11455     *
11456     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11457     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11458     * {@link #hasOverlappingRendering}.</p>
11459     *
11460     * @param alpha The opacity of the view.
11461     *
11462     * @see #hasOverlappingRendering()
11463     * @see #setLayerType(int, android.graphics.Paint)
11464     *
11465     * @attr ref android.R.styleable#View_alpha
11466     */
11467    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11468        ensureTransformationInfo();
11469        if (mTransformationInfo.mAlpha != alpha) {
11470            mTransformationInfo.mAlpha = alpha;
11471            if (onSetAlpha((int) (alpha * 255))) {
11472                mPrivateFlags |= PFLAG_ALPHA_SET;
11473                // subclass is handling alpha - don't optimize rendering cache invalidation
11474                invalidateParentCaches();
11475                invalidate(true);
11476            } else {
11477                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11478                invalidateViewProperty(true, false);
11479                mRenderNode.setAlpha(getFinalAlpha());
11480                notifyViewAccessibilityStateChangedIfNeeded(
11481                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11482            }
11483        }
11484    }
11485
11486    /**
11487     * Faster version of setAlpha() which performs the same steps except there are
11488     * no calls to invalidate(). The caller of this function should perform proper invalidation
11489     * on the parent and this object. The return value indicates whether the subclass handles
11490     * alpha (the return value for onSetAlpha()).
11491     *
11492     * @param alpha The new value for the alpha property
11493     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11494     *         the new value for the alpha property is different from the old value
11495     */
11496    boolean setAlphaNoInvalidation(float alpha) {
11497        ensureTransformationInfo();
11498        if (mTransformationInfo.mAlpha != alpha) {
11499            mTransformationInfo.mAlpha = alpha;
11500            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11501            if (subclassHandlesAlpha) {
11502                mPrivateFlags |= PFLAG_ALPHA_SET;
11503                return true;
11504            } else {
11505                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11506                mRenderNode.setAlpha(getFinalAlpha());
11507            }
11508        }
11509        return false;
11510    }
11511
11512    /**
11513     * This property is hidden and intended only for use by the Fade transition, which
11514     * animates it to produce a visual translucency that does not side-effect (or get
11515     * affected by) the real alpha property. This value is composited with the other
11516     * alpha value (and the AlphaAnimation value, when that is present) to produce
11517     * a final visual translucency result, which is what is passed into the DisplayList.
11518     *
11519     * @hide
11520     */
11521    public void setTransitionAlpha(float alpha) {
11522        ensureTransformationInfo();
11523        if (mTransformationInfo.mTransitionAlpha != alpha) {
11524            mTransformationInfo.mTransitionAlpha = alpha;
11525            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11526            invalidateViewProperty(true, false);
11527            mRenderNode.setAlpha(getFinalAlpha());
11528        }
11529    }
11530
11531    /**
11532     * Calculates the visual alpha of this view, which is a combination of the actual
11533     * alpha value and the transitionAlpha value (if set).
11534     */
11535    private float getFinalAlpha() {
11536        if (mTransformationInfo != null) {
11537            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11538        }
11539        return 1;
11540    }
11541
11542    /**
11543     * This property is hidden and intended only for use by the Fade transition, which
11544     * animates it to produce a visual translucency that does not side-effect (or get
11545     * affected by) the real alpha property. This value is composited with the other
11546     * alpha value (and the AlphaAnimation value, when that is present) to produce
11547     * a final visual translucency result, which is what is passed into the DisplayList.
11548     *
11549     * @hide
11550     */
11551    @ViewDebug.ExportedProperty(category = "drawing")
11552    public float getTransitionAlpha() {
11553        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11554    }
11555
11556    /**
11557     * Top position of this view relative to its parent.
11558     *
11559     * @return The top of this view, in pixels.
11560     */
11561    @ViewDebug.CapturedViewProperty
11562    public final int getTop() {
11563        return mTop;
11564    }
11565
11566    /**
11567     * Sets the top position of this view relative to its parent. This method is meant to be called
11568     * by the layout system and should not generally be called otherwise, because the property
11569     * may be changed at any time by the layout.
11570     *
11571     * @param top The top of this view, in pixels.
11572     */
11573    public final void setTop(int top) {
11574        if (top != mTop) {
11575            final boolean matrixIsIdentity = hasIdentityMatrix();
11576            if (matrixIsIdentity) {
11577                if (mAttachInfo != null) {
11578                    int minTop;
11579                    int yLoc;
11580                    if (top < mTop) {
11581                        minTop = top;
11582                        yLoc = top - mTop;
11583                    } else {
11584                        minTop = mTop;
11585                        yLoc = 0;
11586                    }
11587                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11588                }
11589            } else {
11590                // Double-invalidation is necessary to capture view's old and new areas
11591                invalidate(true);
11592            }
11593
11594            int width = mRight - mLeft;
11595            int oldHeight = mBottom - mTop;
11596
11597            mTop = top;
11598            mRenderNode.setTop(mTop);
11599
11600            sizeChange(width, mBottom - mTop, width, oldHeight);
11601
11602            if (!matrixIsIdentity) {
11603                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11604                invalidate(true);
11605            }
11606            mBackgroundSizeChanged = true;
11607            if (mForegroundInfo != null) {
11608                mForegroundInfo.mBoundsChanged = true;
11609            }
11610            invalidateParentIfNeeded();
11611            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11612                // View was rejected last time it was drawn by its parent; this may have changed
11613                invalidateParentIfNeeded();
11614            }
11615        }
11616    }
11617
11618    /**
11619     * Bottom position of this view relative to its parent.
11620     *
11621     * @return The bottom of this view, in pixels.
11622     */
11623    @ViewDebug.CapturedViewProperty
11624    public final int getBottom() {
11625        return mBottom;
11626    }
11627
11628    /**
11629     * True if this view has changed since the last time being drawn.
11630     *
11631     * @return The dirty state of this view.
11632     */
11633    public boolean isDirty() {
11634        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11635    }
11636
11637    /**
11638     * Sets the bottom position of this view relative to its parent. This method is meant to be
11639     * called by the layout system and should not generally be called otherwise, because the
11640     * property may be changed at any time by the layout.
11641     *
11642     * @param bottom The bottom of this view, in pixels.
11643     */
11644    public final void setBottom(int bottom) {
11645        if (bottom != mBottom) {
11646            final boolean matrixIsIdentity = hasIdentityMatrix();
11647            if (matrixIsIdentity) {
11648                if (mAttachInfo != null) {
11649                    int maxBottom;
11650                    if (bottom < mBottom) {
11651                        maxBottom = mBottom;
11652                    } else {
11653                        maxBottom = bottom;
11654                    }
11655                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11656                }
11657            } else {
11658                // Double-invalidation is necessary to capture view's old and new areas
11659                invalidate(true);
11660            }
11661
11662            int width = mRight - mLeft;
11663            int oldHeight = mBottom - mTop;
11664
11665            mBottom = bottom;
11666            mRenderNode.setBottom(mBottom);
11667
11668            sizeChange(width, mBottom - mTop, width, oldHeight);
11669
11670            if (!matrixIsIdentity) {
11671                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11672                invalidate(true);
11673            }
11674            mBackgroundSizeChanged = true;
11675            if (mForegroundInfo != null) {
11676                mForegroundInfo.mBoundsChanged = true;
11677            }
11678            invalidateParentIfNeeded();
11679            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11680                // View was rejected last time it was drawn by its parent; this may have changed
11681                invalidateParentIfNeeded();
11682            }
11683        }
11684    }
11685
11686    /**
11687     * Left position of this view relative to its parent.
11688     *
11689     * @return The left edge of this view, in pixels.
11690     */
11691    @ViewDebug.CapturedViewProperty
11692    public final int getLeft() {
11693        return mLeft;
11694    }
11695
11696    /**
11697     * Sets the left position of this view relative to its parent. This method is meant to be called
11698     * by the layout system and should not generally be called otherwise, because the property
11699     * may be changed at any time by the layout.
11700     *
11701     * @param left The left of this view, in pixels.
11702     */
11703    public final void setLeft(int left) {
11704        if (left != mLeft) {
11705            final boolean matrixIsIdentity = hasIdentityMatrix();
11706            if (matrixIsIdentity) {
11707                if (mAttachInfo != null) {
11708                    int minLeft;
11709                    int xLoc;
11710                    if (left < mLeft) {
11711                        minLeft = left;
11712                        xLoc = left - mLeft;
11713                    } else {
11714                        minLeft = mLeft;
11715                        xLoc = 0;
11716                    }
11717                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11718                }
11719            } else {
11720                // Double-invalidation is necessary to capture view's old and new areas
11721                invalidate(true);
11722            }
11723
11724            int oldWidth = mRight - mLeft;
11725            int height = mBottom - mTop;
11726
11727            mLeft = left;
11728            mRenderNode.setLeft(left);
11729
11730            sizeChange(mRight - mLeft, height, oldWidth, height);
11731
11732            if (!matrixIsIdentity) {
11733                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11734                invalidate(true);
11735            }
11736            mBackgroundSizeChanged = true;
11737            if (mForegroundInfo != null) {
11738                mForegroundInfo.mBoundsChanged = true;
11739            }
11740            invalidateParentIfNeeded();
11741            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11742                // View was rejected last time it was drawn by its parent; this may have changed
11743                invalidateParentIfNeeded();
11744            }
11745        }
11746    }
11747
11748    /**
11749     * Right position of this view relative to its parent.
11750     *
11751     * @return The right edge of this view, in pixels.
11752     */
11753    @ViewDebug.CapturedViewProperty
11754    public final int getRight() {
11755        return mRight;
11756    }
11757
11758    /**
11759     * Sets the right position of this view relative to its parent. This method is meant to be called
11760     * by the layout system and should not generally be called otherwise, because the property
11761     * may be changed at any time by the layout.
11762     *
11763     * @param right The right of this view, in pixels.
11764     */
11765    public final void setRight(int right) {
11766        if (right != mRight) {
11767            final boolean matrixIsIdentity = hasIdentityMatrix();
11768            if (matrixIsIdentity) {
11769                if (mAttachInfo != null) {
11770                    int maxRight;
11771                    if (right < mRight) {
11772                        maxRight = mRight;
11773                    } else {
11774                        maxRight = right;
11775                    }
11776                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11777                }
11778            } else {
11779                // Double-invalidation is necessary to capture view's old and new areas
11780                invalidate(true);
11781            }
11782
11783            int oldWidth = mRight - mLeft;
11784            int height = mBottom - mTop;
11785
11786            mRight = right;
11787            mRenderNode.setRight(mRight);
11788
11789            sizeChange(mRight - mLeft, height, oldWidth, height);
11790
11791            if (!matrixIsIdentity) {
11792                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11793                invalidate(true);
11794            }
11795            mBackgroundSizeChanged = true;
11796            if (mForegroundInfo != null) {
11797                mForegroundInfo.mBoundsChanged = true;
11798            }
11799            invalidateParentIfNeeded();
11800            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11801                // View was rejected last time it was drawn by its parent; this may have changed
11802                invalidateParentIfNeeded();
11803            }
11804        }
11805    }
11806
11807    /**
11808     * The visual x position of this view, in pixels. This is equivalent to the
11809     * {@link #setTranslationX(float) translationX} property plus the current
11810     * {@link #getLeft() left} property.
11811     *
11812     * @return The visual x position of this view, in pixels.
11813     */
11814    @ViewDebug.ExportedProperty(category = "drawing")
11815    public float getX() {
11816        return mLeft + getTranslationX();
11817    }
11818
11819    /**
11820     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11821     * {@link #setTranslationX(float) translationX} property to be the difference between
11822     * the x value passed in and the current {@link #getLeft() left} property.
11823     *
11824     * @param x The visual x position of this view, in pixels.
11825     */
11826    public void setX(float x) {
11827        setTranslationX(x - mLeft);
11828    }
11829
11830    /**
11831     * The visual y position of this view, in pixels. This is equivalent to the
11832     * {@link #setTranslationY(float) translationY} property plus the current
11833     * {@link #getTop() top} property.
11834     *
11835     * @return The visual y position of this view, in pixels.
11836     */
11837    @ViewDebug.ExportedProperty(category = "drawing")
11838    public float getY() {
11839        return mTop + getTranslationY();
11840    }
11841
11842    /**
11843     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11844     * {@link #setTranslationY(float) translationY} property to be the difference between
11845     * the y value passed in and the current {@link #getTop() top} property.
11846     *
11847     * @param y The visual y position of this view, in pixels.
11848     */
11849    public void setY(float y) {
11850        setTranslationY(y - mTop);
11851    }
11852
11853    /**
11854     * The visual z position of this view, in pixels. This is equivalent to the
11855     * {@link #setTranslationZ(float) translationZ} property plus the current
11856     * {@link #getElevation() elevation} property.
11857     *
11858     * @return The visual z position of this view, in pixels.
11859     */
11860    @ViewDebug.ExportedProperty(category = "drawing")
11861    public float getZ() {
11862        return getElevation() + getTranslationZ();
11863    }
11864
11865    /**
11866     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11867     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11868     * the x value passed in and the current {@link #getElevation() elevation} property.
11869     *
11870     * @param z The visual z position of this view, in pixels.
11871     */
11872    public void setZ(float z) {
11873        setTranslationZ(z - getElevation());
11874    }
11875
11876    /**
11877     * The base elevation of this view relative to its parent, in pixels.
11878     *
11879     * @return The base depth position of the view, in pixels.
11880     */
11881    @ViewDebug.ExportedProperty(category = "drawing")
11882    public float getElevation() {
11883        return mRenderNode.getElevation();
11884    }
11885
11886    /**
11887     * Sets the base elevation of this view, in pixels.
11888     *
11889     * @attr ref android.R.styleable#View_elevation
11890     */
11891    public void setElevation(float elevation) {
11892        if (elevation != getElevation()) {
11893            invalidateViewProperty(true, false);
11894            mRenderNode.setElevation(elevation);
11895            invalidateViewProperty(false, true);
11896
11897            invalidateParentIfNeededAndWasQuickRejected();
11898        }
11899    }
11900
11901    /**
11902     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11903     * This position is post-layout, in addition to wherever the object's
11904     * layout placed it.
11905     *
11906     * @return The horizontal position of this view relative to its left position, in pixels.
11907     */
11908    @ViewDebug.ExportedProperty(category = "drawing")
11909    public float getTranslationX() {
11910        return mRenderNode.getTranslationX();
11911    }
11912
11913    /**
11914     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11915     * This effectively positions the object post-layout, in addition to wherever the object's
11916     * layout placed it.
11917     *
11918     * @param translationX The horizontal position of this view relative to its left position,
11919     * in pixels.
11920     *
11921     * @attr ref android.R.styleable#View_translationX
11922     */
11923    public void setTranslationX(float translationX) {
11924        if (translationX != getTranslationX()) {
11925            invalidateViewProperty(true, false);
11926            mRenderNode.setTranslationX(translationX);
11927            invalidateViewProperty(false, true);
11928
11929            invalidateParentIfNeededAndWasQuickRejected();
11930            notifySubtreeAccessibilityStateChangedIfNeeded();
11931        }
11932    }
11933
11934    /**
11935     * The vertical location of this view relative to its {@link #getTop() top} position.
11936     * This position is post-layout, in addition to wherever the object's
11937     * layout placed it.
11938     *
11939     * @return The vertical position of this view relative to its top position,
11940     * in pixels.
11941     */
11942    @ViewDebug.ExportedProperty(category = "drawing")
11943    public float getTranslationY() {
11944        return mRenderNode.getTranslationY();
11945    }
11946
11947    /**
11948     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11949     * This effectively positions the object post-layout, in addition to wherever the object's
11950     * layout placed it.
11951     *
11952     * @param translationY The vertical position of this view relative to its top position,
11953     * in pixels.
11954     *
11955     * @attr ref android.R.styleable#View_translationY
11956     */
11957    public void setTranslationY(float translationY) {
11958        if (translationY != getTranslationY()) {
11959            invalidateViewProperty(true, false);
11960            mRenderNode.setTranslationY(translationY);
11961            invalidateViewProperty(false, true);
11962
11963            invalidateParentIfNeededAndWasQuickRejected();
11964            notifySubtreeAccessibilityStateChangedIfNeeded();
11965        }
11966    }
11967
11968    /**
11969     * The depth location of this view relative to its {@link #getElevation() elevation}.
11970     *
11971     * @return The depth of this view relative to its elevation.
11972     */
11973    @ViewDebug.ExportedProperty(category = "drawing")
11974    public float getTranslationZ() {
11975        return mRenderNode.getTranslationZ();
11976    }
11977
11978    /**
11979     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11980     *
11981     * @attr ref android.R.styleable#View_translationZ
11982     */
11983    public void setTranslationZ(float translationZ) {
11984        if (translationZ != getTranslationZ()) {
11985            invalidateViewProperty(true, false);
11986            mRenderNode.setTranslationZ(translationZ);
11987            invalidateViewProperty(false, true);
11988
11989            invalidateParentIfNeededAndWasQuickRejected();
11990        }
11991    }
11992
11993    /** @hide */
11994    public void setAnimationMatrix(Matrix matrix) {
11995        invalidateViewProperty(true, false);
11996        mRenderNode.setAnimationMatrix(matrix);
11997        invalidateViewProperty(false, true);
11998
11999        invalidateParentIfNeededAndWasQuickRejected();
12000    }
12001
12002    /**
12003     * Returns the current StateListAnimator if exists.
12004     *
12005     * @return StateListAnimator or null if it does not exists
12006     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12007     */
12008    public StateListAnimator getStateListAnimator() {
12009        return mStateListAnimator;
12010    }
12011
12012    /**
12013     * Attaches the provided StateListAnimator to this View.
12014     * <p>
12015     * Any previously attached StateListAnimator will be detached.
12016     *
12017     * @param stateListAnimator The StateListAnimator to update the view
12018     * @see {@link android.animation.StateListAnimator}
12019     */
12020    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12021        if (mStateListAnimator == stateListAnimator) {
12022            return;
12023        }
12024        if (mStateListAnimator != null) {
12025            mStateListAnimator.setTarget(null);
12026        }
12027        mStateListAnimator = stateListAnimator;
12028        if (stateListAnimator != null) {
12029            stateListAnimator.setTarget(this);
12030            if (isAttachedToWindow()) {
12031                stateListAnimator.setState(getDrawableState());
12032            }
12033        }
12034    }
12035
12036    /**
12037     * Returns whether the Outline should be used to clip the contents of the View.
12038     * <p>
12039     * Note that this flag will only be respected if the View's Outline returns true from
12040     * {@link Outline#canClip()}.
12041     *
12042     * @see #setOutlineProvider(ViewOutlineProvider)
12043     * @see #setClipToOutline(boolean)
12044     */
12045    public final boolean getClipToOutline() {
12046        return mRenderNode.getClipToOutline();
12047    }
12048
12049    /**
12050     * Sets whether the View's Outline should be used to clip the contents of the View.
12051     * <p>
12052     * Only a single non-rectangular clip can be applied on a View at any time.
12053     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12054     * circular reveal} animation take priority over Outline clipping, and
12055     * child Outline clipping takes priority over Outline clipping done by a
12056     * parent.
12057     * <p>
12058     * Note that this flag will only be respected if the View's Outline returns true from
12059     * {@link Outline#canClip()}.
12060     *
12061     * @see #setOutlineProvider(ViewOutlineProvider)
12062     * @see #getClipToOutline()
12063     */
12064    public void setClipToOutline(boolean clipToOutline) {
12065        damageInParent();
12066        if (getClipToOutline() != clipToOutline) {
12067            mRenderNode.setClipToOutline(clipToOutline);
12068        }
12069    }
12070
12071    // correspond to the enum values of View_outlineProvider
12072    private static final int PROVIDER_BACKGROUND = 0;
12073    private static final int PROVIDER_NONE = 1;
12074    private static final int PROVIDER_BOUNDS = 2;
12075    private static final int PROVIDER_PADDED_BOUNDS = 3;
12076    private void setOutlineProviderFromAttribute(int providerInt) {
12077        switch (providerInt) {
12078            case PROVIDER_BACKGROUND:
12079                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12080                break;
12081            case PROVIDER_NONE:
12082                setOutlineProvider(null);
12083                break;
12084            case PROVIDER_BOUNDS:
12085                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12086                break;
12087            case PROVIDER_PADDED_BOUNDS:
12088                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12089                break;
12090        }
12091    }
12092
12093    /**
12094     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12095     * the shape of the shadow it casts, and enables outline clipping.
12096     * <p>
12097     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12098     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12099     * outline provider with this method allows this behavior to be overridden.
12100     * <p>
12101     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12102     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12103     * <p>
12104     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12105     *
12106     * @see #setClipToOutline(boolean)
12107     * @see #getClipToOutline()
12108     * @see #getOutlineProvider()
12109     */
12110    public void setOutlineProvider(ViewOutlineProvider provider) {
12111        mOutlineProvider = provider;
12112        invalidateOutline();
12113    }
12114
12115    /**
12116     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12117     * that defines the shape of the shadow it casts, and enables outline clipping.
12118     *
12119     * @see #setOutlineProvider(ViewOutlineProvider)
12120     */
12121    public ViewOutlineProvider getOutlineProvider() {
12122        return mOutlineProvider;
12123    }
12124
12125    /**
12126     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12127     *
12128     * @see #setOutlineProvider(ViewOutlineProvider)
12129     */
12130    public void invalidateOutline() {
12131        rebuildOutline();
12132
12133        notifySubtreeAccessibilityStateChangedIfNeeded();
12134        invalidateViewProperty(false, false);
12135    }
12136
12137    /**
12138     * Internal version of {@link #invalidateOutline()} which invalidates the
12139     * outline without invalidating the view itself. This is intended to be called from
12140     * within methods in the View class itself which are the result of the view being
12141     * invalidated already. For example, when we are drawing the background of a View,
12142     * we invalidate the outline in case it changed in the meantime, but we do not
12143     * need to invalidate the view because we're already drawing the background as part
12144     * of drawing the view in response to an earlier invalidation of the view.
12145     */
12146    private void rebuildOutline() {
12147        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12148        if (mAttachInfo == null) return;
12149
12150        if (mOutlineProvider == null) {
12151            // no provider, remove outline
12152            mRenderNode.setOutline(null);
12153        } else {
12154            final Outline outline = mAttachInfo.mTmpOutline;
12155            outline.setEmpty();
12156            outline.setAlpha(1.0f);
12157
12158            mOutlineProvider.getOutline(this, outline);
12159            mRenderNode.setOutline(outline);
12160        }
12161    }
12162
12163    /**
12164     * HierarchyViewer only
12165     *
12166     * @hide
12167     */
12168    @ViewDebug.ExportedProperty(category = "drawing")
12169    public boolean hasShadow() {
12170        return mRenderNode.hasShadow();
12171    }
12172
12173
12174    /** @hide */
12175    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12176        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12177        invalidateViewProperty(false, false);
12178    }
12179
12180    /**
12181     * Hit rectangle in parent's coordinates
12182     *
12183     * @param outRect The hit rectangle of the view.
12184     */
12185    public void getHitRect(Rect outRect) {
12186        if (hasIdentityMatrix() || mAttachInfo == null) {
12187            outRect.set(mLeft, mTop, mRight, mBottom);
12188        } else {
12189            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12190            tmpRect.set(0, 0, getWidth(), getHeight());
12191            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12192            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12193                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12194        }
12195    }
12196
12197    /**
12198     * Determines whether the given point, in local coordinates is inside the view.
12199     */
12200    /*package*/ final boolean pointInView(float localX, float localY) {
12201        return localX >= 0 && localX < (mRight - mLeft)
12202                && localY >= 0 && localY < (mBottom - mTop);
12203    }
12204
12205    /**
12206     * Utility method to determine whether the given point, in local coordinates,
12207     * is inside the view, where the area of the view is expanded by the slop factor.
12208     * This method is called while processing touch-move events to determine if the event
12209     * is still within the view.
12210     *
12211     * @hide
12212     */
12213    public boolean pointInView(float localX, float localY, float slop) {
12214        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12215                localY < ((mBottom - mTop) + slop);
12216    }
12217
12218    /**
12219     * When a view has focus and the user navigates away from it, the next view is searched for
12220     * starting from the rectangle filled in by this method.
12221     *
12222     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12223     * of the view.  However, if your view maintains some idea of internal selection,
12224     * such as a cursor, or a selected row or column, you should override this method and
12225     * fill in a more specific rectangle.
12226     *
12227     * @param r The rectangle to fill in, in this view's coordinates.
12228     */
12229    public void getFocusedRect(Rect r) {
12230        getDrawingRect(r);
12231    }
12232
12233    /**
12234     * If some part of this view is not clipped by any of its parents, then
12235     * return that area in r in global (root) coordinates. To convert r to local
12236     * coordinates (without taking possible View rotations into account), offset
12237     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12238     * If the view is completely clipped or translated out, return false.
12239     *
12240     * @param r If true is returned, r holds the global coordinates of the
12241     *        visible portion of this view.
12242     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12243     *        between this view and its root. globalOffet may be null.
12244     * @return true if r is non-empty (i.e. part of the view is visible at the
12245     *         root level.
12246     */
12247    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12248        int width = mRight - mLeft;
12249        int height = mBottom - mTop;
12250        if (width > 0 && height > 0) {
12251            r.set(0, 0, width, height);
12252            if (globalOffset != null) {
12253                globalOffset.set(-mScrollX, -mScrollY);
12254            }
12255            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12256        }
12257        return false;
12258    }
12259
12260    public final boolean getGlobalVisibleRect(Rect r) {
12261        return getGlobalVisibleRect(r, null);
12262    }
12263
12264    public final boolean getLocalVisibleRect(Rect r) {
12265        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12266        if (getGlobalVisibleRect(r, offset)) {
12267            r.offset(-offset.x, -offset.y); // make r local
12268            return true;
12269        }
12270        return false;
12271    }
12272
12273    /**
12274     * Offset this view's vertical location by the specified number of pixels.
12275     *
12276     * @param offset the number of pixels to offset the view by
12277     */
12278    public void offsetTopAndBottom(int offset) {
12279        if (offset != 0) {
12280            final boolean matrixIsIdentity = hasIdentityMatrix();
12281            if (matrixIsIdentity) {
12282                if (isHardwareAccelerated()) {
12283                    invalidateViewProperty(false, false);
12284                } else {
12285                    final ViewParent p = mParent;
12286                    if (p != null && mAttachInfo != null) {
12287                        final Rect r = mAttachInfo.mTmpInvalRect;
12288                        int minTop;
12289                        int maxBottom;
12290                        int yLoc;
12291                        if (offset < 0) {
12292                            minTop = mTop + offset;
12293                            maxBottom = mBottom;
12294                            yLoc = offset;
12295                        } else {
12296                            minTop = mTop;
12297                            maxBottom = mBottom + offset;
12298                            yLoc = 0;
12299                        }
12300                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12301                        p.invalidateChild(this, r);
12302                    }
12303                }
12304            } else {
12305                invalidateViewProperty(false, false);
12306            }
12307
12308            mTop += offset;
12309            mBottom += offset;
12310            mRenderNode.offsetTopAndBottom(offset);
12311            if (isHardwareAccelerated()) {
12312                invalidateViewProperty(false, false);
12313                invalidateParentIfNeededAndWasQuickRejected();
12314            } else {
12315                if (!matrixIsIdentity) {
12316                    invalidateViewProperty(false, true);
12317                }
12318                invalidateParentIfNeeded();
12319            }
12320            notifySubtreeAccessibilityStateChangedIfNeeded();
12321        }
12322    }
12323
12324    /**
12325     * Offset this view's horizontal location by the specified amount of pixels.
12326     *
12327     * @param offset the number of pixels to offset the view by
12328     */
12329    public void offsetLeftAndRight(int offset) {
12330        if (offset != 0) {
12331            final boolean matrixIsIdentity = hasIdentityMatrix();
12332            if (matrixIsIdentity) {
12333                if (isHardwareAccelerated()) {
12334                    invalidateViewProperty(false, false);
12335                } else {
12336                    final ViewParent p = mParent;
12337                    if (p != null && mAttachInfo != null) {
12338                        final Rect r = mAttachInfo.mTmpInvalRect;
12339                        int minLeft;
12340                        int maxRight;
12341                        if (offset < 0) {
12342                            minLeft = mLeft + offset;
12343                            maxRight = mRight;
12344                        } else {
12345                            minLeft = mLeft;
12346                            maxRight = mRight + offset;
12347                        }
12348                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12349                        p.invalidateChild(this, r);
12350                    }
12351                }
12352            } else {
12353                invalidateViewProperty(false, false);
12354            }
12355
12356            mLeft += offset;
12357            mRight += offset;
12358            mRenderNode.offsetLeftAndRight(offset);
12359            if (isHardwareAccelerated()) {
12360                invalidateViewProperty(false, false);
12361                invalidateParentIfNeededAndWasQuickRejected();
12362            } else {
12363                if (!matrixIsIdentity) {
12364                    invalidateViewProperty(false, true);
12365                }
12366                invalidateParentIfNeeded();
12367            }
12368            notifySubtreeAccessibilityStateChangedIfNeeded();
12369        }
12370    }
12371
12372    /**
12373     * Get the LayoutParams associated with this view. All views should have
12374     * layout parameters. These supply parameters to the <i>parent</i> of this
12375     * view specifying how it should be arranged. There are many subclasses of
12376     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12377     * of ViewGroup that are responsible for arranging their children.
12378     *
12379     * This method may return null if this View is not attached to a parent
12380     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12381     * was not invoked successfully. When a View is attached to a parent
12382     * ViewGroup, this method must not return null.
12383     *
12384     * @return The LayoutParams associated with this view, or null if no
12385     *         parameters have been set yet
12386     */
12387    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12388    public ViewGroup.LayoutParams getLayoutParams() {
12389        return mLayoutParams;
12390    }
12391
12392    /**
12393     * Set the layout parameters associated with this view. These supply
12394     * parameters to the <i>parent</i> of this view specifying how it should be
12395     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12396     * correspond to the different subclasses of ViewGroup that are responsible
12397     * for arranging their children.
12398     *
12399     * @param params The layout parameters for this view, cannot be null
12400     */
12401    public void setLayoutParams(ViewGroup.LayoutParams params) {
12402        if (params == null) {
12403            throw new NullPointerException("Layout parameters cannot be null");
12404        }
12405        mLayoutParams = params;
12406        resolveLayoutParams();
12407        if (mParent instanceof ViewGroup) {
12408            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12409        }
12410        requestLayout();
12411    }
12412
12413    /**
12414     * Resolve the layout parameters depending on the resolved layout direction
12415     *
12416     * @hide
12417     */
12418    public void resolveLayoutParams() {
12419        if (mLayoutParams != null) {
12420            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12421        }
12422    }
12423
12424    /**
12425     * Set the scrolled position of your view. This will cause a call to
12426     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12427     * invalidated.
12428     * @param x the x position to scroll to
12429     * @param y the y position to scroll to
12430     */
12431    public void scrollTo(int x, int y) {
12432        if (mScrollX != x || mScrollY != y) {
12433            int oldX = mScrollX;
12434            int oldY = mScrollY;
12435            mScrollX = x;
12436            mScrollY = y;
12437            invalidateParentCaches();
12438            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12439            if (!awakenScrollBars()) {
12440                postInvalidateOnAnimation();
12441            }
12442        }
12443    }
12444
12445    /**
12446     * Move the scrolled position of your view. This will cause a call to
12447     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12448     * invalidated.
12449     * @param x the amount of pixels to scroll by horizontally
12450     * @param y the amount of pixels to scroll by vertically
12451     */
12452    public void scrollBy(int x, int y) {
12453        scrollTo(mScrollX + x, mScrollY + y);
12454    }
12455
12456    /**
12457     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12458     * animation to fade the scrollbars out after a default delay. If a subclass
12459     * provides animated scrolling, the start delay should equal the duration
12460     * of the scrolling animation.</p>
12461     *
12462     * <p>The animation starts only if at least one of the scrollbars is
12463     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12464     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12465     * this method returns true, and false otherwise. If the animation is
12466     * started, this method calls {@link #invalidate()}; in that case the
12467     * caller should not call {@link #invalidate()}.</p>
12468     *
12469     * <p>This method should be invoked every time a subclass directly updates
12470     * the scroll parameters.</p>
12471     *
12472     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12473     * and {@link #scrollTo(int, int)}.</p>
12474     *
12475     * @return true if the animation is played, false otherwise
12476     *
12477     * @see #awakenScrollBars(int)
12478     * @see #scrollBy(int, int)
12479     * @see #scrollTo(int, int)
12480     * @see #isHorizontalScrollBarEnabled()
12481     * @see #isVerticalScrollBarEnabled()
12482     * @see #setHorizontalScrollBarEnabled(boolean)
12483     * @see #setVerticalScrollBarEnabled(boolean)
12484     */
12485    protected boolean awakenScrollBars() {
12486        return mScrollCache != null &&
12487                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12488    }
12489
12490    /**
12491     * Trigger the scrollbars to draw.
12492     * This method differs from awakenScrollBars() only in its default duration.
12493     * initialAwakenScrollBars() will show the scroll bars for longer than
12494     * usual to give the user more of a chance to notice them.
12495     *
12496     * @return true if the animation is played, false otherwise.
12497     */
12498    private boolean initialAwakenScrollBars() {
12499        return mScrollCache != null &&
12500                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12501    }
12502
12503    /**
12504     * <p>
12505     * Trigger the scrollbars to draw. When invoked this method starts an
12506     * animation to fade the scrollbars out after a fixed delay. If a subclass
12507     * provides animated scrolling, the start delay should equal the duration of
12508     * the scrolling animation.
12509     * </p>
12510     *
12511     * <p>
12512     * The animation starts only if at least one of the scrollbars is enabled,
12513     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12514     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12515     * this method returns true, and false otherwise. If the animation is
12516     * started, this method calls {@link #invalidate()}; in that case the caller
12517     * should not call {@link #invalidate()}.
12518     * </p>
12519     *
12520     * <p>
12521     * This method should be invoked every time a subclass directly updates the
12522     * scroll parameters.
12523     * </p>
12524     *
12525     * @param startDelay the delay, in milliseconds, after which the animation
12526     *        should start; when the delay is 0, the animation starts
12527     *        immediately
12528     * @return true if the animation is played, false otherwise
12529     *
12530     * @see #scrollBy(int, int)
12531     * @see #scrollTo(int, int)
12532     * @see #isHorizontalScrollBarEnabled()
12533     * @see #isVerticalScrollBarEnabled()
12534     * @see #setHorizontalScrollBarEnabled(boolean)
12535     * @see #setVerticalScrollBarEnabled(boolean)
12536     */
12537    protected boolean awakenScrollBars(int startDelay) {
12538        return awakenScrollBars(startDelay, true);
12539    }
12540
12541    /**
12542     * <p>
12543     * Trigger the scrollbars to draw. When invoked this method starts an
12544     * animation to fade the scrollbars out after a fixed delay. If a subclass
12545     * provides animated scrolling, the start delay should equal the duration of
12546     * the scrolling animation.
12547     * </p>
12548     *
12549     * <p>
12550     * The animation starts only if at least one of the scrollbars is enabled,
12551     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12552     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12553     * this method returns true, and false otherwise. If the animation is
12554     * started, this method calls {@link #invalidate()} if the invalidate parameter
12555     * is set to true; in that case the caller
12556     * should not call {@link #invalidate()}.
12557     * </p>
12558     *
12559     * <p>
12560     * This method should be invoked every time a subclass directly updates the
12561     * scroll parameters.
12562     * </p>
12563     *
12564     * @param startDelay the delay, in milliseconds, after which the animation
12565     *        should start; when the delay is 0, the animation starts
12566     *        immediately
12567     *
12568     * @param invalidate Whether this method should call invalidate
12569     *
12570     * @return true if the animation is played, false otherwise
12571     *
12572     * @see #scrollBy(int, int)
12573     * @see #scrollTo(int, int)
12574     * @see #isHorizontalScrollBarEnabled()
12575     * @see #isVerticalScrollBarEnabled()
12576     * @see #setHorizontalScrollBarEnabled(boolean)
12577     * @see #setVerticalScrollBarEnabled(boolean)
12578     */
12579    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12580        final ScrollabilityCache scrollCache = mScrollCache;
12581
12582        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12583            return false;
12584        }
12585
12586        if (scrollCache.scrollBar == null) {
12587            scrollCache.scrollBar = new ScrollBarDrawable();
12588            scrollCache.scrollBar.setCallback(this);
12589            scrollCache.scrollBar.setState(getDrawableState());
12590        }
12591
12592        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12593
12594            if (invalidate) {
12595                // Invalidate to show the scrollbars
12596                postInvalidateOnAnimation();
12597            }
12598
12599            if (scrollCache.state == ScrollabilityCache.OFF) {
12600                // FIXME: this is copied from WindowManagerService.
12601                // We should get this value from the system when it
12602                // is possible to do so.
12603                final int KEY_REPEAT_FIRST_DELAY = 750;
12604                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12605            }
12606
12607            // Tell mScrollCache when we should start fading. This may
12608            // extend the fade start time if one was already scheduled
12609            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12610            scrollCache.fadeStartTime = fadeStartTime;
12611            scrollCache.state = ScrollabilityCache.ON;
12612
12613            // Schedule our fader to run, unscheduling any old ones first
12614            if (mAttachInfo != null) {
12615                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12616                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12617            }
12618
12619            return true;
12620        }
12621
12622        return false;
12623    }
12624
12625    /**
12626     * Do not invalidate views which are not visible and which are not running an animation. They
12627     * will not get drawn and they should not set dirty flags as if they will be drawn
12628     */
12629    private boolean skipInvalidate() {
12630        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12631                (!(mParent instanceof ViewGroup) ||
12632                        !((ViewGroup) mParent).isViewTransitioning(this));
12633    }
12634
12635    /**
12636     * Mark the area defined by dirty as needing to be drawn. If the view is
12637     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12638     * point in the future.
12639     * <p>
12640     * This must be called from a UI thread. To call from a non-UI thread, call
12641     * {@link #postInvalidate()}.
12642     * <p>
12643     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12644     * {@code dirty}.
12645     *
12646     * @param dirty the rectangle representing the bounds of the dirty region
12647     */
12648    public void invalidate(Rect dirty) {
12649        final int scrollX = mScrollX;
12650        final int scrollY = mScrollY;
12651        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12652                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12653    }
12654
12655    /**
12656     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12657     * coordinates of the dirty rect are relative to the view. If the view is
12658     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12659     * point in the future.
12660     * <p>
12661     * This must be called from a UI thread. To call from a non-UI thread, call
12662     * {@link #postInvalidate()}.
12663     *
12664     * @param l the left position of the dirty region
12665     * @param t the top position of the dirty region
12666     * @param r the right position of the dirty region
12667     * @param b the bottom position of the dirty region
12668     */
12669    public void invalidate(int l, int t, int r, int b) {
12670        final int scrollX = mScrollX;
12671        final int scrollY = mScrollY;
12672        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12673    }
12674
12675    /**
12676     * Invalidate the whole view. If the view is visible,
12677     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12678     * the future.
12679     * <p>
12680     * This must be called from a UI thread. To call from a non-UI thread, call
12681     * {@link #postInvalidate()}.
12682     */
12683    public void invalidate() {
12684        invalidate(true);
12685    }
12686
12687    /**
12688     * This is where the invalidate() work actually happens. A full invalidate()
12689     * causes the drawing cache to be invalidated, but this function can be
12690     * called with invalidateCache set to false to skip that invalidation step
12691     * for cases that do not need it (for example, a component that remains at
12692     * the same dimensions with the same content).
12693     *
12694     * @param invalidateCache Whether the drawing cache for this view should be
12695     *            invalidated as well. This is usually true for a full
12696     *            invalidate, but may be set to false if the View's contents or
12697     *            dimensions have not changed.
12698     */
12699    void invalidate(boolean invalidateCache) {
12700        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12701    }
12702
12703    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12704            boolean fullInvalidate) {
12705        if (mGhostView != null) {
12706            mGhostView.invalidate(true);
12707            return;
12708        }
12709
12710        if (skipInvalidate()) {
12711            return;
12712        }
12713
12714        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12715                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12716                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12717                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12718            if (fullInvalidate) {
12719                mLastIsOpaque = isOpaque();
12720                mPrivateFlags &= ~PFLAG_DRAWN;
12721            }
12722
12723            mPrivateFlags |= PFLAG_DIRTY;
12724
12725            if (invalidateCache) {
12726                mPrivateFlags |= PFLAG_INVALIDATED;
12727                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12728            }
12729
12730            // Propagate the damage rectangle to the parent view.
12731            final AttachInfo ai = mAttachInfo;
12732            final ViewParent p = mParent;
12733            if (p != null && ai != null && l < r && t < b) {
12734                final Rect damage = ai.mTmpInvalRect;
12735                damage.set(l, t, r, b);
12736                p.invalidateChild(this, damage);
12737            }
12738
12739            // Damage the entire projection receiver, if necessary.
12740            if (mBackground != null && mBackground.isProjected()) {
12741                final View receiver = getProjectionReceiver();
12742                if (receiver != null) {
12743                    receiver.damageInParent();
12744                }
12745            }
12746
12747            // Damage the entire IsolatedZVolume receiving this view's shadow.
12748            if (isHardwareAccelerated() && getZ() != 0) {
12749                damageShadowReceiver();
12750            }
12751        }
12752    }
12753
12754    /**
12755     * @return this view's projection receiver, or {@code null} if none exists
12756     */
12757    private View getProjectionReceiver() {
12758        ViewParent p = getParent();
12759        while (p != null && p instanceof View) {
12760            final View v = (View) p;
12761            if (v.isProjectionReceiver()) {
12762                return v;
12763            }
12764            p = p.getParent();
12765        }
12766
12767        return null;
12768    }
12769
12770    /**
12771     * @return whether the view is a projection receiver
12772     */
12773    private boolean isProjectionReceiver() {
12774        return mBackground != null;
12775    }
12776
12777    /**
12778     * Damage area of the screen that can be covered by this View's shadow.
12779     *
12780     * This method will guarantee that any changes to shadows cast by a View
12781     * are damaged on the screen for future redraw.
12782     */
12783    private void damageShadowReceiver() {
12784        final AttachInfo ai = mAttachInfo;
12785        if (ai != null) {
12786            ViewParent p = getParent();
12787            if (p != null && p instanceof ViewGroup) {
12788                final ViewGroup vg = (ViewGroup) p;
12789                vg.damageInParent();
12790            }
12791        }
12792    }
12793
12794    /**
12795     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12796     * set any flags or handle all of the cases handled by the default invalidation methods.
12797     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12798     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12799     * walk up the hierarchy, transforming the dirty rect as necessary.
12800     *
12801     * The method also handles normal invalidation logic if display list properties are not
12802     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12803     * backup approach, to handle these cases used in the various property-setting methods.
12804     *
12805     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12806     * are not being used in this view
12807     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12808     * list properties are not being used in this view
12809     */
12810    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12811        if (!isHardwareAccelerated()
12812                || !mRenderNode.isValid()
12813                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12814            if (invalidateParent) {
12815                invalidateParentCaches();
12816            }
12817            if (forceRedraw) {
12818                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12819            }
12820            invalidate(false);
12821        } else {
12822            damageInParent();
12823        }
12824        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12825            damageShadowReceiver();
12826        }
12827    }
12828
12829    /**
12830     * Tells the parent view to damage this view's bounds.
12831     *
12832     * @hide
12833     */
12834    protected void damageInParent() {
12835        final AttachInfo ai = mAttachInfo;
12836        final ViewParent p = mParent;
12837        if (p != null && ai != null) {
12838            final Rect r = ai.mTmpInvalRect;
12839            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12840            if (mParent instanceof ViewGroup) {
12841                ((ViewGroup) mParent).damageChild(this, r);
12842            } else {
12843                mParent.invalidateChild(this, r);
12844            }
12845        }
12846    }
12847
12848    /**
12849     * Utility method to transform a given Rect by the current matrix of this view.
12850     */
12851    void transformRect(final Rect rect) {
12852        if (!getMatrix().isIdentity()) {
12853            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12854            boundingRect.set(rect);
12855            getMatrix().mapRect(boundingRect);
12856            rect.set((int) Math.floor(boundingRect.left),
12857                    (int) Math.floor(boundingRect.top),
12858                    (int) Math.ceil(boundingRect.right),
12859                    (int) Math.ceil(boundingRect.bottom));
12860        }
12861    }
12862
12863    /**
12864     * Used to indicate that the parent of this view should clear its caches. This functionality
12865     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12866     * which is necessary when various parent-managed properties of the view change, such as
12867     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12868     * clears the parent caches and does not causes an invalidate event.
12869     *
12870     * @hide
12871     */
12872    protected void invalidateParentCaches() {
12873        if (mParent instanceof View) {
12874            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12875        }
12876    }
12877
12878    /**
12879     * Used to indicate that the parent of this view should be invalidated. This functionality
12880     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12881     * which is necessary when various parent-managed properties of the view change, such as
12882     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12883     * an invalidation event to the parent.
12884     *
12885     * @hide
12886     */
12887    protected void invalidateParentIfNeeded() {
12888        if (isHardwareAccelerated() && mParent instanceof View) {
12889            ((View) mParent).invalidate(true);
12890        }
12891    }
12892
12893    /**
12894     * @hide
12895     */
12896    protected void invalidateParentIfNeededAndWasQuickRejected() {
12897        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12898            // View was rejected last time it was drawn by its parent; this may have changed
12899            invalidateParentIfNeeded();
12900        }
12901    }
12902
12903    /**
12904     * Indicates whether this View is opaque. An opaque View guarantees that it will
12905     * draw all the pixels overlapping its bounds using a fully opaque color.
12906     *
12907     * Subclasses of View should override this method whenever possible to indicate
12908     * whether an instance is opaque. Opaque Views are treated in a special way by
12909     * the View hierarchy, possibly allowing it to perform optimizations during
12910     * invalidate/draw passes.
12911     *
12912     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12913     */
12914    @ViewDebug.ExportedProperty(category = "drawing")
12915    public boolean isOpaque() {
12916        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12917                getFinalAlpha() >= 1.0f;
12918    }
12919
12920    /**
12921     * @hide
12922     */
12923    protected void computeOpaqueFlags() {
12924        // Opaque if:
12925        //   - Has a background
12926        //   - Background is opaque
12927        //   - Doesn't have scrollbars or scrollbars overlay
12928
12929        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12930            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12931        } else {
12932            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12933        }
12934
12935        final int flags = mViewFlags;
12936        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12937                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12938                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12939            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12940        } else {
12941            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12942        }
12943    }
12944
12945    /**
12946     * @hide
12947     */
12948    protected boolean hasOpaqueScrollbars() {
12949        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12950    }
12951
12952    /**
12953     * @return A handler associated with the thread running the View. This
12954     * handler can be used to pump events in the UI events queue.
12955     */
12956    public Handler getHandler() {
12957        final AttachInfo attachInfo = mAttachInfo;
12958        if (attachInfo != null) {
12959            return attachInfo.mHandler;
12960        }
12961        return null;
12962    }
12963
12964    /**
12965     * Gets the view root associated with the View.
12966     * @return The view root, or null if none.
12967     * @hide
12968     */
12969    public ViewRootImpl getViewRootImpl() {
12970        if (mAttachInfo != null) {
12971            return mAttachInfo.mViewRootImpl;
12972        }
12973        return null;
12974    }
12975
12976    /**
12977     * @hide
12978     */
12979    public HardwareRenderer getHardwareRenderer() {
12980        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12981    }
12982
12983    /**
12984     * <p>Causes the Runnable to be added to the message queue.
12985     * The runnable will be run on the user interface thread.</p>
12986     *
12987     * @param action The Runnable that will be executed.
12988     *
12989     * @return Returns true if the Runnable was successfully placed in to the
12990     *         message queue.  Returns false on failure, usually because the
12991     *         looper processing the message queue is exiting.
12992     *
12993     * @see #postDelayed
12994     * @see #removeCallbacks
12995     */
12996    public boolean post(Runnable action) {
12997        final AttachInfo attachInfo = mAttachInfo;
12998        if (attachInfo != null) {
12999            return attachInfo.mHandler.post(action);
13000        }
13001        // Assume that post will succeed later
13002        ViewRootImpl.getRunQueue().post(action);
13003        return true;
13004    }
13005
13006    /**
13007     * <p>Causes the Runnable to be added to the message queue, to be run
13008     * after the specified amount of time elapses.
13009     * The runnable will be run on the user interface thread.</p>
13010     *
13011     * @param action The Runnable that will be executed.
13012     * @param delayMillis The delay (in milliseconds) until the Runnable
13013     *        will be executed.
13014     *
13015     * @return true if the Runnable was successfully placed in to the
13016     *         message queue.  Returns false on failure, usually because the
13017     *         looper processing the message queue is exiting.  Note that a
13018     *         result of true does not mean the Runnable will be processed --
13019     *         if the looper is quit before the delivery time of the message
13020     *         occurs then the message will be dropped.
13021     *
13022     * @see #post
13023     * @see #removeCallbacks
13024     */
13025    public boolean postDelayed(Runnable action, long delayMillis) {
13026        final AttachInfo attachInfo = mAttachInfo;
13027        if (attachInfo != null) {
13028            return attachInfo.mHandler.postDelayed(action, delayMillis);
13029        }
13030        // Assume that post will succeed later
13031        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13032        return true;
13033    }
13034
13035    /**
13036     * <p>Causes the Runnable to execute on the next animation time step.
13037     * The runnable will be run on the user interface thread.</p>
13038     *
13039     * @param action The Runnable that will be executed.
13040     *
13041     * @see #postOnAnimationDelayed
13042     * @see #removeCallbacks
13043     */
13044    public void postOnAnimation(Runnable action) {
13045        final AttachInfo attachInfo = mAttachInfo;
13046        if (attachInfo != null) {
13047            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13048                    Choreographer.CALLBACK_ANIMATION, action, null);
13049        } else {
13050            // Assume that post will succeed later
13051            ViewRootImpl.getRunQueue().post(action);
13052        }
13053    }
13054
13055    /**
13056     * <p>Causes the Runnable to execute on the next animation time step,
13057     * after the specified amount of time elapses.
13058     * The runnable will be run on the user interface thread.</p>
13059     *
13060     * @param action The Runnable that will be executed.
13061     * @param delayMillis The delay (in milliseconds) until the Runnable
13062     *        will be executed.
13063     *
13064     * @see #postOnAnimation
13065     * @see #removeCallbacks
13066     */
13067    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13068        final AttachInfo attachInfo = mAttachInfo;
13069        if (attachInfo != null) {
13070            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13071                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13072        } else {
13073            // Assume that post will succeed later
13074            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13075        }
13076    }
13077
13078    /**
13079     * <p>Removes the specified Runnable from the message queue.</p>
13080     *
13081     * @param action The Runnable to remove from the message handling queue
13082     *
13083     * @return true if this view could ask the Handler to remove the Runnable,
13084     *         false otherwise. When the returned value is true, the Runnable
13085     *         may or may not have been actually removed from the message queue
13086     *         (for instance, if the Runnable was not in the queue already.)
13087     *
13088     * @see #post
13089     * @see #postDelayed
13090     * @see #postOnAnimation
13091     * @see #postOnAnimationDelayed
13092     */
13093    public boolean removeCallbacks(Runnable action) {
13094        if (action != null) {
13095            final AttachInfo attachInfo = mAttachInfo;
13096            if (attachInfo != null) {
13097                attachInfo.mHandler.removeCallbacks(action);
13098                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13099                        Choreographer.CALLBACK_ANIMATION, action, null);
13100            }
13101            // Assume that post will succeed later
13102            ViewRootImpl.getRunQueue().removeCallbacks(action);
13103        }
13104        return true;
13105    }
13106
13107    /**
13108     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13109     * Use this to invalidate the View from a non-UI thread.</p>
13110     *
13111     * <p>This method can be invoked from outside of the UI thread
13112     * only when this View is attached to a window.</p>
13113     *
13114     * @see #invalidate()
13115     * @see #postInvalidateDelayed(long)
13116     */
13117    public void postInvalidate() {
13118        postInvalidateDelayed(0);
13119    }
13120
13121    /**
13122     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13123     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13124     *
13125     * <p>This method can be invoked from outside of the UI thread
13126     * only when this View is attached to a window.</p>
13127     *
13128     * @param left The left coordinate of the rectangle to invalidate.
13129     * @param top The top coordinate of the rectangle to invalidate.
13130     * @param right The right coordinate of the rectangle to invalidate.
13131     * @param bottom The bottom coordinate of the rectangle to invalidate.
13132     *
13133     * @see #invalidate(int, int, int, int)
13134     * @see #invalidate(Rect)
13135     * @see #postInvalidateDelayed(long, int, int, int, int)
13136     */
13137    public void postInvalidate(int left, int top, int right, int bottom) {
13138        postInvalidateDelayed(0, left, top, right, bottom);
13139    }
13140
13141    /**
13142     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13143     * loop. Waits for the specified amount of time.</p>
13144     *
13145     * <p>This method can be invoked from outside of the UI thread
13146     * only when this View is attached to a window.</p>
13147     *
13148     * @param delayMilliseconds the duration in milliseconds to delay the
13149     *         invalidation by
13150     *
13151     * @see #invalidate()
13152     * @see #postInvalidate()
13153     */
13154    public void postInvalidateDelayed(long delayMilliseconds) {
13155        // We try only with the AttachInfo because there's no point in invalidating
13156        // if we are not attached to our window
13157        final AttachInfo attachInfo = mAttachInfo;
13158        if (attachInfo != null) {
13159            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13160        }
13161    }
13162
13163    /**
13164     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13165     * through the event loop. Waits for the specified amount of time.</p>
13166     *
13167     * <p>This method can be invoked from outside of the UI thread
13168     * only when this View is attached to a window.</p>
13169     *
13170     * @param delayMilliseconds the duration in milliseconds to delay the
13171     *         invalidation by
13172     * @param left The left coordinate of the rectangle to invalidate.
13173     * @param top The top coordinate of the rectangle to invalidate.
13174     * @param right The right coordinate of the rectangle to invalidate.
13175     * @param bottom The bottom coordinate of the rectangle to invalidate.
13176     *
13177     * @see #invalidate(int, int, int, int)
13178     * @see #invalidate(Rect)
13179     * @see #postInvalidate(int, int, int, int)
13180     */
13181    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13182            int right, int bottom) {
13183
13184        // We try only with the AttachInfo because there's no point in invalidating
13185        // if we are not attached to our window
13186        final AttachInfo attachInfo = mAttachInfo;
13187        if (attachInfo != null) {
13188            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13189            info.target = this;
13190            info.left = left;
13191            info.top = top;
13192            info.right = right;
13193            info.bottom = bottom;
13194
13195            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13196        }
13197    }
13198
13199    /**
13200     * <p>Cause an invalidate to happen on the next animation time step, typically the
13201     * next display frame.</p>
13202     *
13203     * <p>This method can be invoked from outside of the UI thread
13204     * only when this View is attached to a window.</p>
13205     *
13206     * @see #invalidate()
13207     */
13208    public void postInvalidateOnAnimation() {
13209        // We try only with the AttachInfo because there's no point in invalidating
13210        // if we are not attached to our window
13211        final AttachInfo attachInfo = mAttachInfo;
13212        if (attachInfo != null) {
13213            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13214        }
13215    }
13216
13217    /**
13218     * <p>Cause an invalidate of the specified area to happen on the next animation
13219     * time step, typically the next display frame.</p>
13220     *
13221     * <p>This method can be invoked from outside of the UI thread
13222     * only when this View is attached to a window.</p>
13223     *
13224     * @param left The left coordinate of the rectangle to invalidate.
13225     * @param top The top coordinate of the rectangle to invalidate.
13226     * @param right The right coordinate of the rectangle to invalidate.
13227     * @param bottom The bottom coordinate of the rectangle to invalidate.
13228     *
13229     * @see #invalidate(int, int, int, int)
13230     * @see #invalidate(Rect)
13231     */
13232    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13233        // We try only with the AttachInfo because there's no point in invalidating
13234        // if we are not attached to our window
13235        final AttachInfo attachInfo = mAttachInfo;
13236        if (attachInfo != null) {
13237            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13238            info.target = this;
13239            info.left = left;
13240            info.top = top;
13241            info.right = right;
13242            info.bottom = bottom;
13243
13244            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13245        }
13246    }
13247
13248    /**
13249     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13250     * This event is sent at most once every
13251     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13252     */
13253    private void postSendViewScrolledAccessibilityEventCallback() {
13254        if (mSendViewScrolledAccessibilityEvent == null) {
13255            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13256        }
13257        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13258            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13259            postDelayed(mSendViewScrolledAccessibilityEvent,
13260                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13261        }
13262    }
13263
13264    /**
13265     * Called by a parent to request that a child update its values for mScrollX
13266     * and mScrollY if necessary. This will typically be done if the child is
13267     * animating a scroll using a {@link android.widget.Scroller Scroller}
13268     * object.
13269     */
13270    public void computeScroll() {
13271    }
13272
13273    /**
13274     * <p>Indicate whether the horizontal edges are faded when the view is
13275     * scrolled horizontally.</p>
13276     *
13277     * @return true if the horizontal edges should are faded on scroll, false
13278     *         otherwise
13279     *
13280     * @see #setHorizontalFadingEdgeEnabled(boolean)
13281     *
13282     * @attr ref android.R.styleable#View_requiresFadingEdge
13283     */
13284    public boolean isHorizontalFadingEdgeEnabled() {
13285        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13286    }
13287
13288    /**
13289     * <p>Define whether the horizontal edges should be faded when this view
13290     * is scrolled horizontally.</p>
13291     *
13292     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13293     *                                    be faded when the view is scrolled
13294     *                                    horizontally
13295     *
13296     * @see #isHorizontalFadingEdgeEnabled()
13297     *
13298     * @attr ref android.R.styleable#View_requiresFadingEdge
13299     */
13300    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13301        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13302            if (horizontalFadingEdgeEnabled) {
13303                initScrollCache();
13304            }
13305
13306            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13307        }
13308    }
13309
13310    /**
13311     * <p>Indicate whether the vertical edges are faded when the view is
13312     * scrolled horizontally.</p>
13313     *
13314     * @return true if the vertical edges should are faded on scroll, false
13315     *         otherwise
13316     *
13317     * @see #setVerticalFadingEdgeEnabled(boolean)
13318     *
13319     * @attr ref android.R.styleable#View_requiresFadingEdge
13320     */
13321    public boolean isVerticalFadingEdgeEnabled() {
13322        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13323    }
13324
13325    /**
13326     * <p>Define whether the vertical edges should be faded when this view
13327     * is scrolled vertically.</p>
13328     *
13329     * @param verticalFadingEdgeEnabled true if the vertical edges should
13330     *                                  be faded when the view is scrolled
13331     *                                  vertically
13332     *
13333     * @see #isVerticalFadingEdgeEnabled()
13334     *
13335     * @attr ref android.R.styleable#View_requiresFadingEdge
13336     */
13337    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13338        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13339            if (verticalFadingEdgeEnabled) {
13340                initScrollCache();
13341            }
13342
13343            mViewFlags ^= FADING_EDGE_VERTICAL;
13344        }
13345    }
13346
13347    /**
13348     * Returns the strength, or intensity, of the top faded edge. The strength is
13349     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13350     * returns 0.0 or 1.0 but no value in between.
13351     *
13352     * Subclasses should override this method to provide a smoother fade transition
13353     * when scrolling occurs.
13354     *
13355     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13356     */
13357    protected float getTopFadingEdgeStrength() {
13358        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13359    }
13360
13361    /**
13362     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13363     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13364     * returns 0.0 or 1.0 but no value in between.
13365     *
13366     * Subclasses should override this method to provide a smoother fade transition
13367     * when scrolling occurs.
13368     *
13369     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13370     */
13371    protected float getBottomFadingEdgeStrength() {
13372        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13373                computeVerticalScrollRange() ? 1.0f : 0.0f;
13374    }
13375
13376    /**
13377     * Returns the strength, or intensity, of the left faded edge. The strength is
13378     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13379     * returns 0.0 or 1.0 but no value in between.
13380     *
13381     * Subclasses should override this method to provide a smoother fade transition
13382     * when scrolling occurs.
13383     *
13384     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13385     */
13386    protected float getLeftFadingEdgeStrength() {
13387        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13388    }
13389
13390    /**
13391     * Returns the strength, or intensity, of the right faded edge. The strength is
13392     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13393     * returns 0.0 or 1.0 but no value in between.
13394     *
13395     * Subclasses should override this method to provide a smoother fade transition
13396     * when scrolling occurs.
13397     *
13398     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13399     */
13400    protected float getRightFadingEdgeStrength() {
13401        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13402                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13403    }
13404
13405    /**
13406     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13407     * scrollbar is not drawn by default.</p>
13408     *
13409     * @return true if the horizontal scrollbar should be painted, false
13410     *         otherwise
13411     *
13412     * @see #setHorizontalScrollBarEnabled(boolean)
13413     */
13414    public boolean isHorizontalScrollBarEnabled() {
13415        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13416    }
13417
13418    /**
13419     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13420     * scrollbar is not drawn by default.</p>
13421     *
13422     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13423     *                                   be painted
13424     *
13425     * @see #isHorizontalScrollBarEnabled()
13426     */
13427    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13428        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13429            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13430            computeOpaqueFlags();
13431            resolvePadding();
13432        }
13433    }
13434
13435    /**
13436     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13437     * scrollbar is not drawn by default.</p>
13438     *
13439     * @return true if the vertical scrollbar should be painted, false
13440     *         otherwise
13441     *
13442     * @see #setVerticalScrollBarEnabled(boolean)
13443     */
13444    public boolean isVerticalScrollBarEnabled() {
13445        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13446    }
13447
13448    /**
13449     * <p>Define whether the vertical scrollbar should be drawn or not. The
13450     * scrollbar is not drawn by default.</p>
13451     *
13452     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13453     *                                 be painted
13454     *
13455     * @see #isVerticalScrollBarEnabled()
13456     */
13457    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13458        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13459            mViewFlags ^= SCROLLBARS_VERTICAL;
13460            computeOpaqueFlags();
13461            resolvePadding();
13462        }
13463    }
13464
13465    /**
13466     * @hide
13467     */
13468    protected void recomputePadding() {
13469        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13470    }
13471
13472    /**
13473     * Define whether scrollbars will fade when the view is not scrolling.
13474     *
13475     * @param fadeScrollbars whether to enable fading
13476     *
13477     * @attr ref android.R.styleable#View_fadeScrollbars
13478     */
13479    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13480        initScrollCache();
13481        final ScrollabilityCache scrollabilityCache = mScrollCache;
13482        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13483        if (fadeScrollbars) {
13484            scrollabilityCache.state = ScrollabilityCache.OFF;
13485        } else {
13486            scrollabilityCache.state = ScrollabilityCache.ON;
13487        }
13488    }
13489
13490    /**
13491     *
13492     * Returns true if scrollbars will fade when this view is not scrolling
13493     *
13494     * @return true if scrollbar fading is enabled
13495     *
13496     * @attr ref android.R.styleable#View_fadeScrollbars
13497     */
13498    public boolean isScrollbarFadingEnabled() {
13499        return mScrollCache != null && mScrollCache.fadeScrollBars;
13500    }
13501
13502    /**
13503     *
13504     * Returns the delay before scrollbars fade.
13505     *
13506     * @return the delay before scrollbars fade
13507     *
13508     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13509     */
13510    public int getScrollBarDefaultDelayBeforeFade() {
13511        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13512                mScrollCache.scrollBarDefaultDelayBeforeFade;
13513    }
13514
13515    /**
13516     * Define the delay before scrollbars fade.
13517     *
13518     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13519     *
13520     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13521     */
13522    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13523        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13524    }
13525
13526    /**
13527     *
13528     * Returns the scrollbar fade duration.
13529     *
13530     * @return the scrollbar fade duration
13531     *
13532     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13533     */
13534    public int getScrollBarFadeDuration() {
13535        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13536                mScrollCache.scrollBarFadeDuration;
13537    }
13538
13539    /**
13540     * Define the scrollbar fade duration.
13541     *
13542     * @param scrollBarFadeDuration - the scrollbar fade duration
13543     *
13544     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13545     */
13546    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13547        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13548    }
13549
13550    /**
13551     *
13552     * Returns the scrollbar size.
13553     *
13554     * @return the scrollbar size
13555     *
13556     * @attr ref android.R.styleable#View_scrollbarSize
13557     */
13558    public int getScrollBarSize() {
13559        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13560                mScrollCache.scrollBarSize;
13561    }
13562
13563    /**
13564     * Define the scrollbar size.
13565     *
13566     * @param scrollBarSize - the scrollbar size
13567     *
13568     * @attr ref android.R.styleable#View_scrollbarSize
13569     */
13570    public void setScrollBarSize(int scrollBarSize) {
13571        getScrollCache().scrollBarSize = scrollBarSize;
13572    }
13573
13574    /**
13575     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13576     * inset. When inset, they add to the padding of the view. And the scrollbars
13577     * can be drawn inside the padding area or on the edge of the view. For example,
13578     * if a view has a background drawable and you want to draw the scrollbars
13579     * inside the padding specified by the drawable, you can use
13580     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13581     * appear at the edge of the view, ignoring the padding, then you can use
13582     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13583     * @param style the style of the scrollbars. Should be one of
13584     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13585     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13586     * @see #SCROLLBARS_INSIDE_OVERLAY
13587     * @see #SCROLLBARS_INSIDE_INSET
13588     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13589     * @see #SCROLLBARS_OUTSIDE_INSET
13590     *
13591     * @attr ref android.R.styleable#View_scrollbarStyle
13592     */
13593    public void setScrollBarStyle(@ScrollBarStyle int style) {
13594        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13595            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13596            computeOpaqueFlags();
13597            resolvePadding();
13598        }
13599    }
13600
13601    /**
13602     * <p>Returns the current scrollbar style.</p>
13603     * @return the current scrollbar style
13604     * @see #SCROLLBARS_INSIDE_OVERLAY
13605     * @see #SCROLLBARS_INSIDE_INSET
13606     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13607     * @see #SCROLLBARS_OUTSIDE_INSET
13608     *
13609     * @attr ref android.R.styleable#View_scrollbarStyle
13610     */
13611    @ViewDebug.ExportedProperty(mapping = {
13612            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13613            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13614            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13615            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13616    })
13617    @ScrollBarStyle
13618    public int getScrollBarStyle() {
13619        return mViewFlags & SCROLLBARS_STYLE_MASK;
13620    }
13621
13622    /**
13623     * <p>Compute the horizontal range that the horizontal scrollbar
13624     * represents.</p>
13625     *
13626     * <p>The range is expressed in arbitrary units that must be the same as the
13627     * units used by {@link #computeHorizontalScrollExtent()} and
13628     * {@link #computeHorizontalScrollOffset()}.</p>
13629     *
13630     * <p>The default range is the drawing width of this view.</p>
13631     *
13632     * @return the total horizontal range represented by the horizontal
13633     *         scrollbar
13634     *
13635     * @see #computeHorizontalScrollExtent()
13636     * @see #computeHorizontalScrollOffset()
13637     * @see android.widget.ScrollBarDrawable
13638     */
13639    protected int computeHorizontalScrollRange() {
13640        return getWidth();
13641    }
13642
13643    /**
13644     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13645     * within the horizontal range. This value is used to compute the position
13646     * of the thumb within the scrollbar's track.</p>
13647     *
13648     * <p>The range is expressed in arbitrary units that must be the same as the
13649     * units used by {@link #computeHorizontalScrollRange()} and
13650     * {@link #computeHorizontalScrollExtent()}.</p>
13651     *
13652     * <p>The default offset is the scroll offset of this view.</p>
13653     *
13654     * @return the horizontal offset of the scrollbar's thumb
13655     *
13656     * @see #computeHorizontalScrollRange()
13657     * @see #computeHorizontalScrollExtent()
13658     * @see android.widget.ScrollBarDrawable
13659     */
13660    protected int computeHorizontalScrollOffset() {
13661        return mScrollX;
13662    }
13663
13664    /**
13665     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13666     * within the horizontal range. This value is used to compute the length
13667     * of the thumb within the scrollbar's track.</p>
13668     *
13669     * <p>The range is expressed in arbitrary units that must be the same as the
13670     * units used by {@link #computeHorizontalScrollRange()} and
13671     * {@link #computeHorizontalScrollOffset()}.</p>
13672     *
13673     * <p>The default extent is the drawing width of this view.</p>
13674     *
13675     * @return the horizontal extent of the scrollbar's thumb
13676     *
13677     * @see #computeHorizontalScrollRange()
13678     * @see #computeHorizontalScrollOffset()
13679     * @see android.widget.ScrollBarDrawable
13680     */
13681    protected int computeHorizontalScrollExtent() {
13682        return getWidth();
13683    }
13684
13685    /**
13686     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13687     *
13688     * <p>The range is expressed in arbitrary units that must be the same as the
13689     * units used by {@link #computeVerticalScrollExtent()} and
13690     * {@link #computeVerticalScrollOffset()}.</p>
13691     *
13692     * @return the total vertical range represented by the vertical scrollbar
13693     *
13694     * <p>The default range is the drawing height of this view.</p>
13695     *
13696     * @see #computeVerticalScrollExtent()
13697     * @see #computeVerticalScrollOffset()
13698     * @see android.widget.ScrollBarDrawable
13699     */
13700    protected int computeVerticalScrollRange() {
13701        return getHeight();
13702    }
13703
13704    /**
13705     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13706     * within the horizontal range. This value is used to compute the position
13707     * of the thumb within the scrollbar's track.</p>
13708     *
13709     * <p>The range is expressed in arbitrary units that must be the same as the
13710     * units used by {@link #computeVerticalScrollRange()} and
13711     * {@link #computeVerticalScrollExtent()}.</p>
13712     *
13713     * <p>The default offset is the scroll offset of this view.</p>
13714     *
13715     * @return the vertical offset of the scrollbar's thumb
13716     *
13717     * @see #computeVerticalScrollRange()
13718     * @see #computeVerticalScrollExtent()
13719     * @see android.widget.ScrollBarDrawable
13720     */
13721    protected int computeVerticalScrollOffset() {
13722        return mScrollY;
13723    }
13724
13725    /**
13726     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13727     * within the vertical range. This value is used to compute the length
13728     * of the thumb within the scrollbar's track.</p>
13729     *
13730     * <p>The range is expressed in arbitrary units that must be the same as the
13731     * units used by {@link #computeVerticalScrollRange()} and
13732     * {@link #computeVerticalScrollOffset()}.</p>
13733     *
13734     * <p>The default extent is the drawing height of this view.</p>
13735     *
13736     * @return the vertical extent of the scrollbar's thumb
13737     *
13738     * @see #computeVerticalScrollRange()
13739     * @see #computeVerticalScrollOffset()
13740     * @see android.widget.ScrollBarDrawable
13741     */
13742    protected int computeVerticalScrollExtent() {
13743        return getHeight();
13744    }
13745
13746    /**
13747     * Check if this view can be scrolled horizontally in a certain direction.
13748     *
13749     * @param direction Negative to check scrolling left, positive to check scrolling right.
13750     * @return true if this view can be scrolled in the specified direction, false otherwise.
13751     */
13752    public boolean canScrollHorizontally(int direction) {
13753        final int offset = computeHorizontalScrollOffset();
13754        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13755        if (range == 0) return false;
13756        if (direction < 0) {
13757            return offset > 0;
13758        } else {
13759            return offset < range - 1;
13760        }
13761    }
13762
13763    /**
13764     * Check if this view can be scrolled vertically in a certain direction.
13765     *
13766     * @param direction Negative to check scrolling up, positive to check scrolling down.
13767     * @return true if this view can be scrolled in the specified direction, false otherwise.
13768     */
13769    public boolean canScrollVertically(int direction) {
13770        final int offset = computeVerticalScrollOffset();
13771        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13772        if (range == 0) return false;
13773        if (direction < 0) {
13774            return offset > 0;
13775        } else {
13776            return offset < range - 1;
13777        }
13778    }
13779
13780    void getScrollIndicatorBounds(@NonNull Rect out) {
13781        out.left = mScrollX;
13782        out.right = mScrollX + mRight - mLeft;
13783        out.top = mScrollY;
13784        out.bottom = mScrollY + mBottom - mTop;
13785    }
13786
13787    private void onDrawScrollIndicators(Canvas c) {
13788        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13789            // No scroll indicators enabled.
13790            return;
13791        }
13792
13793        final Drawable dr = mScrollIndicatorDrawable;
13794        if (dr == null) {
13795            // Scroll indicators aren't supported here.
13796            return;
13797        }
13798
13799        final int h = dr.getIntrinsicHeight();
13800        final int w = dr.getIntrinsicWidth();
13801        final Rect rect = mAttachInfo.mTmpInvalRect;
13802        getScrollIndicatorBounds(rect);
13803
13804        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13805            final boolean canScrollUp = canScrollVertically(-1);
13806            if (canScrollUp) {
13807                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13808                dr.draw(c);
13809            }
13810        }
13811
13812        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13813            final boolean canScrollDown = canScrollVertically(1);
13814            if (canScrollDown) {
13815                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13816                dr.draw(c);
13817            }
13818        }
13819
13820        final int leftRtl;
13821        final int rightRtl;
13822        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13823            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13824            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13825        } else {
13826            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13827            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13828        }
13829
13830        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13831        if ((mPrivateFlags3 & leftMask) != 0) {
13832            final boolean canScrollLeft = canScrollHorizontally(-1);
13833            if (canScrollLeft) {
13834                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13835                dr.draw(c);
13836            }
13837        }
13838
13839        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13840        if ((mPrivateFlags3 & rightMask) != 0) {
13841            final boolean canScrollRight = canScrollHorizontally(1);
13842            if (canScrollRight) {
13843                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13844                dr.draw(c);
13845            }
13846        }
13847    }
13848
13849    /**
13850     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13851     * scrollbars are painted only if they have been awakened first.</p>
13852     *
13853     * @param canvas the canvas on which to draw the scrollbars
13854     *
13855     * @see #awakenScrollBars(int)
13856     */
13857    protected final void onDrawScrollBars(Canvas canvas) {
13858        // scrollbars are drawn only when the animation is running
13859        final ScrollabilityCache cache = mScrollCache;
13860        if (cache != null) {
13861
13862            int state = cache.state;
13863
13864            if (state == ScrollabilityCache.OFF) {
13865                return;
13866            }
13867
13868            boolean invalidate = false;
13869
13870            if (state == ScrollabilityCache.FADING) {
13871                // We're fading -- get our fade interpolation
13872                if (cache.interpolatorValues == null) {
13873                    cache.interpolatorValues = new float[1];
13874                }
13875
13876                float[] values = cache.interpolatorValues;
13877
13878                // Stops the animation if we're done
13879                if (cache.scrollBarInterpolator.timeToValues(values) ==
13880                        Interpolator.Result.FREEZE_END) {
13881                    cache.state = ScrollabilityCache.OFF;
13882                } else {
13883                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13884                }
13885
13886                // This will make the scroll bars inval themselves after
13887                // drawing. We only want this when we're fading so that
13888                // we prevent excessive redraws
13889                invalidate = true;
13890            } else {
13891                // We're just on -- but we may have been fading before so
13892                // reset alpha
13893                cache.scrollBar.mutate().setAlpha(255);
13894            }
13895
13896
13897            final int viewFlags = mViewFlags;
13898
13899            final boolean drawHorizontalScrollBar =
13900                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13901            final boolean drawVerticalScrollBar =
13902                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13903                && !isVerticalScrollBarHidden();
13904
13905            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13906                final int width = mRight - mLeft;
13907                final int height = mBottom - mTop;
13908
13909                final ScrollBarDrawable scrollBar = cache.scrollBar;
13910
13911                final int scrollX = mScrollX;
13912                final int scrollY = mScrollY;
13913                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13914
13915                int left;
13916                int top;
13917                int right;
13918                int bottom;
13919
13920                if (drawHorizontalScrollBar) {
13921                    int size = scrollBar.getSize(false);
13922                    if (size <= 0) {
13923                        size = cache.scrollBarSize;
13924                    }
13925
13926                    scrollBar.setParameters(computeHorizontalScrollRange(),
13927                                            computeHorizontalScrollOffset(),
13928                                            computeHorizontalScrollExtent(), false);
13929                    final int verticalScrollBarGap = drawVerticalScrollBar ?
13930                            getVerticalScrollbarWidth() : 0;
13931                    top = scrollY + height - size - (mUserPaddingBottom & inside);
13932                    left = scrollX + (mPaddingLeft & inside);
13933                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13934                    bottom = top + size;
13935                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13936                    if (invalidate) {
13937                        invalidate(left, top, right, bottom);
13938                    }
13939                }
13940
13941                if (drawVerticalScrollBar) {
13942                    int size = scrollBar.getSize(true);
13943                    if (size <= 0) {
13944                        size = cache.scrollBarSize;
13945                    }
13946
13947                    scrollBar.setParameters(computeVerticalScrollRange(),
13948                                            computeVerticalScrollOffset(),
13949                                            computeVerticalScrollExtent(), true);
13950                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
13951                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13952                        verticalScrollbarPosition = isLayoutRtl() ?
13953                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13954                    }
13955                    switch (verticalScrollbarPosition) {
13956                        default:
13957                        case SCROLLBAR_POSITION_RIGHT:
13958                            left = scrollX + width - size - (mUserPaddingRight & inside);
13959                            break;
13960                        case SCROLLBAR_POSITION_LEFT:
13961                            left = scrollX + (mUserPaddingLeft & inside);
13962                            break;
13963                    }
13964                    top = scrollY + (mPaddingTop & inside);
13965                    right = left + size;
13966                    bottom = scrollY + height - (mUserPaddingBottom & inside);
13967                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13968                    if (invalidate) {
13969                        invalidate(left, top, right, bottom);
13970                    }
13971                }
13972            }
13973        }
13974    }
13975
13976    /**
13977     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13978     * FastScroller is visible.
13979     * @return whether to temporarily hide the vertical scrollbar
13980     * @hide
13981     */
13982    protected boolean isVerticalScrollBarHidden() {
13983        return false;
13984    }
13985
13986    /**
13987     * <p>Draw the horizontal scrollbar if
13988     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13989     *
13990     * @param canvas the canvas on which to draw the scrollbar
13991     * @param scrollBar the scrollbar's drawable
13992     *
13993     * @see #isHorizontalScrollBarEnabled()
13994     * @see #computeHorizontalScrollRange()
13995     * @see #computeHorizontalScrollExtent()
13996     * @see #computeHorizontalScrollOffset()
13997     * @see android.widget.ScrollBarDrawable
13998     * @hide
13999     */
14000    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14001            int l, int t, int r, int b) {
14002        scrollBar.setBounds(l, t, r, b);
14003        scrollBar.draw(canvas);
14004    }
14005
14006    /**
14007     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14008     * returns true.</p>
14009     *
14010     * @param canvas the canvas on which to draw the scrollbar
14011     * @param scrollBar the scrollbar's drawable
14012     *
14013     * @see #isVerticalScrollBarEnabled()
14014     * @see #computeVerticalScrollRange()
14015     * @see #computeVerticalScrollExtent()
14016     * @see #computeVerticalScrollOffset()
14017     * @see android.widget.ScrollBarDrawable
14018     * @hide
14019     */
14020    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14021            int l, int t, int r, int b) {
14022        scrollBar.setBounds(l, t, r, b);
14023        scrollBar.draw(canvas);
14024    }
14025
14026    /**
14027     * Implement this to do your drawing.
14028     *
14029     * @param canvas the canvas on which the background will be drawn
14030     */
14031    protected void onDraw(Canvas canvas) {
14032    }
14033
14034    /*
14035     * Caller is responsible for calling requestLayout if necessary.
14036     * (This allows addViewInLayout to not request a new layout.)
14037     */
14038    void assignParent(ViewParent parent) {
14039        if (mParent == null) {
14040            mParent = parent;
14041        } else if (parent == null) {
14042            mParent = null;
14043        } else {
14044            throw new RuntimeException("view " + this + " being added, but"
14045                    + " it already has a parent");
14046        }
14047    }
14048
14049    /**
14050     * This is called when the view is attached to a window.  At this point it
14051     * has a Surface and will start drawing.  Note that this function is
14052     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14053     * however it may be called any time before the first onDraw -- including
14054     * before or after {@link #onMeasure(int, int)}.
14055     *
14056     * @see #onDetachedFromWindow()
14057     */
14058    @CallSuper
14059    protected void onAttachedToWindow() {
14060        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14061            mParent.requestTransparentRegion(this);
14062        }
14063
14064        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14065
14066        jumpDrawablesToCurrentState();
14067
14068        resetSubtreeAccessibilityStateChanged();
14069
14070        // rebuild, since Outline not maintained while View is detached
14071        rebuildOutline();
14072
14073        if (isFocused()) {
14074            InputMethodManager imm = InputMethodManager.peekInstance();
14075            if (imm != null) {
14076                imm.focusIn(this);
14077            }
14078        }
14079    }
14080
14081    /**
14082     * Resolve all RTL related properties.
14083     *
14084     * @return true if resolution of RTL properties has been done
14085     *
14086     * @hide
14087     */
14088    public boolean resolveRtlPropertiesIfNeeded() {
14089        if (!needRtlPropertiesResolution()) return false;
14090
14091        // Order is important here: LayoutDirection MUST be resolved first
14092        if (!isLayoutDirectionResolved()) {
14093            resolveLayoutDirection();
14094            resolveLayoutParams();
14095        }
14096        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14097        if (!isTextDirectionResolved()) {
14098            resolveTextDirection();
14099        }
14100        if (!isTextAlignmentResolved()) {
14101            resolveTextAlignment();
14102        }
14103        // Should resolve Drawables before Padding because we need the layout direction of the
14104        // Drawable to correctly resolve Padding.
14105        if (!areDrawablesResolved()) {
14106            resolveDrawables();
14107        }
14108        if (!isPaddingResolved()) {
14109            resolvePadding();
14110        }
14111        onRtlPropertiesChanged(getLayoutDirection());
14112        return true;
14113    }
14114
14115    /**
14116     * Reset resolution of all RTL related properties.
14117     *
14118     * @hide
14119     */
14120    public void resetRtlProperties() {
14121        resetResolvedLayoutDirection();
14122        resetResolvedTextDirection();
14123        resetResolvedTextAlignment();
14124        resetResolvedPadding();
14125        resetResolvedDrawables();
14126    }
14127
14128    /**
14129     * @see #onScreenStateChanged(int)
14130     */
14131    void dispatchScreenStateChanged(int screenState) {
14132        onScreenStateChanged(screenState);
14133    }
14134
14135    /**
14136     * This method is called whenever the state of the screen this view is
14137     * attached to changes. A state change will usually occurs when the screen
14138     * turns on or off (whether it happens automatically or the user does it
14139     * manually.)
14140     *
14141     * @param screenState The new state of the screen. Can be either
14142     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14143     */
14144    public void onScreenStateChanged(int screenState) {
14145    }
14146
14147    /**
14148     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14149     */
14150    private boolean hasRtlSupport() {
14151        return mContext.getApplicationInfo().hasRtlSupport();
14152    }
14153
14154    /**
14155     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14156     * RTL not supported)
14157     */
14158    private boolean isRtlCompatibilityMode() {
14159        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14160        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14161    }
14162
14163    /**
14164     * @return true if RTL properties need resolution.
14165     *
14166     */
14167    private boolean needRtlPropertiesResolution() {
14168        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14169    }
14170
14171    /**
14172     * Called when any RTL property (layout direction or text direction or text alignment) has
14173     * been changed.
14174     *
14175     * Subclasses need to override this method to take care of cached information that depends on the
14176     * resolved layout direction, or to inform child views that inherit their layout direction.
14177     *
14178     * The default implementation does nothing.
14179     *
14180     * @param layoutDirection the direction of the layout
14181     *
14182     * @see #LAYOUT_DIRECTION_LTR
14183     * @see #LAYOUT_DIRECTION_RTL
14184     */
14185    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14186    }
14187
14188    /**
14189     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14190     * that the parent directionality can and will be resolved before its children.
14191     *
14192     * @return true if resolution has been done, false otherwise.
14193     *
14194     * @hide
14195     */
14196    public boolean resolveLayoutDirection() {
14197        // Clear any previous layout direction resolution
14198        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14199
14200        if (hasRtlSupport()) {
14201            // Set resolved depending on layout direction
14202            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14203                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14204                case LAYOUT_DIRECTION_INHERIT:
14205                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14206                    // later to get the correct resolved value
14207                    if (!canResolveLayoutDirection()) return false;
14208
14209                    // Parent has not yet resolved, LTR is still the default
14210                    try {
14211                        if (!mParent.isLayoutDirectionResolved()) return false;
14212
14213                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14214                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14215                        }
14216                    } catch (AbstractMethodError e) {
14217                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14218                                " does not fully implement ViewParent", e);
14219                    }
14220                    break;
14221                case LAYOUT_DIRECTION_RTL:
14222                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14223                    break;
14224                case LAYOUT_DIRECTION_LOCALE:
14225                    if((LAYOUT_DIRECTION_RTL ==
14226                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14227                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14228                    }
14229                    break;
14230                default:
14231                    // Nothing to do, LTR by default
14232            }
14233        }
14234
14235        // Set to resolved
14236        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14237        return true;
14238    }
14239
14240    /**
14241     * Check if layout direction resolution can be done.
14242     *
14243     * @return true if layout direction resolution can be done otherwise return false.
14244     */
14245    public boolean canResolveLayoutDirection() {
14246        switch (getRawLayoutDirection()) {
14247            case LAYOUT_DIRECTION_INHERIT:
14248                if (mParent != null) {
14249                    try {
14250                        return mParent.canResolveLayoutDirection();
14251                    } catch (AbstractMethodError e) {
14252                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14253                                " does not fully implement ViewParent", e);
14254                    }
14255                }
14256                return false;
14257
14258            default:
14259                return true;
14260        }
14261    }
14262
14263    /**
14264     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14265     * {@link #onMeasure(int, int)}.
14266     *
14267     * @hide
14268     */
14269    public void resetResolvedLayoutDirection() {
14270        // Reset the current resolved bits
14271        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14272    }
14273
14274    /**
14275     * @return true if the layout direction is inherited.
14276     *
14277     * @hide
14278     */
14279    public boolean isLayoutDirectionInherited() {
14280        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14281    }
14282
14283    /**
14284     * @return true if layout direction has been resolved.
14285     */
14286    public boolean isLayoutDirectionResolved() {
14287        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14288    }
14289
14290    /**
14291     * Return if padding has been resolved
14292     *
14293     * @hide
14294     */
14295    boolean isPaddingResolved() {
14296        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14297    }
14298
14299    /**
14300     * Resolves padding depending on layout direction, if applicable, and
14301     * recomputes internal padding values to adjust for scroll bars.
14302     *
14303     * @hide
14304     */
14305    public void resolvePadding() {
14306        final int resolvedLayoutDirection = getLayoutDirection();
14307
14308        if (!isRtlCompatibilityMode()) {
14309            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14310            // If start / end padding are defined, they will be resolved (hence overriding) to
14311            // left / right or right / left depending on the resolved layout direction.
14312            // If start / end padding are not defined, use the left / right ones.
14313            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14314                Rect padding = sThreadLocal.get();
14315                if (padding == null) {
14316                    padding = new Rect();
14317                    sThreadLocal.set(padding);
14318                }
14319                mBackground.getPadding(padding);
14320                if (!mLeftPaddingDefined) {
14321                    mUserPaddingLeftInitial = padding.left;
14322                }
14323                if (!mRightPaddingDefined) {
14324                    mUserPaddingRightInitial = padding.right;
14325                }
14326            }
14327            switch (resolvedLayoutDirection) {
14328                case LAYOUT_DIRECTION_RTL:
14329                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14330                        mUserPaddingRight = mUserPaddingStart;
14331                    } else {
14332                        mUserPaddingRight = mUserPaddingRightInitial;
14333                    }
14334                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14335                        mUserPaddingLeft = mUserPaddingEnd;
14336                    } else {
14337                        mUserPaddingLeft = mUserPaddingLeftInitial;
14338                    }
14339                    break;
14340                case LAYOUT_DIRECTION_LTR:
14341                default:
14342                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14343                        mUserPaddingLeft = mUserPaddingStart;
14344                    } else {
14345                        mUserPaddingLeft = mUserPaddingLeftInitial;
14346                    }
14347                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14348                        mUserPaddingRight = mUserPaddingEnd;
14349                    } else {
14350                        mUserPaddingRight = mUserPaddingRightInitial;
14351                    }
14352            }
14353
14354            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14355        }
14356
14357        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14358        onRtlPropertiesChanged(resolvedLayoutDirection);
14359
14360        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14361    }
14362
14363    /**
14364     * Reset the resolved layout direction.
14365     *
14366     * @hide
14367     */
14368    public void resetResolvedPadding() {
14369        resetResolvedPaddingInternal();
14370    }
14371
14372    /**
14373     * Used when we only want to reset *this* view's padding and not trigger overrides
14374     * in ViewGroup that reset children too.
14375     */
14376    void resetResolvedPaddingInternal() {
14377        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14378    }
14379
14380    /**
14381     * This is called when the view is detached from a window.  At this point it
14382     * no longer has a surface for drawing.
14383     *
14384     * @see #onAttachedToWindow()
14385     */
14386    @CallSuper
14387    protected void onDetachedFromWindow() {
14388    }
14389
14390    /**
14391     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14392     * after onDetachedFromWindow().
14393     *
14394     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14395     * The super method should be called at the end of the overridden method to ensure
14396     * subclasses are destroyed first
14397     *
14398     * @hide
14399     */
14400    @CallSuper
14401    protected void onDetachedFromWindowInternal() {
14402        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14403        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14404
14405        removeUnsetPressCallback();
14406        removeLongPressCallback();
14407        removePerformClickCallback();
14408        removeSendViewScrolledAccessibilityEventCallback();
14409        stopNestedScroll();
14410
14411        // Anything that started animating right before detach should already
14412        // be in its final state when re-attached.
14413        jumpDrawablesToCurrentState();
14414
14415        destroyDrawingCache();
14416
14417        cleanupDraw();
14418        mCurrentAnimation = null;
14419    }
14420
14421    private void cleanupDraw() {
14422        resetDisplayList();
14423        if (mAttachInfo != null) {
14424            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14425        }
14426    }
14427
14428    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14429    }
14430
14431    /**
14432     * @return The number of times this view has been attached to a window
14433     */
14434    protected int getWindowAttachCount() {
14435        return mWindowAttachCount;
14436    }
14437
14438    /**
14439     * Retrieve a unique token identifying the window this view is attached to.
14440     * @return Return the window's token for use in
14441     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14442     */
14443    public IBinder getWindowToken() {
14444        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14445    }
14446
14447    /**
14448     * Retrieve the {@link WindowId} for the window this view is
14449     * currently attached to.
14450     */
14451    public WindowId getWindowId() {
14452        if (mAttachInfo == null) {
14453            return null;
14454        }
14455        if (mAttachInfo.mWindowId == null) {
14456            try {
14457                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14458                        mAttachInfo.mWindowToken);
14459                mAttachInfo.mWindowId = new WindowId(
14460                        mAttachInfo.mIWindowId);
14461            } catch (RemoteException e) {
14462            }
14463        }
14464        return mAttachInfo.mWindowId;
14465    }
14466
14467    /**
14468     * Retrieve a unique token identifying the top-level "real" window of
14469     * the window that this view is attached to.  That is, this is like
14470     * {@link #getWindowToken}, except if the window this view in is a panel
14471     * window (attached to another containing window), then the token of
14472     * the containing window is returned instead.
14473     *
14474     * @return Returns the associated window token, either
14475     * {@link #getWindowToken()} or the containing window's token.
14476     */
14477    public IBinder getApplicationWindowToken() {
14478        AttachInfo ai = mAttachInfo;
14479        if (ai != null) {
14480            IBinder appWindowToken = ai.mPanelParentWindowToken;
14481            if (appWindowToken == null) {
14482                appWindowToken = ai.mWindowToken;
14483            }
14484            return appWindowToken;
14485        }
14486        return null;
14487    }
14488
14489    /**
14490     * Gets the logical display to which the view's window has been attached.
14491     *
14492     * @return The logical display, or null if the view is not currently attached to a window.
14493     */
14494    public Display getDisplay() {
14495        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14496    }
14497
14498    /**
14499     * Retrieve private session object this view hierarchy is using to
14500     * communicate with the window manager.
14501     * @return the session object to communicate with the window manager
14502     */
14503    /*package*/ IWindowSession getWindowSession() {
14504        return mAttachInfo != null ? mAttachInfo.mSession : null;
14505    }
14506
14507    /**
14508     * Return the visibility value of the least visible component passed.
14509     */
14510    int combineVisibility(int vis1, int vis2) {
14511        // This works because VISIBLE < INVISIBLE < GONE.
14512        return Math.max(vis1, vis2);
14513    }
14514
14515    /**
14516     * @param info the {@link android.view.View.AttachInfo} to associated with
14517     *        this view
14518     */
14519    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14520        //System.out.println("Attached! " + this);
14521        mAttachInfo = info;
14522        if (mOverlay != null) {
14523            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14524        }
14525        mWindowAttachCount++;
14526        // We will need to evaluate the drawable state at least once.
14527        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14528        if (mFloatingTreeObserver != null) {
14529            info.mTreeObserver.merge(mFloatingTreeObserver);
14530            mFloatingTreeObserver = null;
14531        }
14532        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14533            mAttachInfo.mScrollContainers.add(this);
14534            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14535        }
14536        performCollectViewAttributes(mAttachInfo, visibility);
14537        onAttachedToWindow();
14538
14539        ListenerInfo li = mListenerInfo;
14540        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14541                li != null ? li.mOnAttachStateChangeListeners : null;
14542        if (listeners != null && listeners.size() > 0) {
14543            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14544            // perform the dispatching. The iterator is a safe guard against listeners that
14545            // could mutate the list by calling the various add/remove methods. This prevents
14546            // the array from being modified while we iterate it.
14547            for (OnAttachStateChangeListener listener : listeners) {
14548                listener.onViewAttachedToWindow(this);
14549            }
14550        }
14551
14552        int vis = info.mWindowVisibility;
14553        if (vis != GONE) {
14554            onWindowVisibilityChanged(vis);
14555        }
14556
14557        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14558        // As all views in the subtree will already receive dispatchAttachedToWindow
14559        // traversing the subtree again here is not desired.
14560        onVisibilityChanged(this, visibility);
14561
14562        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14563            // If nobody has evaluated the drawable state yet, then do it now.
14564            refreshDrawableState();
14565        }
14566        needGlobalAttributesUpdate(false);
14567    }
14568
14569    void dispatchDetachedFromWindow() {
14570        AttachInfo info = mAttachInfo;
14571        if (info != null) {
14572            int vis = info.mWindowVisibility;
14573            if (vis != GONE) {
14574                onWindowVisibilityChanged(GONE);
14575            }
14576        }
14577
14578        onDetachedFromWindow();
14579        onDetachedFromWindowInternal();
14580
14581        InputMethodManager imm = InputMethodManager.peekInstance();
14582        if (imm != null) {
14583            imm.onViewDetachedFromWindow(this);
14584        }
14585
14586        ListenerInfo li = mListenerInfo;
14587        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14588                li != null ? li.mOnAttachStateChangeListeners : null;
14589        if (listeners != null && listeners.size() > 0) {
14590            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14591            // perform the dispatching. The iterator is a safe guard against listeners that
14592            // could mutate the list by calling the various add/remove methods. This prevents
14593            // the array from being modified while we iterate it.
14594            for (OnAttachStateChangeListener listener : listeners) {
14595                listener.onViewDetachedFromWindow(this);
14596            }
14597        }
14598
14599        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14600            mAttachInfo.mScrollContainers.remove(this);
14601            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14602        }
14603
14604        mAttachInfo = null;
14605        if (mOverlay != null) {
14606            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14607        }
14608    }
14609
14610    /**
14611     * Cancel any deferred high-level input events that were previously posted to the event queue.
14612     *
14613     * <p>Many views post high-level events such as click handlers to the event queue
14614     * to run deferred in order to preserve a desired user experience - clearing visible
14615     * pressed states before executing, etc. This method will abort any events of this nature
14616     * that are currently in flight.</p>
14617     *
14618     * <p>Custom views that generate their own high-level deferred input events should override
14619     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14620     *
14621     * <p>This will also cancel pending input events for any child views.</p>
14622     *
14623     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14624     * This will not impact newer events posted after this call that may occur as a result of
14625     * lower-level input events still waiting in the queue. If you are trying to prevent
14626     * double-submitted  events for the duration of some sort of asynchronous transaction
14627     * you should also take other steps to protect against unexpected double inputs e.g. calling
14628     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14629     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14630     */
14631    public final void cancelPendingInputEvents() {
14632        dispatchCancelPendingInputEvents();
14633    }
14634
14635    /**
14636     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14637     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14638     */
14639    void dispatchCancelPendingInputEvents() {
14640        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14641        onCancelPendingInputEvents();
14642        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14643            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14644                    " did not call through to super.onCancelPendingInputEvents()");
14645        }
14646    }
14647
14648    /**
14649     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14650     * a parent view.
14651     *
14652     * <p>This method is responsible for removing any pending high-level input events that were
14653     * posted to the event queue to run later. Custom view classes that post their own deferred
14654     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14655     * {@link android.os.Handler} should override this method, call
14656     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14657     * </p>
14658     */
14659    public void onCancelPendingInputEvents() {
14660        removePerformClickCallback();
14661        cancelLongPress();
14662        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14663    }
14664
14665    /**
14666     * Store this view hierarchy's frozen state into the given container.
14667     *
14668     * @param container The SparseArray in which to save the view's state.
14669     *
14670     * @see #restoreHierarchyState(android.util.SparseArray)
14671     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14672     * @see #onSaveInstanceState()
14673     */
14674    public void saveHierarchyState(SparseArray<Parcelable> container) {
14675        dispatchSaveInstanceState(container);
14676    }
14677
14678    /**
14679     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14680     * this view and its children. May be overridden to modify how freezing happens to a
14681     * view's children; for example, some views may want to not store state for their children.
14682     *
14683     * @param container The SparseArray in which to save the view's state.
14684     *
14685     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14686     * @see #saveHierarchyState(android.util.SparseArray)
14687     * @see #onSaveInstanceState()
14688     */
14689    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14690        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14691            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14692            Parcelable state = onSaveInstanceState();
14693            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14694                throw new IllegalStateException(
14695                        "Derived class did not call super.onSaveInstanceState()");
14696            }
14697            if (state != null) {
14698                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14699                // + ": " + state);
14700                container.put(mID, state);
14701            }
14702        }
14703    }
14704
14705    /**
14706     * Hook allowing a view to generate a representation of its internal state
14707     * that can later be used to create a new instance with that same state.
14708     * This state should only contain information that is not persistent or can
14709     * not be reconstructed later. For example, you will never store your
14710     * current position on screen because that will be computed again when a
14711     * new instance of the view is placed in its view hierarchy.
14712     * <p>
14713     * Some examples of things you may store here: the current cursor position
14714     * in a text view (but usually not the text itself since that is stored in a
14715     * content provider or other persistent storage), the currently selected
14716     * item in a list view.
14717     *
14718     * @return Returns a Parcelable object containing the view's current dynamic
14719     *         state, or null if there is nothing interesting to save. The
14720     *         default implementation returns null.
14721     * @see #onRestoreInstanceState(android.os.Parcelable)
14722     * @see #saveHierarchyState(android.util.SparseArray)
14723     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14724     * @see #setSaveEnabled(boolean)
14725     */
14726    @CallSuper
14727    protected Parcelable onSaveInstanceState() {
14728        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14729        if (mStartActivityRequestWho != null) {
14730            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14731            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14732            return state;
14733        }
14734        return BaseSavedState.EMPTY_STATE;
14735    }
14736
14737    /**
14738     * Restore this view hierarchy's frozen state from the given container.
14739     *
14740     * @param container The SparseArray which holds previously frozen states.
14741     *
14742     * @see #saveHierarchyState(android.util.SparseArray)
14743     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14744     * @see #onRestoreInstanceState(android.os.Parcelable)
14745     */
14746    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14747        dispatchRestoreInstanceState(container);
14748    }
14749
14750    /**
14751     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14752     * state for this view and its children. May be overridden to modify how restoring
14753     * happens to a view's children; for example, some views may want to not store state
14754     * for their children.
14755     *
14756     * @param container The SparseArray which holds previously saved state.
14757     *
14758     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14759     * @see #restoreHierarchyState(android.util.SparseArray)
14760     * @see #onRestoreInstanceState(android.os.Parcelable)
14761     */
14762    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14763        if (mID != NO_ID) {
14764            Parcelable state = container.get(mID);
14765            if (state != null) {
14766                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14767                // + ": " + state);
14768                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14769                onRestoreInstanceState(state);
14770                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14771                    throw new IllegalStateException(
14772                            "Derived class did not call super.onRestoreInstanceState()");
14773                }
14774            }
14775        }
14776    }
14777
14778    /**
14779     * Hook allowing a view to re-apply a representation of its internal state that had previously
14780     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14781     * null state.
14782     *
14783     * @param state The frozen state that had previously been returned by
14784     *        {@link #onSaveInstanceState}.
14785     *
14786     * @see #onSaveInstanceState()
14787     * @see #restoreHierarchyState(android.util.SparseArray)
14788     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14789     */
14790    @CallSuper
14791    protected void onRestoreInstanceState(Parcelable state) {
14792        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14793        if (state != null && !(state instanceof AbsSavedState)) {
14794            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14795                    + "received " + state.getClass().toString() + " instead. This usually happens "
14796                    + "when two views of different type have the same id in the same hierarchy. "
14797                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14798                    + "other views do not use the same id.");
14799        }
14800        if (state != null && state instanceof BaseSavedState) {
14801            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14802        }
14803    }
14804
14805    /**
14806     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14807     *
14808     * @return the drawing start time in milliseconds
14809     */
14810    public long getDrawingTime() {
14811        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14812    }
14813
14814    /**
14815     * <p>Enables or disables the duplication of the parent's state into this view. When
14816     * duplication is enabled, this view gets its drawable state from its parent rather
14817     * than from its own internal properties.</p>
14818     *
14819     * <p>Note: in the current implementation, setting this property to true after the
14820     * view was added to a ViewGroup might have no effect at all. This property should
14821     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14822     *
14823     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14824     * property is enabled, an exception will be thrown.</p>
14825     *
14826     * <p>Note: if the child view uses and updates additional states which are unknown to the
14827     * parent, these states should not be affected by this method.</p>
14828     *
14829     * @param enabled True to enable duplication of the parent's drawable state, false
14830     *                to disable it.
14831     *
14832     * @see #getDrawableState()
14833     * @see #isDuplicateParentStateEnabled()
14834     */
14835    public void setDuplicateParentStateEnabled(boolean enabled) {
14836        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14837    }
14838
14839    /**
14840     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14841     *
14842     * @return True if this view's drawable state is duplicated from the parent,
14843     *         false otherwise
14844     *
14845     * @see #getDrawableState()
14846     * @see #setDuplicateParentStateEnabled(boolean)
14847     */
14848    public boolean isDuplicateParentStateEnabled() {
14849        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14850    }
14851
14852    /**
14853     * <p>Specifies the type of layer backing this view. The layer can be
14854     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14855     * {@link #LAYER_TYPE_HARDWARE}.</p>
14856     *
14857     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14858     * instance that controls how the layer is composed on screen. The following
14859     * properties of the paint are taken into account when composing the layer:</p>
14860     * <ul>
14861     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14862     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14863     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14864     * </ul>
14865     *
14866     * <p>If this view has an alpha value set to < 1.0 by calling
14867     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14868     * by this view's alpha value.</p>
14869     *
14870     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14871     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14872     * for more information on when and how to use layers.</p>
14873     *
14874     * @param layerType The type of layer to use with this view, must be one of
14875     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14876     *        {@link #LAYER_TYPE_HARDWARE}
14877     * @param paint The paint used to compose the layer. This argument is optional
14878     *        and can be null. It is ignored when the layer type is
14879     *        {@link #LAYER_TYPE_NONE}
14880     *
14881     * @see #getLayerType()
14882     * @see #LAYER_TYPE_NONE
14883     * @see #LAYER_TYPE_SOFTWARE
14884     * @see #LAYER_TYPE_HARDWARE
14885     * @see #setAlpha(float)
14886     *
14887     * @attr ref android.R.styleable#View_layerType
14888     */
14889    public void setLayerType(int layerType, Paint paint) {
14890        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14891            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14892                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14893        }
14894
14895        boolean typeChanged = mRenderNode.setLayerType(layerType);
14896
14897        if (!typeChanged) {
14898            setLayerPaint(paint);
14899            return;
14900        }
14901
14902        // Destroy any previous software drawing cache if needed
14903        if (mLayerType == LAYER_TYPE_SOFTWARE) {
14904            destroyDrawingCache();
14905        }
14906
14907        mLayerType = layerType;
14908        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14909        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14910        mRenderNode.setLayerPaint(mLayerPaint);
14911
14912        // draw() behaves differently if we are on a layer, so we need to
14913        // invalidate() here
14914        invalidateParentCaches();
14915        invalidate(true);
14916    }
14917
14918    /**
14919     * Updates the {@link Paint} object used with the current layer (used only if the current
14920     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14921     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14922     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14923     * ensure that the view gets redrawn immediately.
14924     *
14925     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14926     * instance that controls how the layer is composed on screen. The following
14927     * properties of the paint are taken into account when composing the layer:</p>
14928     * <ul>
14929     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14930     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14931     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14932     * </ul>
14933     *
14934     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14935     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14936     *
14937     * @param paint The paint used to compose the layer. This argument is optional
14938     *        and can be null. It is ignored when the layer type is
14939     *        {@link #LAYER_TYPE_NONE}
14940     *
14941     * @see #setLayerType(int, android.graphics.Paint)
14942     */
14943    public void setLayerPaint(Paint paint) {
14944        int layerType = getLayerType();
14945        if (layerType != LAYER_TYPE_NONE) {
14946            mLayerPaint = paint == null ? new Paint() : paint;
14947            if (layerType == LAYER_TYPE_HARDWARE) {
14948                if (mRenderNode.setLayerPaint(mLayerPaint)) {
14949                    invalidateViewProperty(false, false);
14950                }
14951            } else {
14952                invalidate();
14953            }
14954        }
14955    }
14956
14957    /**
14958     * Indicates what type of layer is currently associated with this view. By default
14959     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14960     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14961     * for more information on the different types of layers.
14962     *
14963     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14964     *         {@link #LAYER_TYPE_HARDWARE}
14965     *
14966     * @see #setLayerType(int, android.graphics.Paint)
14967     * @see #buildLayer()
14968     * @see #LAYER_TYPE_NONE
14969     * @see #LAYER_TYPE_SOFTWARE
14970     * @see #LAYER_TYPE_HARDWARE
14971     */
14972    public int getLayerType() {
14973        return mLayerType;
14974    }
14975
14976    /**
14977     * Forces this view's layer to be created and this view to be rendered
14978     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14979     * invoking this method will have no effect.
14980     *
14981     * This method can for instance be used to render a view into its layer before
14982     * starting an animation. If this view is complex, rendering into the layer
14983     * before starting the animation will avoid skipping frames.
14984     *
14985     * @throws IllegalStateException If this view is not attached to a window
14986     *
14987     * @see #setLayerType(int, android.graphics.Paint)
14988     */
14989    public void buildLayer() {
14990        if (mLayerType == LAYER_TYPE_NONE) return;
14991
14992        final AttachInfo attachInfo = mAttachInfo;
14993        if (attachInfo == null) {
14994            throw new IllegalStateException("This view must be attached to a window first");
14995        }
14996
14997        if (getWidth() == 0 || getHeight() == 0) {
14998            return;
14999        }
15000
15001        switch (mLayerType) {
15002            case LAYER_TYPE_HARDWARE:
15003                updateDisplayListIfDirty();
15004                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15005                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15006                }
15007                break;
15008            case LAYER_TYPE_SOFTWARE:
15009                buildDrawingCache(true);
15010                break;
15011        }
15012    }
15013
15014    /**
15015     * Destroys all hardware rendering resources. This method is invoked
15016     * when the system needs to reclaim resources. Upon execution of this
15017     * method, you should free any OpenGL resources created by the view.
15018     *
15019     * Note: you <strong>must</strong> call
15020     * <code>super.destroyHardwareResources()</code> when overriding
15021     * this method.
15022     *
15023     * @hide
15024     */
15025    @CallSuper
15026    protected void destroyHardwareResources() {
15027        // Although the Layer will be destroyed by RenderNode, we want to release
15028        // the staging display list, which is also a signal to RenderNode that it's
15029        // safe to free its copy of the display list as it knows that we will
15030        // push an updated DisplayList if we try to draw again
15031        resetDisplayList();
15032    }
15033
15034    /**
15035     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15036     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15037     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15038     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15039     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15040     * null.</p>
15041     *
15042     * <p>Enabling the drawing cache is similar to
15043     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15044     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15045     * drawing cache has no effect on rendering because the system uses a different mechanism
15046     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15047     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15048     * for information on how to enable software and hardware layers.</p>
15049     *
15050     * <p>This API can be used to manually generate
15051     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15052     * {@link #getDrawingCache()}.</p>
15053     *
15054     * @param enabled true to enable the drawing cache, false otherwise
15055     *
15056     * @see #isDrawingCacheEnabled()
15057     * @see #getDrawingCache()
15058     * @see #buildDrawingCache()
15059     * @see #setLayerType(int, android.graphics.Paint)
15060     */
15061    public void setDrawingCacheEnabled(boolean enabled) {
15062        mCachingFailed = false;
15063        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15064    }
15065
15066    /**
15067     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15068     *
15069     * @return true if the drawing cache is enabled
15070     *
15071     * @see #setDrawingCacheEnabled(boolean)
15072     * @see #getDrawingCache()
15073     */
15074    @ViewDebug.ExportedProperty(category = "drawing")
15075    public boolean isDrawingCacheEnabled() {
15076        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15077    }
15078
15079    /**
15080     * Debugging utility which recursively outputs the dirty state of a view and its
15081     * descendants.
15082     *
15083     * @hide
15084     */
15085    @SuppressWarnings({"UnusedDeclaration"})
15086    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15087        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15088                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15089                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15090                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15091        if (clear) {
15092            mPrivateFlags &= clearMask;
15093        }
15094        if (this instanceof ViewGroup) {
15095            ViewGroup parent = (ViewGroup) this;
15096            final int count = parent.getChildCount();
15097            for (int i = 0; i < count; i++) {
15098                final View child = parent.getChildAt(i);
15099                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15100            }
15101        }
15102    }
15103
15104    /**
15105     * This method is used by ViewGroup to cause its children to restore or recreate their
15106     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15107     * to recreate its own display list, which would happen if it went through the normal
15108     * draw/dispatchDraw mechanisms.
15109     *
15110     * @hide
15111     */
15112    protected void dispatchGetDisplayList() {}
15113
15114    /**
15115     * A view that is not attached or hardware accelerated cannot create a display list.
15116     * This method checks these conditions and returns the appropriate result.
15117     *
15118     * @return true if view has the ability to create a display list, false otherwise.
15119     *
15120     * @hide
15121     */
15122    public boolean canHaveDisplayList() {
15123        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15124    }
15125
15126    /**
15127     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15128     * @hide
15129     */
15130    @NonNull
15131    public RenderNode updateDisplayListIfDirty() {
15132        final RenderNode renderNode = mRenderNode;
15133        if (!canHaveDisplayList()) {
15134            // can't populate RenderNode, don't try
15135            return renderNode;
15136        }
15137
15138        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15139                || !renderNode.isValid()
15140                || (mRecreateDisplayList)) {
15141            // Don't need to recreate the display list, just need to tell our
15142            // children to restore/recreate theirs
15143            if (renderNode.isValid()
15144                    && !mRecreateDisplayList) {
15145                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15146                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15147                dispatchGetDisplayList();
15148
15149                return renderNode; // no work needed
15150            }
15151
15152            // If we got here, we're recreating it. Mark it as such to ensure that
15153            // we copy in child display lists into ours in drawChild()
15154            mRecreateDisplayList = true;
15155
15156            int width = mRight - mLeft;
15157            int height = mBottom - mTop;
15158            int layerType = getLayerType();
15159
15160            final DisplayListCanvas canvas = renderNode.start(width, height);
15161            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15162
15163            try {
15164                if (layerType == LAYER_TYPE_SOFTWARE) {
15165                    buildDrawingCache(true);
15166                    Bitmap cache = getDrawingCache(true);
15167                    if (cache != null) {
15168                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15169                    }
15170                } else {
15171                    computeScroll();
15172
15173                    canvas.translate(-mScrollX, -mScrollY);
15174                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15175                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15176
15177                    // Fast path for layouts with no backgrounds
15178                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15179                        dispatchDraw(canvas);
15180                        if (mOverlay != null && !mOverlay.isEmpty()) {
15181                            mOverlay.getOverlayView().draw(canvas);
15182                        }
15183                    } else {
15184                        draw(canvas);
15185                    }
15186                }
15187            } finally {
15188                renderNode.end(canvas);
15189                setDisplayListProperties(renderNode);
15190            }
15191        } else {
15192            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15193            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15194        }
15195        return renderNode;
15196    }
15197
15198    private void resetDisplayList() {
15199        if (mRenderNode.isValid()) {
15200            mRenderNode.destroyDisplayListData();
15201        }
15202
15203        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15204            mBackgroundRenderNode.destroyDisplayListData();
15205        }
15206    }
15207
15208    /**
15209     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15210     *
15211     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15212     *
15213     * @see #getDrawingCache(boolean)
15214     */
15215    public Bitmap getDrawingCache() {
15216        return getDrawingCache(false);
15217    }
15218
15219    /**
15220     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15221     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15222     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15223     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15224     * request the drawing cache by calling this method and draw it on screen if the
15225     * returned bitmap is not null.</p>
15226     *
15227     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15228     * this method will create a bitmap of the same size as this view. Because this bitmap
15229     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15230     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15231     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15232     * size than the view. This implies that your application must be able to handle this
15233     * size.</p>
15234     *
15235     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15236     *        the current density of the screen when the application is in compatibility
15237     *        mode.
15238     *
15239     * @return A bitmap representing this view or null if cache is disabled.
15240     *
15241     * @see #setDrawingCacheEnabled(boolean)
15242     * @see #isDrawingCacheEnabled()
15243     * @see #buildDrawingCache(boolean)
15244     * @see #destroyDrawingCache()
15245     */
15246    public Bitmap getDrawingCache(boolean autoScale) {
15247        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15248            return null;
15249        }
15250        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15251            buildDrawingCache(autoScale);
15252        }
15253        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15254    }
15255
15256    /**
15257     * <p>Frees the resources used by the drawing cache. If you call
15258     * {@link #buildDrawingCache()} manually without calling
15259     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15260     * should cleanup the cache with this method afterwards.</p>
15261     *
15262     * @see #setDrawingCacheEnabled(boolean)
15263     * @see #buildDrawingCache()
15264     * @see #getDrawingCache()
15265     */
15266    public void destroyDrawingCache() {
15267        if (mDrawingCache != null) {
15268            mDrawingCache.recycle();
15269            mDrawingCache = null;
15270        }
15271        if (mUnscaledDrawingCache != null) {
15272            mUnscaledDrawingCache.recycle();
15273            mUnscaledDrawingCache = null;
15274        }
15275    }
15276
15277    /**
15278     * Setting a solid background color for the drawing cache's bitmaps will improve
15279     * performance and memory usage. Note, though that this should only be used if this
15280     * view will always be drawn on top of a solid color.
15281     *
15282     * @param color The background color to use for the drawing cache's bitmap
15283     *
15284     * @see #setDrawingCacheEnabled(boolean)
15285     * @see #buildDrawingCache()
15286     * @see #getDrawingCache()
15287     */
15288    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15289        if (color != mDrawingCacheBackgroundColor) {
15290            mDrawingCacheBackgroundColor = color;
15291            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15292        }
15293    }
15294
15295    /**
15296     * @see #setDrawingCacheBackgroundColor(int)
15297     *
15298     * @return The background color to used for the drawing cache's bitmap
15299     */
15300    @ColorInt
15301    public int getDrawingCacheBackgroundColor() {
15302        return mDrawingCacheBackgroundColor;
15303    }
15304
15305    /**
15306     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15307     *
15308     * @see #buildDrawingCache(boolean)
15309     */
15310    public void buildDrawingCache() {
15311        buildDrawingCache(false);
15312    }
15313
15314    /**
15315     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15316     *
15317     * <p>If you call {@link #buildDrawingCache()} manually without calling
15318     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15319     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15320     *
15321     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15322     * this method will create a bitmap of the same size as this view. Because this bitmap
15323     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15324     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15325     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15326     * size than the view. This implies that your application must be able to handle this
15327     * size.</p>
15328     *
15329     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15330     * you do not need the drawing cache bitmap, calling this method will increase memory
15331     * usage and cause the view to be rendered in software once, thus negatively impacting
15332     * performance.</p>
15333     *
15334     * @see #getDrawingCache()
15335     * @see #destroyDrawingCache()
15336     */
15337    public void buildDrawingCache(boolean autoScale) {
15338        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15339                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15340            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15341                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15342                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15343            }
15344            try {
15345                buildDrawingCacheImpl(autoScale);
15346            } finally {
15347                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15348            }
15349        }
15350    }
15351
15352    /**
15353     * private, internal implementation of buildDrawingCache, used to enable tracing
15354     */
15355    private void buildDrawingCacheImpl(boolean autoScale) {
15356        mCachingFailed = false;
15357
15358        int width = mRight - mLeft;
15359        int height = mBottom - mTop;
15360
15361        final AttachInfo attachInfo = mAttachInfo;
15362        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15363
15364        if (autoScale && scalingRequired) {
15365            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15366            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15367        }
15368
15369        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15370        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15371        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15372
15373        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15374        final long drawingCacheSize =
15375                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15376        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15377            if (width > 0 && height > 0) {
15378                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15379                        + " too large to fit into a software layer (or drawing cache), needs "
15380                        + projectedBitmapSize + " bytes, only "
15381                        + drawingCacheSize + " available");
15382            }
15383            destroyDrawingCache();
15384            mCachingFailed = true;
15385            return;
15386        }
15387
15388        boolean clear = true;
15389        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15390
15391        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15392            Bitmap.Config quality;
15393            if (!opaque) {
15394                // Never pick ARGB_4444 because it looks awful
15395                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15396                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15397                    case DRAWING_CACHE_QUALITY_AUTO:
15398                    case DRAWING_CACHE_QUALITY_LOW:
15399                    case DRAWING_CACHE_QUALITY_HIGH:
15400                    default:
15401                        quality = Bitmap.Config.ARGB_8888;
15402                        break;
15403                }
15404            } else {
15405                // Optimization for translucent windows
15406                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15407                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15408            }
15409
15410            // Try to cleanup memory
15411            if (bitmap != null) bitmap.recycle();
15412
15413            try {
15414                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15415                        width, height, quality);
15416                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15417                if (autoScale) {
15418                    mDrawingCache = bitmap;
15419                } else {
15420                    mUnscaledDrawingCache = bitmap;
15421                }
15422                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15423            } catch (OutOfMemoryError e) {
15424                // If there is not enough memory to create the bitmap cache, just
15425                // ignore the issue as bitmap caches are not required to draw the
15426                // view hierarchy
15427                if (autoScale) {
15428                    mDrawingCache = null;
15429                } else {
15430                    mUnscaledDrawingCache = null;
15431                }
15432                mCachingFailed = true;
15433                return;
15434            }
15435
15436            clear = drawingCacheBackgroundColor != 0;
15437        }
15438
15439        Canvas canvas;
15440        if (attachInfo != null) {
15441            canvas = attachInfo.mCanvas;
15442            if (canvas == null) {
15443                canvas = new Canvas();
15444            }
15445            canvas.setBitmap(bitmap);
15446            // Temporarily clobber the cached Canvas in case one of our children
15447            // is also using a drawing cache. Without this, the children would
15448            // steal the canvas by attaching their own bitmap to it and bad, bad
15449            // thing would happen (invisible views, corrupted drawings, etc.)
15450            attachInfo.mCanvas = null;
15451        } else {
15452            // This case should hopefully never or seldom happen
15453            canvas = new Canvas(bitmap);
15454        }
15455
15456        if (clear) {
15457            bitmap.eraseColor(drawingCacheBackgroundColor);
15458        }
15459
15460        computeScroll();
15461        final int restoreCount = canvas.save();
15462
15463        if (autoScale && scalingRequired) {
15464            final float scale = attachInfo.mApplicationScale;
15465            canvas.scale(scale, scale);
15466        }
15467
15468        canvas.translate(-mScrollX, -mScrollY);
15469
15470        mPrivateFlags |= PFLAG_DRAWN;
15471        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15472                mLayerType != LAYER_TYPE_NONE) {
15473            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15474        }
15475
15476        // Fast path for layouts with no backgrounds
15477        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15478            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15479            dispatchDraw(canvas);
15480            if (mOverlay != null && !mOverlay.isEmpty()) {
15481                mOverlay.getOverlayView().draw(canvas);
15482            }
15483        } else {
15484            draw(canvas);
15485        }
15486
15487        canvas.restoreToCount(restoreCount);
15488        canvas.setBitmap(null);
15489
15490        if (attachInfo != null) {
15491            // Restore the cached Canvas for our siblings
15492            attachInfo.mCanvas = canvas;
15493        }
15494    }
15495
15496    /**
15497     * Create a snapshot of the view into a bitmap.  We should probably make
15498     * some form of this public, but should think about the API.
15499     */
15500    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15501        int width = mRight - mLeft;
15502        int height = mBottom - mTop;
15503
15504        final AttachInfo attachInfo = mAttachInfo;
15505        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15506        width = (int) ((width * scale) + 0.5f);
15507        height = (int) ((height * scale) + 0.5f);
15508
15509        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15510                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15511        if (bitmap == null) {
15512            throw new OutOfMemoryError();
15513        }
15514
15515        Resources resources = getResources();
15516        if (resources != null) {
15517            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15518        }
15519
15520        Canvas canvas;
15521        if (attachInfo != null) {
15522            canvas = attachInfo.mCanvas;
15523            if (canvas == null) {
15524                canvas = new Canvas();
15525            }
15526            canvas.setBitmap(bitmap);
15527            // Temporarily clobber the cached Canvas in case one of our children
15528            // is also using a drawing cache. Without this, the children would
15529            // steal the canvas by attaching their own bitmap to it and bad, bad
15530            // things would happen (invisible views, corrupted drawings, etc.)
15531            attachInfo.mCanvas = null;
15532        } else {
15533            // This case should hopefully never or seldom happen
15534            canvas = new Canvas(bitmap);
15535        }
15536
15537        if ((backgroundColor & 0xff000000) != 0) {
15538            bitmap.eraseColor(backgroundColor);
15539        }
15540
15541        computeScroll();
15542        final int restoreCount = canvas.save();
15543        canvas.scale(scale, scale);
15544        canvas.translate(-mScrollX, -mScrollY);
15545
15546        // Temporarily remove the dirty mask
15547        int flags = mPrivateFlags;
15548        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15549
15550        // Fast path for layouts with no backgrounds
15551        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15552            dispatchDraw(canvas);
15553            if (mOverlay != null && !mOverlay.isEmpty()) {
15554                mOverlay.getOverlayView().draw(canvas);
15555            }
15556        } else {
15557            draw(canvas);
15558        }
15559
15560        mPrivateFlags = flags;
15561
15562        canvas.restoreToCount(restoreCount);
15563        canvas.setBitmap(null);
15564
15565        if (attachInfo != null) {
15566            // Restore the cached Canvas for our siblings
15567            attachInfo.mCanvas = canvas;
15568        }
15569
15570        return bitmap;
15571    }
15572
15573    /**
15574     * Indicates whether this View is currently in edit mode. A View is usually
15575     * in edit mode when displayed within a developer tool. For instance, if
15576     * this View is being drawn by a visual user interface builder, this method
15577     * should return true.
15578     *
15579     * Subclasses should check the return value of this method to provide
15580     * different behaviors if their normal behavior might interfere with the
15581     * host environment. For instance: the class spawns a thread in its
15582     * constructor, the drawing code relies on device-specific features, etc.
15583     *
15584     * This method is usually checked in the drawing code of custom widgets.
15585     *
15586     * @return True if this View is in edit mode, false otherwise.
15587     */
15588    public boolean isInEditMode() {
15589        return false;
15590    }
15591
15592    /**
15593     * If the View draws content inside its padding and enables fading edges,
15594     * it needs to support padding offsets. Padding offsets are added to the
15595     * fading edges to extend the length of the fade so that it covers pixels
15596     * drawn inside the padding.
15597     *
15598     * Subclasses of this class should override this method if they need
15599     * to draw content inside the padding.
15600     *
15601     * @return True if padding offset must be applied, false otherwise.
15602     *
15603     * @see #getLeftPaddingOffset()
15604     * @see #getRightPaddingOffset()
15605     * @see #getTopPaddingOffset()
15606     * @see #getBottomPaddingOffset()
15607     *
15608     * @since CURRENT
15609     */
15610    protected boolean isPaddingOffsetRequired() {
15611        return false;
15612    }
15613
15614    /**
15615     * Amount by which to extend the left fading region. Called only when
15616     * {@link #isPaddingOffsetRequired()} returns true.
15617     *
15618     * @return The left padding offset in pixels.
15619     *
15620     * @see #isPaddingOffsetRequired()
15621     *
15622     * @since CURRENT
15623     */
15624    protected int getLeftPaddingOffset() {
15625        return 0;
15626    }
15627
15628    /**
15629     * Amount by which to extend the right fading region. Called only when
15630     * {@link #isPaddingOffsetRequired()} returns true.
15631     *
15632     * @return The right padding offset in pixels.
15633     *
15634     * @see #isPaddingOffsetRequired()
15635     *
15636     * @since CURRENT
15637     */
15638    protected int getRightPaddingOffset() {
15639        return 0;
15640    }
15641
15642    /**
15643     * Amount by which to extend the top fading region. Called only when
15644     * {@link #isPaddingOffsetRequired()} returns true.
15645     *
15646     * @return The top padding offset in pixels.
15647     *
15648     * @see #isPaddingOffsetRequired()
15649     *
15650     * @since CURRENT
15651     */
15652    protected int getTopPaddingOffset() {
15653        return 0;
15654    }
15655
15656    /**
15657     * Amount by which to extend the bottom fading region. Called only when
15658     * {@link #isPaddingOffsetRequired()} returns true.
15659     *
15660     * @return The bottom padding offset in pixels.
15661     *
15662     * @see #isPaddingOffsetRequired()
15663     *
15664     * @since CURRENT
15665     */
15666    protected int getBottomPaddingOffset() {
15667        return 0;
15668    }
15669
15670    /**
15671     * @hide
15672     * @param offsetRequired
15673     */
15674    protected int getFadeTop(boolean offsetRequired) {
15675        int top = mPaddingTop;
15676        if (offsetRequired) top += getTopPaddingOffset();
15677        return top;
15678    }
15679
15680    /**
15681     * @hide
15682     * @param offsetRequired
15683     */
15684    protected int getFadeHeight(boolean offsetRequired) {
15685        int padding = mPaddingTop;
15686        if (offsetRequired) padding += getTopPaddingOffset();
15687        return mBottom - mTop - mPaddingBottom - padding;
15688    }
15689
15690    /**
15691     * <p>Indicates whether this view is attached to a hardware accelerated
15692     * window or not.</p>
15693     *
15694     * <p>Even if this method returns true, it does not mean that every call
15695     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15696     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15697     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15698     * window is hardware accelerated,
15699     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15700     * return false, and this method will return true.</p>
15701     *
15702     * @return True if the view is attached to a window and the window is
15703     *         hardware accelerated; false in any other case.
15704     */
15705    @ViewDebug.ExportedProperty(category = "drawing")
15706    public boolean isHardwareAccelerated() {
15707        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15708    }
15709
15710    /**
15711     * Sets a rectangular area on this view to which the view will be clipped
15712     * when it is drawn. Setting the value to null will remove the clip bounds
15713     * and the view will draw normally, using its full bounds.
15714     *
15715     * @param clipBounds The rectangular area, in the local coordinates of
15716     * this view, to which future drawing operations will be clipped.
15717     */
15718    public void setClipBounds(Rect clipBounds) {
15719        if (clipBounds == mClipBounds
15720                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15721            return;
15722        }
15723        if (clipBounds != null) {
15724            if (mClipBounds == null) {
15725                mClipBounds = new Rect(clipBounds);
15726            } else {
15727                mClipBounds.set(clipBounds);
15728            }
15729        } else {
15730            mClipBounds = null;
15731        }
15732        mRenderNode.setClipBounds(mClipBounds);
15733        invalidateViewProperty(false, false);
15734    }
15735
15736    /**
15737     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15738     *
15739     * @return A copy of the current clip bounds if clip bounds are set,
15740     * otherwise null.
15741     */
15742    public Rect getClipBounds() {
15743        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15744    }
15745
15746
15747    /**
15748     * Populates an output rectangle with the clip bounds of the view,
15749     * returning {@code true} if successful or {@code false} if the view's
15750     * clip bounds are {@code null}.
15751     *
15752     * @param outRect rectangle in which to place the clip bounds of the view
15753     * @return {@code true} if successful or {@code false} if the view's
15754     *         clip bounds are {@code null}
15755     */
15756    public boolean getClipBounds(Rect outRect) {
15757        if (mClipBounds != null) {
15758            outRect.set(mClipBounds);
15759            return true;
15760        }
15761        return false;
15762    }
15763
15764    /**
15765     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15766     * case of an active Animation being run on the view.
15767     */
15768    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15769            Animation a, boolean scalingRequired) {
15770        Transformation invalidationTransform;
15771        final int flags = parent.mGroupFlags;
15772        final boolean initialized = a.isInitialized();
15773        if (!initialized) {
15774            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15775            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15776            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15777            onAnimationStart();
15778        }
15779
15780        final Transformation t = parent.getChildTransformation();
15781        boolean more = a.getTransformation(drawingTime, t, 1f);
15782        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15783            if (parent.mInvalidationTransformation == null) {
15784                parent.mInvalidationTransformation = new Transformation();
15785            }
15786            invalidationTransform = parent.mInvalidationTransformation;
15787            a.getTransformation(drawingTime, invalidationTransform, 1f);
15788        } else {
15789            invalidationTransform = t;
15790        }
15791
15792        if (more) {
15793            if (!a.willChangeBounds()) {
15794                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15795                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15796                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15797                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15798                    // The child need to draw an animation, potentially offscreen, so
15799                    // make sure we do not cancel invalidate requests
15800                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15801                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15802                }
15803            } else {
15804                if (parent.mInvalidateRegion == null) {
15805                    parent.mInvalidateRegion = new RectF();
15806                }
15807                final RectF region = parent.mInvalidateRegion;
15808                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15809                        invalidationTransform);
15810
15811                // The child need to draw an animation, potentially offscreen, so
15812                // make sure we do not cancel invalidate requests
15813                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15814
15815                final int left = mLeft + (int) region.left;
15816                final int top = mTop + (int) region.top;
15817                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15818                        top + (int) (region.height() + .5f));
15819            }
15820        }
15821        return more;
15822    }
15823
15824    /**
15825     * This method is called by getDisplayList() when a display list is recorded for a View.
15826     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15827     */
15828    void setDisplayListProperties(RenderNode renderNode) {
15829        if (renderNode != null) {
15830            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15831            renderNode.setClipToBounds(mParent instanceof ViewGroup
15832                    && ((ViewGroup) mParent).getClipChildren());
15833
15834            float alpha = 1;
15835            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15836                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15837                ViewGroup parentVG = (ViewGroup) mParent;
15838                final Transformation t = parentVG.getChildTransformation();
15839                if (parentVG.getChildStaticTransformation(this, t)) {
15840                    final int transformType = t.getTransformationType();
15841                    if (transformType != Transformation.TYPE_IDENTITY) {
15842                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15843                            alpha = t.getAlpha();
15844                        }
15845                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15846                            renderNode.setStaticMatrix(t.getMatrix());
15847                        }
15848                    }
15849                }
15850            }
15851            if (mTransformationInfo != null) {
15852                alpha *= getFinalAlpha();
15853                if (alpha < 1) {
15854                    final int multipliedAlpha = (int) (255 * alpha);
15855                    if (onSetAlpha(multipliedAlpha)) {
15856                        alpha = 1;
15857                    }
15858                }
15859                renderNode.setAlpha(alpha);
15860            } else if (alpha < 1) {
15861                renderNode.setAlpha(alpha);
15862            }
15863        }
15864    }
15865
15866    /**
15867     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15868     *
15869     * This is where the View specializes rendering behavior based on layer type,
15870     * and hardware acceleration.
15871     */
15872    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15873        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15874        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15875         *
15876         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15877         * HW accelerated, it can't handle drawing RenderNodes.
15878         */
15879        boolean drawingWithRenderNode = mAttachInfo != null
15880                && mAttachInfo.mHardwareAccelerated
15881                && hardwareAcceleratedCanvas;
15882
15883        boolean more = false;
15884        final boolean childHasIdentityMatrix = hasIdentityMatrix();
15885        final int parentFlags = parent.mGroupFlags;
15886
15887        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15888            parent.getChildTransformation().clear();
15889            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15890        }
15891
15892        Transformation transformToApply = null;
15893        boolean concatMatrix = false;
15894        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15895        final Animation a = getAnimation();
15896        if (a != null) {
15897            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15898            concatMatrix = a.willChangeTransformationMatrix();
15899            if (concatMatrix) {
15900                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15901            }
15902            transformToApply = parent.getChildTransformation();
15903        } else {
15904            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15905                // No longer animating: clear out old animation matrix
15906                mRenderNode.setAnimationMatrix(null);
15907                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15908            }
15909            if (!drawingWithRenderNode
15910                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15911                final Transformation t = parent.getChildTransformation();
15912                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15913                if (hasTransform) {
15914                    final int transformType = t.getTransformationType();
15915                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15916                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15917                }
15918            }
15919        }
15920
15921        concatMatrix |= !childHasIdentityMatrix;
15922
15923        // Sets the flag as early as possible to allow draw() implementations
15924        // to call invalidate() successfully when doing animations
15925        mPrivateFlags |= PFLAG_DRAWN;
15926
15927        if (!concatMatrix &&
15928                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15929                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15930                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15931                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15932            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15933            return more;
15934        }
15935        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15936
15937        if (hardwareAcceleratedCanvas) {
15938            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15939            // retain the flag's value temporarily in the mRecreateDisplayList flag
15940            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15941            mPrivateFlags &= ~PFLAG_INVALIDATED;
15942        }
15943
15944        RenderNode renderNode = null;
15945        Bitmap cache = null;
15946        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15947        if (layerType == LAYER_TYPE_SOFTWARE
15948                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15949            // If not drawing with RenderNode, treat HW layers as SW
15950            layerType = LAYER_TYPE_SOFTWARE;
15951            buildDrawingCache(true);
15952            cache = getDrawingCache(true);
15953        }
15954
15955        if (drawingWithRenderNode) {
15956            // Delay getting the display list until animation-driven alpha values are
15957            // set up and possibly passed on to the view
15958            renderNode = updateDisplayListIfDirty();
15959            if (!renderNode.isValid()) {
15960                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15961                // to getDisplayList(), the display list will be marked invalid and we should not
15962                // try to use it again.
15963                renderNode = null;
15964                drawingWithRenderNode = false;
15965            }
15966        }
15967
15968        int sx = 0;
15969        int sy = 0;
15970        if (!drawingWithRenderNode) {
15971            computeScroll();
15972            sx = mScrollX;
15973            sy = mScrollY;
15974        }
15975
15976        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15977        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15978
15979        int restoreTo = -1;
15980        if (!drawingWithRenderNode || transformToApply != null) {
15981            restoreTo = canvas.save();
15982        }
15983        if (offsetForScroll) {
15984            canvas.translate(mLeft - sx, mTop - sy);
15985        } else {
15986            if (!drawingWithRenderNode) {
15987                canvas.translate(mLeft, mTop);
15988            }
15989            if (scalingRequired) {
15990                if (drawingWithRenderNode) {
15991                    // TODO: Might not need this if we put everything inside the DL
15992                    restoreTo = canvas.save();
15993                }
15994                // mAttachInfo cannot be null, otherwise scalingRequired == false
15995                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15996                canvas.scale(scale, scale);
15997            }
15998        }
15999
16000        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16001        if (transformToApply != null
16002                || alpha < 1
16003                || !hasIdentityMatrix()
16004                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16005            if (transformToApply != null || !childHasIdentityMatrix) {
16006                int transX = 0;
16007                int transY = 0;
16008
16009                if (offsetForScroll) {
16010                    transX = -sx;
16011                    transY = -sy;
16012                }
16013
16014                if (transformToApply != null) {
16015                    if (concatMatrix) {
16016                        if (drawingWithRenderNode) {
16017                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16018                        } else {
16019                            // Undo the scroll translation, apply the transformation matrix,
16020                            // then redo the scroll translate to get the correct result.
16021                            canvas.translate(-transX, -transY);
16022                            canvas.concat(transformToApply.getMatrix());
16023                            canvas.translate(transX, transY);
16024                        }
16025                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16026                    }
16027
16028                    float transformAlpha = transformToApply.getAlpha();
16029                    if (transformAlpha < 1) {
16030                        alpha *= transformAlpha;
16031                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16032                    }
16033                }
16034
16035                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16036                    canvas.translate(-transX, -transY);
16037                    canvas.concat(getMatrix());
16038                    canvas.translate(transX, transY);
16039                }
16040            }
16041
16042            // Deal with alpha if it is or used to be <1
16043            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16044                if (alpha < 1) {
16045                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16046                } else {
16047                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16048                }
16049                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16050                if (!drawingWithDrawingCache) {
16051                    final int multipliedAlpha = (int) (255 * alpha);
16052                    if (!onSetAlpha(multipliedAlpha)) {
16053                        if (drawingWithRenderNode) {
16054                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16055                        } else if (layerType == LAYER_TYPE_NONE) {
16056                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16057                                    multipliedAlpha);
16058                        }
16059                    } else {
16060                        // Alpha is handled by the child directly, clobber the layer's alpha
16061                        mPrivateFlags |= PFLAG_ALPHA_SET;
16062                    }
16063                }
16064            }
16065        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16066            onSetAlpha(255);
16067            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16068        }
16069
16070        if (!drawingWithRenderNode) {
16071            // apply clips directly, since RenderNode won't do it for this draw
16072            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16073                if (offsetForScroll) {
16074                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16075                } else {
16076                    if (!scalingRequired || cache == null) {
16077                        canvas.clipRect(0, 0, getWidth(), getHeight());
16078                    } else {
16079                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16080                    }
16081                }
16082            }
16083
16084            if (mClipBounds != null) {
16085                // clip bounds ignore scroll
16086                canvas.clipRect(mClipBounds);
16087            }
16088        }
16089
16090        if (!drawingWithDrawingCache) {
16091            if (drawingWithRenderNode) {
16092                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16093                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16094            } else {
16095                // Fast path for layouts with no backgrounds
16096                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16097                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16098                    dispatchDraw(canvas);
16099                } else {
16100                    draw(canvas);
16101                }
16102            }
16103        } else if (cache != null) {
16104            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16105            if (layerType == LAYER_TYPE_NONE) {
16106                // no layer paint, use temporary paint to draw bitmap
16107                Paint cachePaint = parent.mCachePaint;
16108                if (cachePaint == null) {
16109                    cachePaint = new Paint();
16110                    cachePaint.setDither(false);
16111                    parent.mCachePaint = cachePaint;
16112                }
16113                cachePaint.setAlpha((int) (alpha * 255));
16114                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16115            } else {
16116                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16117                int layerPaintAlpha = mLayerPaint.getAlpha();
16118                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16119                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16120                mLayerPaint.setAlpha(layerPaintAlpha);
16121            }
16122        }
16123
16124        if (restoreTo >= 0) {
16125            canvas.restoreToCount(restoreTo);
16126        }
16127
16128        if (a != null && !more) {
16129            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16130                onSetAlpha(255);
16131            }
16132            parent.finishAnimatingView(this, a);
16133        }
16134
16135        if (more && hardwareAcceleratedCanvas) {
16136            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16137                // alpha animations should cause the child to recreate its display list
16138                invalidate(true);
16139            }
16140        }
16141
16142        mRecreateDisplayList = false;
16143
16144        return more;
16145    }
16146
16147    /**
16148     * Manually render this view (and all of its children) to the given Canvas.
16149     * The view must have already done a full layout before this function is
16150     * called.  When implementing a view, implement
16151     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16152     * If you do need to override this method, call the superclass version.
16153     *
16154     * @param canvas The Canvas to which the View is rendered.
16155     */
16156    @CallSuper
16157    public void draw(Canvas canvas) {
16158        final int privateFlags = mPrivateFlags;
16159        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16160                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16161        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16162
16163        /*
16164         * Draw traversal performs several drawing steps which must be executed
16165         * in the appropriate order:
16166         *
16167         *      1. Draw the background
16168         *      2. If necessary, save the canvas' layers to prepare for fading
16169         *      3. Draw view's content
16170         *      4. Draw children
16171         *      5. If necessary, draw the fading edges and restore layers
16172         *      6. Draw decorations (scrollbars for instance)
16173         */
16174
16175        // Step 1, draw the background, if needed
16176        int saveCount;
16177
16178        if (!dirtyOpaque) {
16179            drawBackground(canvas);
16180        }
16181
16182        // skip step 2 & 5 if possible (common case)
16183        final int viewFlags = mViewFlags;
16184        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16185        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16186        if (!verticalEdges && !horizontalEdges) {
16187            // Step 3, draw the content
16188            if (!dirtyOpaque) onDraw(canvas);
16189
16190            // Step 4, draw the children
16191            dispatchDraw(canvas);
16192
16193            // Overlay is part of the content and draws beneath Foreground
16194            if (mOverlay != null && !mOverlay.isEmpty()) {
16195                mOverlay.getOverlayView().dispatchDraw(canvas);
16196            }
16197
16198            // Step 6, draw decorations (foreground, scrollbars)
16199            onDrawForeground(canvas);
16200
16201            // we're done...
16202            return;
16203        }
16204
16205        /*
16206         * Here we do the full fledged routine...
16207         * (this is an uncommon case where speed matters less,
16208         * this is why we repeat some of the tests that have been
16209         * done above)
16210         */
16211
16212        boolean drawTop = false;
16213        boolean drawBottom = false;
16214        boolean drawLeft = false;
16215        boolean drawRight = false;
16216
16217        float topFadeStrength = 0.0f;
16218        float bottomFadeStrength = 0.0f;
16219        float leftFadeStrength = 0.0f;
16220        float rightFadeStrength = 0.0f;
16221
16222        // Step 2, save the canvas' layers
16223        int paddingLeft = mPaddingLeft;
16224
16225        final boolean offsetRequired = isPaddingOffsetRequired();
16226        if (offsetRequired) {
16227            paddingLeft += getLeftPaddingOffset();
16228        }
16229
16230        int left = mScrollX + paddingLeft;
16231        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16232        int top = mScrollY + getFadeTop(offsetRequired);
16233        int bottom = top + getFadeHeight(offsetRequired);
16234
16235        if (offsetRequired) {
16236            right += getRightPaddingOffset();
16237            bottom += getBottomPaddingOffset();
16238        }
16239
16240        final ScrollabilityCache scrollabilityCache = mScrollCache;
16241        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16242        int length = (int) fadeHeight;
16243
16244        // clip the fade length if top and bottom fades overlap
16245        // overlapping fades produce odd-looking artifacts
16246        if (verticalEdges && (top + length > bottom - length)) {
16247            length = (bottom - top) / 2;
16248        }
16249
16250        // also clip horizontal fades if necessary
16251        if (horizontalEdges && (left + length > right - length)) {
16252            length = (right - left) / 2;
16253        }
16254
16255        if (verticalEdges) {
16256            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16257            drawTop = topFadeStrength * fadeHeight > 1.0f;
16258            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16259            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16260        }
16261
16262        if (horizontalEdges) {
16263            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16264            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16265            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16266            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16267        }
16268
16269        saveCount = canvas.getSaveCount();
16270
16271        int solidColor = getSolidColor();
16272        if (solidColor == 0) {
16273            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16274
16275            if (drawTop) {
16276                canvas.saveLayer(left, top, right, top + length, null, flags);
16277            }
16278
16279            if (drawBottom) {
16280                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16281            }
16282
16283            if (drawLeft) {
16284                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16285            }
16286
16287            if (drawRight) {
16288                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16289            }
16290        } else {
16291            scrollabilityCache.setFadeColor(solidColor);
16292        }
16293
16294        // Step 3, draw the content
16295        if (!dirtyOpaque) onDraw(canvas);
16296
16297        // Step 4, draw the children
16298        dispatchDraw(canvas);
16299
16300        // Step 5, draw the fade effect and restore layers
16301        final Paint p = scrollabilityCache.paint;
16302        final Matrix matrix = scrollabilityCache.matrix;
16303        final Shader fade = scrollabilityCache.shader;
16304
16305        if (drawTop) {
16306            matrix.setScale(1, fadeHeight * topFadeStrength);
16307            matrix.postTranslate(left, top);
16308            fade.setLocalMatrix(matrix);
16309            p.setShader(fade);
16310            canvas.drawRect(left, top, right, top + length, p);
16311        }
16312
16313        if (drawBottom) {
16314            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16315            matrix.postRotate(180);
16316            matrix.postTranslate(left, bottom);
16317            fade.setLocalMatrix(matrix);
16318            p.setShader(fade);
16319            canvas.drawRect(left, bottom - length, right, bottom, p);
16320        }
16321
16322        if (drawLeft) {
16323            matrix.setScale(1, fadeHeight * leftFadeStrength);
16324            matrix.postRotate(-90);
16325            matrix.postTranslate(left, top);
16326            fade.setLocalMatrix(matrix);
16327            p.setShader(fade);
16328            canvas.drawRect(left, top, left + length, bottom, p);
16329        }
16330
16331        if (drawRight) {
16332            matrix.setScale(1, fadeHeight * rightFadeStrength);
16333            matrix.postRotate(90);
16334            matrix.postTranslate(right, top);
16335            fade.setLocalMatrix(matrix);
16336            p.setShader(fade);
16337            canvas.drawRect(right - length, top, right, bottom, p);
16338        }
16339
16340        canvas.restoreToCount(saveCount);
16341
16342        // Overlay is part of the content and draws beneath Foreground
16343        if (mOverlay != null && !mOverlay.isEmpty()) {
16344            mOverlay.getOverlayView().dispatchDraw(canvas);
16345        }
16346
16347        // Step 6, draw decorations (foreground, scrollbars)
16348        onDrawForeground(canvas);
16349    }
16350
16351    /**
16352     * Draws the background onto the specified canvas.
16353     *
16354     * @param canvas Canvas on which to draw the background
16355     */
16356    private void drawBackground(Canvas canvas) {
16357        final Drawable background = mBackground;
16358        if (background == null) {
16359            return;
16360        }
16361
16362        setBackgroundBounds();
16363
16364        // Attempt to use a display list if requested.
16365        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16366                && mAttachInfo.mHardwareRenderer != null) {
16367            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16368
16369            final RenderNode renderNode = mBackgroundRenderNode;
16370            if (renderNode != null && renderNode.isValid()) {
16371                setBackgroundRenderNodeProperties(renderNode);
16372                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16373                return;
16374            }
16375        }
16376
16377        final int scrollX = mScrollX;
16378        final int scrollY = mScrollY;
16379        if ((scrollX | scrollY) == 0) {
16380            background.draw(canvas);
16381        } else {
16382            canvas.translate(scrollX, scrollY);
16383            background.draw(canvas);
16384            canvas.translate(-scrollX, -scrollY);
16385        }
16386    }
16387
16388    /**
16389     * Sets the correct background bounds and rebuilds the outline, if needed.
16390     * <p/>
16391     * This is called by LayoutLib.
16392     */
16393    void setBackgroundBounds() {
16394        if (mBackgroundSizeChanged && mBackground != null) {
16395            mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
16396            mBackgroundSizeChanged = false;
16397            rebuildOutline();
16398        }
16399    }
16400
16401    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16402        renderNode.setTranslationX(mScrollX);
16403        renderNode.setTranslationY(mScrollY);
16404    }
16405
16406    /**
16407     * Creates a new display list or updates the existing display list for the
16408     * specified Drawable.
16409     *
16410     * @param drawable Drawable for which to create a display list
16411     * @param renderNode Existing RenderNode, or {@code null}
16412     * @return A valid display list for the specified drawable
16413     */
16414    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16415        if (renderNode == null) {
16416            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16417        }
16418
16419        final Rect bounds = drawable.getBounds();
16420        final int width = bounds.width();
16421        final int height = bounds.height();
16422        final DisplayListCanvas canvas = renderNode.start(width, height);
16423
16424        // Reverse left/top translation done by drawable canvas, which will
16425        // instead be applied by rendernode's LTRB bounds below. This way, the
16426        // drawable's bounds match with its rendernode bounds and its content
16427        // will lie within those bounds in the rendernode tree.
16428        canvas.translate(-bounds.left, -bounds.top);
16429
16430        try {
16431            drawable.draw(canvas);
16432        } finally {
16433            renderNode.end(canvas);
16434        }
16435
16436        // Set up drawable properties that are view-independent.
16437        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16438        renderNode.setProjectBackwards(drawable.isProjected());
16439        renderNode.setProjectionReceiver(true);
16440        renderNode.setClipToBounds(false);
16441        return renderNode;
16442    }
16443
16444    /**
16445     * Returns the overlay for this view, creating it if it does not yet exist.
16446     * Adding drawables to the overlay will cause them to be displayed whenever
16447     * the view itself is redrawn. Objects in the overlay should be actively
16448     * managed: remove them when they should not be displayed anymore. The
16449     * overlay will always have the same size as its host view.
16450     *
16451     * <p>Note: Overlays do not currently work correctly with {@link
16452     * SurfaceView} or {@link TextureView}; contents in overlays for these
16453     * types of views may not display correctly.</p>
16454     *
16455     * @return The ViewOverlay object for this view.
16456     * @see ViewOverlay
16457     */
16458    public ViewOverlay getOverlay() {
16459        if (mOverlay == null) {
16460            mOverlay = new ViewOverlay(mContext, this);
16461        }
16462        return mOverlay;
16463    }
16464
16465    /**
16466     * Override this if your view is known to always be drawn on top of a solid color background,
16467     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16468     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16469     * should be set to 0xFF.
16470     *
16471     * @see #setVerticalFadingEdgeEnabled(boolean)
16472     * @see #setHorizontalFadingEdgeEnabled(boolean)
16473     *
16474     * @return The known solid color background for this view, or 0 if the color may vary
16475     */
16476    @ViewDebug.ExportedProperty(category = "drawing")
16477    @ColorInt
16478    public int getSolidColor() {
16479        return 0;
16480    }
16481
16482    /**
16483     * Build a human readable string representation of the specified view flags.
16484     *
16485     * @param flags the view flags to convert to a string
16486     * @return a String representing the supplied flags
16487     */
16488    private static String printFlags(int flags) {
16489        String output = "";
16490        int numFlags = 0;
16491        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16492            output += "TAKES_FOCUS";
16493            numFlags++;
16494        }
16495
16496        switch (flags & VISIBILITY_MASK) {
16497        case INVISIBLE:
16498            if (numFlags > 0) {
16499                output += " ";
16500            }
16501            output += "INVISIBLE";
16502            // USELESS HERE numFlags++;
16503            break;
16504        case GONE:
16505            if (numFlags > 0) {
16506                output += " ";
16507            }
16508            output += "GONE";
16509            // USELESS HERE numFlags++;
16510            break;
16511        default:
16512            break;
16513        }
16514        return output;
16515    }
16516
16517    /**
16518     * Build a human readable string representation of the specified private
16519     * view flags.
16520     *
16521     * @param privateFlags the private view flags to convert to a string
16522     * @return a String representing the supplied flags
16523     */
16524    private static String printPrivateFlags(int privateFlags) {
16525        String output = "";
16526        int numFlags = 0;
16527
16528        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16529            output += "WANTS_FOCUS";
16530            numFlags++;
16531        }
16532
16533        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16534            if (numFlags > 0) {
16535                output += " ";
16536            }
16537            output += "FOCUSED";
16538            numFlags++;
16539        }
16540
16541        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16542            if (numFlags > 0) {
16543                output += " ";
16544            }
16545            output += "SELECTED";
16546            numFlags++;
16547        }
16548
16549        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16550            if (numFlags > 0) {
16551                output += " ";
16552            }
16553            output += "IS_ROOT_NAMESPACE";
16554            numFlags++;
16555        }
16556
16557        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16558            if (numFlags > 0) {
16559                output += " ";
16560            }
16561            output += "HAS_BOUNDS";
16562            numFlags++;
16563        }
16564
16565        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16566            if (numFlags > 0) {
16567                output += " ";
16568            }
16569            output += "DRAWN";
16570            // USELESS HERE numFlags++;
16571        }
16572        return output;
16573    }
16574
16575    /**
16576     * <p>Indicates whether or not this view's layout will be requested during
16577     * the next hierarchy layout pass.</p>
16578     *
16579     * @return true if the layout will be forced during next layout pass
16580     */
16581    public boolean isLayoutRequested() {
16582        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16583    }
16584
16585    /**
16586     * Return true if o is a ViewGroup that is laying out using optical bounds.
16587     * @hide
16588     */
16589    public static boolean isLayoutModeOptical(Object o) {
16590        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16591    }
16592
16593    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16594        Insets parentInsets = mParent instanceof View ?
16595                ((View) mParent).getOpticalInsets() : Insets.NONE;
16596        Insets childInsets = getOpticalInsets();
16597        return setFrame(
16598                left   + parentInsets.left - childInsets.left,
16599                top    + parentInsets.top  - childInsets.top,
16600                right  + parentInsets.left + childInsets.right,
16601                bottom + parentInsets.top  + childInsets.bottom);
16602    }
16603
16604    /**
16605     * Assign a size and position to a view and all of its
16606     * descendants
16607     *
16608     * <p>This is the second phase of the layout mechanism.
16609     * (The first is measuring). In this phase, each parent calls
16610     * layout on all of its children to position them.
16611     * This is typically done using the child measurements
16612     * that were stored in the measure pass().</p>
16613     *
16614     * <p>Derived classes should not override this method.
16615     * Derived classes with children should override
16616     * onLayout. In that method, they should
16617     * call layout on each of their children.</p>
16618     *
16619     * @param l Left position, relative to parent
16620     * @param t Top position, relative to parent
16621     * @param r Right position, relative to parent
16622     * @param b Bottom position, relative to parent
16623     */
16624    @SuppressWarnings({"unchecked"})
16625    public void layout(int l, int t, int r, int b) {
16626        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16627            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16628            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16629        }
16630
16631        int oldL = mLeft;
16632        int oldT = mTop;
16633        int oldB = mBottom;
16634        int oldR = mRight;
16635
16636        boolean changed = isLayoutModeOptical(mParent) ?
16637                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16638
16639        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16640            onLayout(changed, l, t, r, b);
16641            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16642
16643            ListenerInfo li = mListenerInfo;
16644            if (li != null && li.mOnLayoutChangeListeners != null) {
16645                ArrayList<OnLayoutChangeListener> listenersCopy =
16646                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16647                int numListeners = listenersCopy.size();
16648                for (int i = 0; i < numListeners; ++i) {
16649                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16650                }
16651            }
16652        }
16653
16654        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16655        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16656    }
16657
16658    /**
16659     * Called from layout when this view should
16660     * assign a size and position to each of its children.
16661     *
16662     * Derived classes with children should override
16663     * this method and call layout on each of
16664     * their children.
16665     * @param changed This is a new size or position for this view
16666     * @param left Left position, relative to parent
16667     * @param top Top position, relative to parent
16668     * @param right Right position, relative to parent
16669     * @param bottom Bottom position, relative to parent
16670     */
16671    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16672    }
16673
16674    /**
16675     * Assign a size and position to this view.
16676     *
16677     * This is called from layout.
16678     *
16679     * @param left Left position, relative to parent
16680     * @param top Top position, relative to parent
16681     * @param right Right position, relative to parent
16682     * @param bottom Bottom position, relative to parent
16683     * @return true if the new size and position are different than the
16684     *         previous ones
16685     * {@hide}
16686     */
16687    protected boolean setFrame(int left, int top, int right, int bottom) {
16688        boolean changed = false;
16689
16690        if (DBG) {
16691            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16692                    + right + "," + bottom + ")");
16693        }
16694
16695        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16696            changed = true;
16697
16698            // Remember our drawn bit
16699            int drawn = mPrivateFlags & PFLAG_DRAWN;
16700
16701            int oldWidth = mRight - mLeft;
16702            int oldHeight = mBottom - mTop;
16703            int newWidth = right - left;
16704            int newHeight = bottom - top;
16705            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16706
16707            // Invalidate our old position
16708            invalidate(sizeChanged);
16709
16710            mLeft = left;
16711            mTop = top;
16712            mRight = right;
16713            mBottom = bottom;
16714            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16715
16716            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16717
16718
16719            if (sizeChanged) {
16720                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16721            }
16722
16723            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16724                // If we are visible, force the DRAWN bit to on so that
16725                // this invalidate will go through (at least to our parent).
16726                // This is because someone may have invalidated this view
16727                // before this call to setFrame came in, thereby clearing
16728                // the DRAWN bit.
16729                mPrivateFlags |= PFLAG_DRAWN;
16730                invalidate(sizeChanged);
16731                // parent display list may need to be recreated based on a change in the bounds
16732                // of any child
16733                invalidateParentCaches();
16734            }
16735
16736            // Reset drawn bit to original value (invalidate turns it off)
16737            mPrivateFlags |= drawn;
16738
16739            mBackgroundSizeChanged = true;
16740            if (mForegroundInfo != null) {
16741                mForegroundInfo.mBoundsChanged = true;
16742            }
16743
16744            notifySubtreeAccessibilityStateChangedIfNeeded();
16745        }
16746        return changed;
16747    }
16748
16749    /**
16750     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16751     * @hide
16752     */
16753    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16754        setFrame(left, top, right, bottom);
16755    }
16756
16757    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16758        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16759        if (mOverlay != null) {
16760            mOverlay.getOverlayView().setRight(newWidth);
16761            mOverlay.getOverlayView().setBottom(newHeight);
16762        }
16763        rebuildOutline();
16764    }
16765
16766    /**
16767     * Finalize inflating a view from XML.  This is called as the last phase
16768     * of inflation, after all child views have been added.
16769     *
16770     * <p>Even if the subclass overrides onFinishInflate, they should always be
16771     * sure to call the super method, so that we get called.
16772     */
16773    @CallSuper
16774    protected void onFinishInflate() {
16775    }
16776
16777    /**
16778     * Returns the resources associated with this view.
16779     *
16780     * @return Resources object.
16781     */
16782    public Resources getResources() {
16783        return mResources;
16784    }
16785
16786    /**
16787     * Invalidates the specified Drawable.
16788     *
16789     * @param drawable the drawable to invalidate
16790     */
16791    @Override
16792    public void invalidateDrawable(@NonNull Drawable drawable) {
16793        if (verifyDrawable(drawable)) {
16794            final Rect dirty = drawable.getDirtyBounds();
16795            final int scrollX = mScrollX;
16796            final int scrollY = mScrollY;
16797
16798            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16799                    dirty.right + scrollX, dirty.bottom + scrollY);
16800            rebuildOutline();
16801        }
16802    }
16803
16804    /**
16805     * Schedules an action on a drawable to occur at a specified time.
16806     *
16807     * @param who the recipient of the action
16808     * @param what the action to run on the drawable
16809     * @param when the time at which the action must occur. Uses the
16810     *        {@link SystemClock#uptimeMillis} timebase.
16811     */
16812    @Override
16813    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16814        if (verifyDrawable(who) && what != null) {
16815            final long delay = when - SystemClock.uptimeMillis();
16816            if (mAttachInfo != null) {
16817                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16818                        Choreographer.CALLBACK_ANIMATION, what, who,
16819                        Choreographer.subtractFrameDelay(delay));
16820            } else {
16821                ViewRootImpl.getRunQueue().postDelayed(what, delay);
16822            }
16823        }
16824    }
16825
16826    /**
16827     * Cancels a scheduled action on a drawable.
16828     *
16829     * @param who the recipient of the action
16830     * @param what the action to cancel
16831     */
16832    @Override
16833    public void unscheduleDrawable(Drawable who, Runnable what) {
16834        if (verifyDrawable(who) && what != null) {
16835            if (mAttachInfo != null) {
16836                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16837                        Choreographer.CALLBACK_ANIMATION, what, who);
16838            }
16839            ViewRootImpl.getRunQueue().removeCallbacks(what);
16840        }
16841    }
16842
16843    /**
16844     * Unschedule any events associated with the given Drawable.  This can be
16845     * used when selecting a new Drawable into a view, so that the previous
16846     * one is completely unscheduled.
16847     *
16848     * @param who The Drawable to unschedule.
16849     *
16850     * @see #drawableStateChanged
16851     */
16852    public void unscheduleDrawable(Drawable who) {
16853        if (mAttachInfo != null && who != null) {
16854            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16855                    Choreographer.CALLBACK_ANIMATION, null, who);
16856        }
16857    }
16858
16859    /**
16860     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16861     * that the View directionality can and will be resolved before its Drawables.
16862     *
16863     * Will call {@link View#onResolveDrawables} when resolution is done.
16864     *
16865     * @hide
16866     */
16867    protected void resolveDrawables() {
16868        // Drawables resolution may need to happen before resolving the layout direction (which is
16869        // done only during the measure() call).
16870        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16871        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16872        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16873        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16874        // direction to be resolved as its resolved value will be the same as its raw value.
16875        if (!isLayoutDirectionResolved() &&
16876                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16877            return;
16878        }
16879
16880        final int layoutDirection = isLayoutDirectionResolved() ?
16881                getLayoutDirection() : getRawLayoutDirection();
16882
16883        if (mBackground != null) {
16884            mBackground.setLayoutDirection(layoutDirection);
16885        }
16886        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16887            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16888        }
16889        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16890        onResolveDrawables(layoutDirection);
16891    }
16892
16893    boolean areDrawablesResolved() {
16894        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16895    }
16896
16897    /**
16898     * Called when layout direction has been resolved.
16899     *
16900     * The default implementation does nothing.
16901     *
16902     * @param layoutDirection The resolved layout direction.
16903     *
16904     * @see #LAYOUT_DIRECTION_LTR
16905     * @see #LAYOUT_DIRECTION_RTL
16906     *
16907     * @hide
16908     */
16909    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16910    }
16911
16912    /**
16913     * @hide
16914     */
16915    protected void resetResolvedDrawables() {
16916        resetResolvedDrawablesInternal();
16917    }
16918
16919    void resetResolvedDrawablesInternal() {
16920        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16921    }
16922
16923    /**
16924     * If your view subclass is displaying its own Drawable objects, it should
16925     * override this function and return true for any Drawable it is
16926     * displaying.  This allows animations for those drawables to be
16927     * scheduled.
16928     *
16929     * <p>Be sure to call through to the super class when overriding this
16930     * function.
16931     *
16932     * @param who The Drawable to verify.  Return true if it is one you are
16933     *            displaying, else return the result of calling through to the
16934     *            super class.
16935     *
16936     * @return boolean If true than the Drawable is being displayed in the
16937     *         view; else false and it is not allowed to animate.
16938     *
16939     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16940     * @see #drawableStateChanged()
16941     */
16942    @CallSuper
16943    protected boolean verifyDrawable(Drawable who) {
16944        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16945                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16946    }
16947
16948    /**
16949     * This function is called whenever the state of the view changes in such
16950     * a way that it impacts the state of drawables being shown.
16951     * <p>
16952     * If the View has a StateListAnimator, it will also be called to run necessary state
16953     * change animations.
16954     * <p>
16955     * Be sure to call through to the superclass when overriding this function.
16956     *
16957     * @see Drawable#setState(int[])
16958     */
16959    @CallSuper
16960    protected void drawableStateChanged() {
16961        final int[] state = getDrawableState();
16962
16963        final Drawable bg = mBackground;
16964        if (bg != null && bg.isStateful()) {
16965            bg.setState(state);
16966        }
16967
16968        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16969        if (fg != null && fg.isStateful()) {
16970            fg.setState(state);
16971        }
16972
16973        if (mScrollCache != null) {
16974            final Drawable scrollBar = mScrollCache.scrollBar;
16975            if (scrollBar != null && scrollBar.isStateful()) {
16976                scrollBar.setState(state);
16977            }
16978        }
16979
16980        if (mStateListAnimator != null) {
16981            mStateListAnimator.setState(state);
16982        }
16983    }
16984
16985    /**
16986     * This function is called whenever the view hotspot changes and needs to
16987     * be propagated to drawables or child views managed by the view.
16988     * <p>
16989     * Dispatching to child views is handled by
16990     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16991     * <p>
16992     * Be sure to call through to the superclass when overriding this function.
16993     *
16994     * @param x hotspot x coordinate
16995     * @param y hotspot y coordinate
16996     */
16997    @CallSuper
16998    public void drawableHotspotChanged(float x, float y) {
16999        if (mBackground != null) {
17000            mBackground.setHotspot(x, y);
17001        }
17002        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17003            mForegroundInfo.mDrawable.setHotspot(x, y);
17004        }
17005
17006        dispatchDrawableHotspotChanged(x, y);
17007    }
17008
17009    /**
17010     * Dispatches drawableHotspotChanged to all of this View's children.
17011     *
17012     * @param x hotspot x coordinate
17013     * @param y hotspot y coordinate
17014     * @see #drawableHotspotChanged(float, float)
17015     */
17016    public void dispatchDrawableHotspotChanged(float x, float y) {
17017    }
17018
17019    /**
17020     * Call this to force a view to update its drawable state. This will cause
17021     * drawableStateChanged to be called on this view. Views that are interested
17022     * in the new state should call getDrawableState.
17023     *
17024     * @see #drawableStateChanged
17025     * @see #getDrawableState
17026     */
17027    public void refreshDrawableState() {
17028        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17029        drawableStateChanged();
17030
17031        ViewParent parent = mParent;
17032        if (parent != null) {
17033            parent.childDrawableStateChanged(this);
17034        }
17035    }
17036
17037    /**
17038     * Return an array of resource IDs of the drawable states representing the
17039     * current state of the view.
17040     *
17041     * @return The current drawable state
17042     *
17043     * @see Drawable#setState(int[])
17044     * @see #drawableStateChanged()
17045     * @see #onCreateDrawableState(int)
17046     */
17047    public final int[] getDrawableState() {
17048        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17049            return mDrawableState;
17050        } else {
17051            mDrawableState = onCreateDrawableState(0);
17052            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17053            return mDrawableState;
17054        }
17055    }
17056
17057    /**
17058     * Generate the new {@link android.graphics.drawable.Drawable} state for
17059     * this view. This is called by the view
17060     * system when the cached Drawable state is determined to be invalid.  To
17061     * retrieve the current state, you should use {@link #getDrawableState}.
17062     *
17063     * @param extraSpace if non-zero, this is the number of extra entries you
17064     * would like in the returned array in which you can place your own
17065     * states.
17066     *
17067     * @return Returns an array holding the current {@link Drawable} state of
17068     * the view.
17069     *
17070     * @see #mergeDrawableStates(int[], int[])
17071     */
17072    protected int[] onCreateDrawableState(int extraSpace) {
17073        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17074                mParent instanceof View) {
17075            return ((View) mParent).onCreateDrawableState(extraSpace);
17076        }
17077
17078        int[] drawableState;
17079
17080        int privateFlags = mPrivateFlags;
17081
17082        int viewStateIndex = 0;
17083        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17084        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17085        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17086        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17087        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17088        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17089        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17090                HardwareRenderer.isAvailable()) {
17091            // This is set if HW acceleration is requested, even if the current
17092            // process doesn't allow it.  This is just to allow app preview
17093            // windows to better match their app.
17094            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17095        }
17096        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17097
17098        final int privateFlags2 = mPrivateFlags2;
17099        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17100            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17101        }
17102        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17103            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17104        }
17105
17106        drawableState = StateSet.get(viewStateIndex);
17107
17108        //noinspection ConstantIfStatement
17109        if (false) {
17110            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17111            Log.i("View", toString()
17112                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17113                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17114                    + " fo=" + hasFocus()
17115                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17116                    + " wf=" + hasWindowFocus()
17117                    + ": " + Arrays.toString(drawableState));
17118        }
17119
17120        if (extraSpace == 0) {
17121            return drawableState;
17122        }
17123
17124        final int[] fullState;
17125        if (drawableState != null) {
17126            fullState = new int[drawableState.length + extraSpace];
17127            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17128        } else {
17129            fullState = new int[extraSpace];
17130        }
17131
17132        return fullState;
17133    }
17134
17135    /**
17136     * Merge your own state values in <var>additionalState</var> into the base
17137     * state values <var>baseState</var> that were returned by
17138     * {@link #onCreateDrawableState(int)}.
17139     *
17140     * @param baseState The base state values returned by
17141     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17142     * own additional state values.
17143     *
17144     * @param additionalState The additional state values you would like
17145     * added to <var>baseState</var>; this array is not modified.
17146     *
17147     * @return As a convenience, the <var>baseState</var> array you originally
17148     * passed into the function is returned.
17149     *
17150     * @see #onCreateDrawableState(int)
17151     */
17152    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17153        final int N = baseState.length;
17154        int i = N - 1;
17155        while (i >= 0 && baseState[i] == 0) {
17156            i--;
17157        }
17158        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17159        return baseState;
17160    }
17161
17162    /**
17163     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17164     * on all Drawable objects associated with this view.
17165     * <p>
17166     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17167     * attached to this view.
17168     */
17169    @CallSuper
17170    public void jumpDrawablesToCurrentState() {
17171        if (mBackground != null) {
17172            mBackground.jumpToCurrentState();
17173        }
17174        if (mStateListAnimator != null) {
17175            mStateListAnimator.jumpToCurrentState();
17176        }
17177        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17178            mForegroundInfo.mDrawable.jumpToCurrentState();
17179        }
17180    }
17181
17182    /**
17183     * Sets the background color for this view.
17184     * @param color the color of the background
17185     */
17186    @RemotableViewMethod
17187    public void setBackgroundColor(@ColorInt int color) {
17188        if (mBackground instanceof ColorDrawable) {
17189            ((ColorDrawable) mBackground.mutate()).setColor(color);
17190            computeOpaqueFlags();
17191            mBackgroundResource = 0;
17192        } else {
17193            setBackground(new ColorDrawable(color));
17194        }
17195    }
17196
17197    /**
17198     * Set the background to a given resource. The resource should refer to
17199     * a Drawable object or 0 to remove the background.
17200     * @param resid The identifier of the resource.
17201     *
17202     * @attr ref android.R.styleable#View_background
17203     */
17204    @RemotableViewMethod
17205    public void setBackgroundResource(@DrawableRes int resid) {
17206        if (resid != 0 && resid == mBackgroundResource) {
17207            return;
17208        }
17209
17210        Drawable d = null;
17211        if (resid != 0) {
17212            d = mContext.getDrawable(resid);
17213        }
17214        setBackground(d);
17215
17216        mBackgroundResource = resid;
17217    }
17218
17219    /**
17220     * Set the background to a given Drawable, or remove the background. If the
17221     * background has padding, this View's padding is set to the background's
17222     * padding. However, when a background is removed, this View's padding isn't
17223     * touched. If setting the padding is desired, please use
17224     * {@link #setPadding(int, int, int, int)}.
17225     *
17226     * @param background The Drawable to use as the background, or null to remove the
17227     *        background
17228     */
17229    public void setBackground(Drawable background) {
17230        //noinspection deprecation
17231        setBackgroundDrawable(background);
17232    }
17233
17234    /**
17235     * @deprecated use {@link #setBackground(Drawable)} instead
17236     */
17237    @Deprecated
17238    public void setBackgroundDrawable(Drawable background) {
17239        computeOpaqueFlags();
17240
17241        if (background == mBackground) {
17242            return;
17243        }
17244
17245        boolean requestLayout = false;
17246
17247        mBackgroundResource = 0;
17248
17249        /*
17250         * Regardless of whether we're setting a new background or not, we want
17251         * to clear the previous drawable.
17252         */
17253        if (mBackground != null) {
17254            mBackground.setCallback(null);
17255            unscheduleDrawable(mBackground);
17256        }
17257
17258        if (background != null) {
17259            Rect padding = sThreadLocal.get();
17260            if (padding == null) {
17261                padding = new Rect();
17262                sThreadLocal.set(padding);
17263            }
17264            resetResolvedDrawablesInternal();
17265            background.setLayoutDirection(getLayoutDirection());
17266            if (background.getPadding(padding)) {
17267                resetResolvedPaddingInternal();
17268                switch (background.getLayoutDirection()) {
17269                    case LAYOUT_DIRECTION_RTL:
17270                        mUserPaddingLeftInitial = padding.right;
17271                        mUserPaddingRightInitial = padding.left;
17272                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17273                        break;
17274                    case LAYOUT_DIRECTION_LTR:
17275                    default:
17276                        mUserPaddingLeftInitial = padding.left;
17277                        mUserPaddingRightInitial = padding.right;
17278                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17279                }
17280                mLeftPaddingDefined = false;
17281                mRightPaddingDefined = false;
17282            }
17283
17284            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17285            // if it has a different minimum size, we should layout again
17286            if (mBackground == null
17287                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17288                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17289                requestLayout = true;
17290            }
17291
17292            background.setCallback(this);
17293            if (background.isStateful()) {
17294                background.setState(getDrawableState());
17295            }
17296            background.setVisible(getVisibility() == VISIBLE, false);
17297            mBackground = background;
17298
17299            applyBackgroundTint();
17300
17301            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17302                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17303                requestLayout = true;
17304            }
17305        } else {
17306            /* Remove the background */
17307            mBackground = null;
17308            if ((mViewFlags & WILL_NOT_DRAW) != 0
17309                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17310                mPrivateFlags |= PFLAG_SKIP_DRAW;
17311            }
17312
17313            /*
17314             * When the background is set, we try to apply its padding to this
17315             * View. When the background is removed, we don't touch this View's
17316             * padding. This is noted in the Javadocs. Hence, we don't need to
17317             * requestLayout(), the invalidate() below is sufficient.
17318             */
17319
17320            // The old background's minimum size could have affected this
17321            // View's layout, so let's requestLayout
17322            requestLayout = true;
17323        }
17324
17325        computeOpaqueFlags();
17326
17327        if (requestLayout) {
17328            requestLayout();
17329        }
17330
17331        mBackgroundSizeChanged = true;
17332        invalidate(true);
17333    }
17334
17335    /**
17336     * Gets the background drawable
17337     *
17338     * @return The drawable used as the background for this view, if any.
17339     *
17340     * @see #setBackground(Drawable)
17341     *
17342     * @attr ref android.R.styleable#View_background
17343     */
17344    public Drawable getBackground() {
17345        return mBackground;
17346    }
17347
17348    /**
17349     * Applies a tint to the background drawable. Does not modify the current tint
17350     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17351     * <p>
17352     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17353     * mutate the drawable and apply the specified tint and tint mode using
17354     * {@link Drawable#setTintList(ColorStateList)}.
17355     *
17356     * @param tint the tint to apply, may be {@code null} to clear tint
17357     *
17358     * @attr ref android.R.styleable#View_backgroundTint
17359     * @see #getBackgroundTintList()
17360     * @see Drawable#setTintList(ColorStateList)
17361     */
17362    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17363        if (mBackgroundTint == null) {
17364            mBackgroundTint = new TintInfo();
17365        }
17366        mBackgroundTint.mTintList = tint;
17367        mBackgroundTint.mHasTintList = true;
17368
17369        applyBackgroundTint();
17370    }
17371
17372    /**
17373     * Return the tint applied to the background drawable, if specified.
17374     *
17375     * @return the tint applied to the background drawable
17376     * @attr ref android.R.styleable#View_backgroundTint
17377     * @see #setBackgroundTintList(ColorStateList)
17378     */
17379    @Nullable
17380    public ColorStateList getBackgroundTintList() {
17381        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17382    }
17383
17384    /**
17385     * Specifies the blending mode used to apply the tint specified by
17386     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17387     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17388     *
17389     * @param tintMode the blending mode used to apply the tint, may be
17390     *                 {@code null} to clear tint
17391     * @attr ref android.R.styleable#View_backgroundTintMode
17392     * @see #getBackgroundTintMode()
17393     * @see Drawable#setTintMode(PorterDuff.Mode)
17394     */
17395    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17396        if (mBackgroundTint == null) {
17397            mBackgroundTint = new TintInfo();
17398        }
17399        mBackgroundTint.mTintMode = tintMode;
17400        mBackgroundTint.mHasTintMode = true;
17401
17402        applyBackgroundTint();
17403    }
17404
17405    /**
17406     * Return the blending mode used to apply the tint to the background
17407     * drawable, if specified.
17408     *
17409     * @return the blending mode used to apply the tint to the background
17410     *         drawable
17411     * @attr ref android.R.styleable#View_backgroundTintMode
17412     * @see #setBackgroundTintMode(PorterDuff.Mode)
17413     */
17414    @Nullable
17415    public PorterDuff.Mode getBackgroundTintMode() {
17416        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17417    }
17418
17419    private void applyBackgroundTint() {
17420        if (mBackground != null && mBackgroundTint != null) {
17421            final TintInfo tintInfo = mBackgroundTint;
17422            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17423                mBackground = mBackground.mutate();
17424
17425                if (tintInfo.mHasTintList) {
17426                    mBackground.setTintList(tintInfo.mTintList);
17427                }
17428
17429                if (tintInfo.mHasTintMode) {
17430                    mBackground.setTintMode(tintInfo.mTintMode);
17431                }
17432
17433                // The drawable (or one of its children) may not have been
17434                // stateful before applying the tint, so let's try again.
17435                if (mBackground.isStateful()) {
17436                    mBackground.setState(getDrawableState());
17437                }
17438            }
17439        }
17440    }
17441
17442    /**
17443     * Returns the drawable used as the foreground of this View. The
17444     * foreground drawable, if non-null, is always drawn on top of the view's content.
17445     *
17446     * @return a Drawable or null if no foreground was set
17447     *
17448     * @see #onDrawForeground(Canvas)
17449     */
17450    public Drawable getForeground() {
17451        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17452    }
17453
17454    /**
17455     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17456     *
17457     * @param foreground the Drawable to be drawn on top of the children
17458     *
17459     * @attr ref android.R.styleable#View_foreground
17460     */
17461    public void setForeground(Drawable foreground) {
17462        if (mForegroundInfo == null) {
17463            if (foreground == null) {
17464                // Nothing to do.
17465                return;
17466            }
17467            mForegroundInfo = new ForegroundInfo();
17468        }
17469
17470        if (foreground == mForegroundInfo.mDrawable) {
17471            // Nothing to do
17472            return;
17473        }
17474
17475        if (mForegroundInfo.mDrawable != null) {
17476            mForegroundInfo.mDrawable.setCallback(null);
17477            unscheduleDrawable(mForegroundInfo.mDrawable);
17478        }
17479
17480        mForegroundInfo.mDrawable = foreground;
17481        mForegroundInfo.mBoundsChanged = true;
17482        if (foreground != null) {
17483            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17484                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17485            }
17486            foreground.setCallback(this);
17487            foreground.setLayoutDirection(getLayoutDirection());
17488            if (foreground.isStateful()) {
17489                foreground.setState(getDrawableState());
17490            }
17491            applyForegroundTint();
17492        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17493            mPrivateFlags |= PFLAG_SKIP_DRAW;
17494        }
17495        requestLayout();
17496        invalidate();
17497    }
17498
17499    /**
17500     * Magic bit used to support features of framework-internal window decor implementation details.
17501     * This used to live exclusively in FrameLayout.
17502     *
17503     * @return true if the foreground should draw inside the padding region or false
17504     *         if it should draw inset by the view's padding
17505     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17506     */
17507    public boolean isForegroundInsidePadding() {
17508        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17509    }
17510
17511    /**
17512     * Describes how the foreground is positioned.
17513     *
17514     * @return foreground gravity.
17515     *
17516     * @see #setForegroundGravity(int)
17517     *
17518     * @attr ref android.R.styleable#View_foregroundGravity
17519     */
17520    public int getForegroundGravity() {
17521        return mForegroundInfo != null ? mForegroundInfo.mGravity
17522                : Gravity.START | Gravity.TOP;
17523    }
17524
17525    /**
17526     * Describes how the foreground is positioned. Defaults to START and TOP.
17527     *
17528     * @param gravity see {@link android.view.Gravity}
17529     *
17530     * @see #getForegroundGravity()
17531     *
17532     * @attr ref android.R.styleable#View_foregroundGravity
17533     */
17534    public void setForegroundGravity(int gravity) {
17535        if (mForegroundInfo == null) {
17536            mForegroundInfo = new ForegroundInfo();
17537        }
17538
17539        if (mForegroundInfo.mGravity != gravity) {
17540            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17541                gravity |= Gravity.START;
17542            }
17543
17544            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17545                gravity |= Gravity.TOP;
17546            }
17547
17548            mForegroundInfo.mGravity = gravity;
17549            requestLayout();
17550        }
17551    }
17552
17553    /**
17554     * Applies a tint to the foreground drawable. Does not modify the current tint
17555     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17556     * <p>
17557     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17558     * mutate the drawable and apply the specified tint and tint mode using
17559     * {@link Drawable#setTintList(ColorStateList)}.
17560     *
17561     * @param tint the tint to apply, may be {@code null} to clear tint
17562     *
17563     * @attr ref android.R.styleable#View_foregroundTint
17564     * @see #getForegroundTintList()
17565     * @see Drawable#setTintList(ColorStateList)
17566     */
17567    public void setForegroundTintList(@Nullable ColorStateList tint) {
17568        if (mForegroundInfo == null) {
17569            mForegroundInfo = new ForegroundInfo();
17570        }
17571        if (mForegroundInfo.mTintInfo == null) {
17572            mForegroundInfo.mTintInfo = new TintInfo();
17573        }
17574        mForegroundInfo.mTintInfo.mTintList = tint;
17575        mForegroundInfo.mTintInfo.mHasTintList = true;
17576
17577        applyForegroundTint();
17578    }
17579
17580    /**
17581     * Return the tint applied to the foreground drawable, if specified.
17582     *
17583     * @return the tint applied to the foreground drawable
17584     * @attr ref android.R.styleable#View_foregroundTint
17585     * @see #setForegroundTintList(ColorStateList)
17586     */
17587    @Nullable
17588    public ColorStateList getForegroundTintList() {
17589        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17590                ? mForegroundInfo.mTintInfo.mTintList : null;
17591    }
17592
17593    /**
17594     * Specifies the blending mode used to apply the tint specified by
17595     * {@link #setForegroundTintList(ColorStateList)}} to the background
17596     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17597     *
17598     * @param tintMode the blending mode used to apply the tint, may be
17599     *                 {@code null} to clear tint
17600     * @attr ref android.R.styleable#View_foregroundTintMode
17601     * @see #getForegroundTintMode()
17602     * @see Drawable#setTintMode(PorterDuff.Mode)
17603     */
17604    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17605        if (mForegroundInfo == null) {
17606            mForegroundInfo = new ForegroundInfo();
17607        }
17608        if (mForegroundInfo.mTintInfo == null) {
17609            mForegroundInfo.mTintInfo = new TintInfo();
17610        }
17611        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17612        mForegroundInfo.mTintInfo.mHasTintMode = true;
17613
17614        applyForegroundTint();
17615    }
17616
17617    /**
17618     * Return the blending mode used to apply the tint to the foreground
17619     * drawable, if specified.
17620     *
17621     * @return the blending mode used to apply the tint to the foreground
17622     *         drawable
17623     * @attr ref android.R.styleable#View_foregroundTintMode
17624     * @see #setForegroundTintMode(PorterDuff.Mode)
17625     */
17626    @Nullable
17627    public PorterDuff.Mode getForegroundTintMode() {
17628        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17629                ? mForegroundInfo.mTintInfo.mTintMode : null;
17630    }
17631
17632    private void applyForegroundTint() {
17633        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17634                && mForegroundInfo.mTintInfo != null) {
17635            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17636            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17637                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17638
17639                if (tintInfo.mHasTintList) {
17640                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17641                }
17642
17643                if (tintInfo.mHasTintMode) {
17644                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17645                }
17646
17647                // The drawable (or one of its children) may not have been
17648                // stateful before applying the tint, so let's try again.
17649                if (mForegroundInfo.mDrawable.isStateful()) {
17650                    mForegroundInfo.mDrawable.setState(getDrawableState());
17651                }
17652            }
17653        }
17654    }
17655
17656    /**
17657     * Draw any foreground content for this view.
17658     *
17659     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17660     * drawable or other view-specific decorations. The foreground is drawn on top of the
17661     * primary view content.</p>
17662     *
17663     * @param canvas canvas to draw into
17664     */
17665    public void onDrawForeground(Canvas canvas) {
17666        onDrawScrollIndicators(canvas);
17667        onDrawScrollBars(canvas);
17668
17669        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17670        if (foreground != null) {
17671            if (mForegroundInfo.mBoundsChanged) {
17672                mForegroundInfo.mBoundsChanged = false;
17673                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17674                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17675
17676                if (mForegroundInfo.mInsidePadding) {
17677                    selfBounds.set(0, 0, getWidth(), getHeight());
17678                } else {
17679                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17680                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17681                }
17682
17683                final int ld = getLayoutDirection();
17684                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17685                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17686                foreground.setBounds(overlayBounds);
17687            }
17688
17689            foreground.draw(canvas);
17690        }
17691    }
17692
17693    /**
17694     * Sets the padding. The view may add on the space required to display
17695     * the scrollbars, depending on the style and visibility of the scrollbars.
17696     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17697     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17698     * from the values set in this call.
17699     *
17700     * @attr ref android.R.styleable#View_padding
17701     * @attr ref android.R.styleable#View_paddingBottom
17702     * @attr ref android.R.styleable#View_paddingLeft
17703     * @attr ref android.R.styleable#View_paddingRight
17704     * @attr ref android.R.styleable#View_paddingTop
17705     * @param left the left padding in pixels
17706     * @param top the top padding in pixels
17707     * @param right the right padding in pixels
17708     * @param bottom the bottom padding in pixels
17709     */
17710    public void setPadding(int left, int top, int right, int bottom) {
17711        resetResolvedPaddingInternal();
17712
17713        mUserPaddingStart = UNDEFINED_PADDING;
17714        mUserPaddingEnd = UNDEFINED_PADDING;
17715
17716        mUserPaddingLeftInitial = left;
17717        mUserPaddingRightInitial = right;
17718
17719        mLeftPaddingDefined = true;
17720        mRightPaddingDefined = true;
17721
17722        internalSetPadding(left, top, right, bottom);
17723    }
17724
17725    /**
17726     * @hide
17727     */
17728    protected void internalSetPadding(int left, int top, int right, int bottom) {
17729        mUserPaddingLeft = left;
17730        mUserPaddingRight = right;
17731        mUserPaddingBottom = bottom;
17732
17733        final int viewFlags = mViewFlags;
17734        boolean changed = false;
17735
17736        // Common case is there are no scroll bars.
17737        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17738            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17739                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17740                        ? 0 : getVerticalScrollbarWidth();
17741                switch (mVerticalScrollbarPosition) {
17742                    case SCROLLBAR_POSITION_DEFAULT:
17743                        if (isLayoutRtl()) {
17744                            left += offset;
17745                        } else {
17746                            right += offset;
17747                        }
17748                        break;
17749                    case SCROLLBAR_POSITION_RIGHT:
17750                        right += offset;
17751                        break;
17752                    case SCROLLBAR_POSITION_LEFT:
17753                        left += offset;
17754                        break;
17755                }
17756            }
17757            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17758                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17759                        ? 0 : getHorizontalScrollbarHeight();
17760            }
17761        }
17762
17763        if (mPaddingLeft != left) {
17764            changed = true;
17765            mPaddingLeft = left;
17766        }
17767        if (mPaddingTop != top) {
17768            changed = true;
17769            mPaddingTop = top;
17770        }
17771        if (mPaddingRight != right) {
17772            changed = true;
17773            mPaddingRight = right;
17774        }
17775        if (mPaddingBottom != bottom) {
17776            changed = true;
17777            mPaddingBottom = bottom;
17778        }
17779
17780        if (changed) {
17781            requestLayout();
17782            invalidateOutline();
17783        }
17784    }
17785
17786    /**
17787     * Sets the relative padding. The view may add on the space required to display
17788     * the scrollbars, depending on the style and visibility of the scrollbars.
17789     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17790     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17791     * from the values set in this call.
17792     *
17793     * @attr ref android.R.styleable#View_padding
17794     * @attr ref android.R.styleable#View_paddingBottom
17795     * @attr ref android.R.styleable#View_paddingStart
17796     * @attr ref android.R.styleable#View_paddingEnd
17797     * @attr ref android.R.styleable#View_paddingTop
17798     * @param start the start padding in pixels
17799     * @param top the top padding in pixels
17800     * @param end the end padding in pixels
17801     * @param bottom the bottom padding in pixels
17802     */
17803    public void setPaddingRelative(int start, int top, int end, int bottom) {
17804        resetResolvedPaddingInternal();
17805
17806        mUserPaddingStart = start;
17807        mUserPaddingEnd = end;
17808        mLeftPaddingDefined = true;
17809        mRightPaddingDefined = true;
17810
17811        switch(getLayoutDirection()) {
17812            case LAYOUT_DIRECTION_RTL:
17813                mUserPaddingLeftInitial = end;
17814                mUserPaddingRightInitial = start;
17815                internalSetPadding(end, top, start, bottom);
17816                break;
17817            case LAYOUT_DIRECTION_LTR:
17818            default:
17819                mUserPaddingLeftInitial = start;
17820                mUserPaddingRightInitial = end;
17821                internalSetPadding(start, top, end, bottom);
17822        }
17823    }
17824
17825    /**
17826     * Returns the top padding of this view.
17827     *
17828     * @return the top padding in pixels
17829     */
17830    public int getPaddingTop() {
17831        return mPaddingTop;
17832    }
17833
17834    /**
17835     * Returns the bottom padding of this view. If there are inset and enabled
17836     * scrollbars, this value may include the space required to display the
17837     * scrollbars as well.
17838     *
17839     * @return the bottom padding in pixels
17840     */
17841    public int getPaddingBottom() {
17842        return mPaddingBottom;
17843    }
17844
17845    /**
17846     * Returns the left padding of this view. If there are inset and enabled
17847     * scrollbars, this value may include the space required to display the
17848     * scrollbars as well.
17849     *
17850     * @return the left padding in pixels
17851     */
17852    public int getPaddingLeft() {
17853        if (!isPaddingResolved()) {
17854            resolvePadding();
17855        }
17856        return mPaddingLeft;
17857    }
17858
17859    /**
17860     * Returns the start padding of this view depending on its resolved layout direction.
17861     * If there are inset and enabled scrollbars, this value may include the space
17862     * required to display the scrollbars as well.
17863     *
17864     * @return the start padding in pixels
17865     */
17866    public int getPaddingStart() {
17867        if (!isPaddingResolved()) {
17868            resolvePadding();
17869        }
17870        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17871                mPaddingRight : mPaddingLeft;
17872    }
17873
17874    /**
17875     * Returns the right padding of this view. If there are inset and enabled
17876     * scrollbars, this value may include the space required to display the
17877     * scrollbars as well.
17878     *
17879     * @return the right padding in pixels
17880     */
17881    public int getPaddingRight() {
17882        if (!isPaddingResolved()) {
17883            resolvePadding();
17884        }
17885        return mPaddingRight;
17886    }
17887
17888    /**
17889     * Returns the end padding of this view depending on its resolved layout direction.
17890     * If there are inset and enabled scrollbars, this value may include the space
17891     * required to display the scrollbars as well.
17892     *
17893     * @return the end padding in pixels
17894     */
17895    public int getPaddingEnd() {
17896        if (!isPaddingResolved()) {
17897            resolvePadding();
17898        }
17899        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17900                mPaddingLeft : mPaddingRight;
17901    }
17902
17903    /**
17904     * Return if the padding has been set through relative values
17905     * {@link #setPaddingRelative(int, int, int, int)} or through
17906     * @attr ref android.R.styleable#View_paddingStart or
17907     * @attr ref android.R.styleable#View_paddingEnd
17908     *
17909     * @return true if the padding is relative or false if it is not.
17910     */
17911    public boolean isPaddingRelative() {
17912        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17913    }
17914
17915    Insets computeOpticalInsets() {
17916        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17917    }
17918
17919    /**
17920     * @hide
17921     */
17922    public void resetPaddingToInitialValues() {
17923        if (isRtlCompatibilityMode()) {
17924            mPaddingLeft = mUserPaddingLeftInitial;
17925            mPaddingRight = mUserPaddingRightInitial;
17926            return;
17927        }
17928        if (isLayoutRtl()) {
17929            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17930            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17931        } else {
17932            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17933            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17934        }
17935    }
17936
17937    /**
17938     * @hide
17939     */
17940    public Insets getOpticalInsets() {
17941        if (mLayoutInsets == null) {
17942            mLayoutInsets = computeOpticalInsets();
17943        }
17944        return mLayoutInsets;
17945    }
17946
17947    /**
17948     * Set this view's optical insets.
17949     *
17950     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17951     * property. Views that compute their own optical insets should call it as part of measurement.
17952     * This method does not request layout. If you are setting optical insets outside of
17953     * measure/layout itself you will want to call requestLayout() yourself.
17954     * </p>
17955     * @hide
17956     */
17957    public void setOpticalInsets(Insets insets) {
17958        mLayoutInsets = insets;
17959    }
17960
17961    /**
17962     * Changes the selection state of this view. A view can be selected or not.
17963     * Note that selection is not the same as focus. Views are typically
17964     * selected in the context of an AdapterView like ListView or GridView;
17965     * the selected view is the view that is highlighted.
17966     *
17967     * @param selected true if the view must be selected, false otherwise
17968     */
17969    public void setSelected(boolean selected) {
17970        //noinspection DoubleNegation
17971        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17972            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17973            if (!selected) resetPressedState();
17974            invalidate(true);
17975            refreshDrawableState();
17976            dispatchSetSelected(selected);
17977            if (selected) {
17978                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17979            } else {
17980                notifyViewAccessibilityStateChangedIfNeeded(
17981                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17982            }
17983        }
17984    }
17985
17986    /**
17987     * Dispatch setSelected to all of this View's children.
17988     *
17989     * @see #setSelected(boolean)
17990     *
17991     * @param selected The new selected state
17992     */
17993    protected void dispatchSetSelected(boolean selected) {
17994    }
17995
17996    /**
17997     * Indicates the selection state of this view.
17998     *
17999     * @return true if the view is selected, false otherwise
18000     */
18001    @ViewDebug.ExportedProperty
18002    public boolean isSelected() {
18003        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18004    }
18005
18006    /**
18007     * Changes the activated state of this view. A view can be activated or not.
18008     * Note that activation is not the same as selection.  Selection is
18009     * a transient property, representing the view (hierarchy) the user is
18010     * currently interacting with.  Activation is a longer-term state that the
18011     * user can move views in and out of.  For example, in a list view with
18012     * single or multiple selection enabled, the views in the current selection
18013     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18014     * here.)  The activated state is propagated down to children of the view it
18015     * is set on.
18016     *
18017     * @param activated true if the view must be activated, false otherwise
18018     */
18019    public void setActivated(boolean activated) {
18020        //noinspection DoubleNegation
18021        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18022            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18023            invalidate(true);
18024            refreshDrawableState();
18025            dispatchSetActivated(activated);
18026        }
18027    }
18028
18029    /**
18030     * Dispatch setActivated to all of this View's children.
18031     *
18032     * @see #setActivated(boolean)
18033     *
18034     * @param activated The new activated state
18035     */
18036    protected void dispatchSetActivated(boolean activated) {
18037    }
18038
18039    /**
18040     * Indicates the activation state of this view.
18041     *
18042     * @return true if the view is activated, false otherwise
18043     */
18044    @ViewDebug.ExportedProperty
18045    public boolean isActivated() {
18046        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18047    }
18048
18049    /**
18050     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18051     * observer can be used to get notifications when global events, like
18052     * layout, happen.
18053     *
18054     * The returned ViewTreeObserver observer is not guaranteed to remain
18055     * valid for the lifetime of this View. If the caller of this method keeps
18056     * a long-lived reference to ViewTreeObserver, it should always check for
18057     * the return value of {@link ViewTreeObserver#isAlive()}.
18058     *
18059     * @return The ViewTreeObserver for this view's hierarchy.
18060     */
18061    public ViewTreeObserver getViewTreeObserver() {
18062        if (mAttachInfo != null) {
18063            return mAttachInfo.mTreeObserver;
18064        }
18065        if (mFloatingTreeObserver == null) {
18066            mFloatingTreeObserver = new ViewTreeObserver();
18067        }
18068        return mFloatingTreeObserver;
18069    }
18070
18071    /**
18072     * <p>Finds the topmost view in the current view hierarchy.</p>
18073     *
18074     * @return the topmost view containing this view
18075     */
18076    public View getRootView() {
18077        if (mAttachInfo != null) {
18078            final View v = mAttachInfo.mRootView;
18079            if (v != null) {
18080                return v;
18081            }
18082        }
18083
18084        View parent = this;
18085
18086        while (parent.mParent != null && parent.mParent instanceof View) {
18087            parent = (View) parent.mParent;
18088        }
18089
18090        return parent;
18091    }
18092
18093    /**
18094     * Transforms a motion event from view-local coordinates to on-screen
18095     * coordinates.
18096     *
18097     * @param ev the view-local motion event
18098     * @return false if the transformation could not be applied
18099     * @hide
18100     */
18101    public boolean toGlobalMotionEvent(MotionEvent ev) {
18102        final AttachInfo info = mAttachInfo;
18103        if (info == null) {
18104            return false;
18105        }
18106
18107        final Matrix m = info.mTmpMatrix;
18108        m.set(Matrix.IDENTITY_MATRIX);
18109        transformMatrixToGlobal(m);
18110        ev.transform(m);
18111        return true;
18112    }
18113
18114    /**
18115     * Transforms a motion event from on-screen coordinates to view-local
18116     * coordinates.
18117     *
18118     * @param ev the on-screen motion event
18119     * @return false if the transformation could not be applied
18120     * @hide
18121     */
18122    public boolean toLocalMotionEvent(MotionEvent ev) {
18123        final AttachInfo info = mAttachInfo;
18124        if (info == null) {
18125            return false;
18126        }
18127
18128        final Matrix m = info.mTmpMatrix;
18129        m.set(Matrix.IDENTITY_MATRIX);
18130        transformMatrixToLocal(m);
18131        ev.transform(m);
18132        return true;
18133    }
18134
18135    /**
18136     * Modifies the input matrix such that it maps view-local coordinates to
18137     * on-screen coordinates.
18138     *
18139     * @param m input matrix to modify
18140     * @hide
18141     */
18142    public void transformMatrixToGlobal(Matrix m) {
18143        final ViewParent parent = mParent;
18144        if (parent instanceof View) {
18145            final View vp = (View) parent;
18146            vp.transformMatrixToGlobal(m);
18147            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18148        } else if (parent instanceof ViewRootImpl) {
18149            final ViewRootImpl vr = (ViewRootImpl) parent;
18150            vr.transformMatrixToGlobal(m);
18151            m.preTranslate(0, -vr.mCurScrollY);
18152        }
18153
18154        m.preTranslate(mLeft, mTop);
18155
18156        if (!hasIdentityMatrix()) {
18157            m.preConcat(getMatrix());
18158        }
18159    }
18160
18161    /**
18162     * Modifies the input matrix such that it maps on-screen coordinates to
18163     * view-local coordinates.
18164     *
18165     * @param m input matrix to modify
18166     * @hide
18167     */
18168    public void transformMatrixToLocal(Matrix m) {
18169        final ViewParent parent = mParent;
18170        if (parent instanceof View) {
18171            final View vp = (View) parent;
18172            vp.transformMatrixToLocal(m);
18173            m.postTranslate(vp.mScrollX, vp.mScrollY);
18174        } else if (parent instanceof ViewRootImpl) {
18175            final ViewRootImpl vr = (ViewRootImpl) parent;
18176            vr.transformMatrixToLocal(m);
18177            m.postTranslate(0, vr.mCurScrollY);
18178        }
18179
18180        m.postTranslate(-mLeft, -mTop);
18181
18182        if (!hasIdentityMatrix()) {
18183            m.postConcat(getInverseMatrix());
18184        }
18185    }
18186
18187    /**
18188     * @hide
18189     */
18190    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18191            @ViewDebug.IntToString(from = 0, to = "x"),
18192            @ViewDebug.IntToString(from = 1, to = "y")
18193    })
18194    public int[] getLocationOnScreen() {
18195        int[] location = new int[2];
18196        getLocationOnScreen(location);
18197        return location;
18198    }
18199
18200    /**
18201     * <p>Computes the coordinates of this view on the screen. The argument
18202     * must be an array of two integers. After the method returns, the array
18203     * contains the x and y location in that order.</p>
18204     *
18205     * @param location an array of two integers in which to hold the coordinates
18206     */
18207    public void getLocationOnScreen(@Size(2) int[] location) {
18208        getLocationInWindow(location);
18209
18210        final AttachInfo info = mAttachInfo;
18211        if (info != null) {
18212            location[0] += info.mWindowLeft;
18213            location[1] += info.mWindowTop;
18214        }
18215    }
18216
18217    /**
18218     * <p>Computes the coordinates of this view in its window. The argument
18219     * must be an array of two integers. After the method returns, the array
18220     * contains the x and y location in that order.</p>
18221     *
18222     * @param location an array of two integers in which to hold the coordinates
18223     */
18224    public void getLocationInWindow(@Size(2) int[] location) {
18225        if (location == null || location.length < 2) {
18226            throw new IllegalArgumentException("location must be an array of two integers");
18227        }
18228
18229        if (mAttachInfo == null) {
18230            // When the view is not attached to a window, this method does not make sense
18231            location[0] = location[1] = 0;
18232            return;
18233        }
18234
18235        float[] position = mAttachInfo.mTmpTransformLocation;
18236        position[0] = position[1] = 0.0f;
18237
18238        if (!hasIdentityMatrix()) {
18239            getMatrix().mapPoints(position);
18240        }
18241
18242        position[0] += mLeft;
18243        position[1] += mTop;
18244
18245        ViewParent viewParent = mParent;
18246        while (viewParent instanceof View) {
18247            final View view = (View) viewParent;
18248
18249            position[0] -= view.mScrollX;
18250            position[1] -= view.mScrollY;
18251
18252            if (!view.hasIdentityMatrix()) {
18253                view.getMatrix().mapPoints(position);
18254            }
18255
18256            position[0] += view.mLeft;
18257            position[1] += view.mTop;
18258
18259            viewParent = view.mParent;
18260         }
18261
18262        if (viewParent instanceof ViewRootImpl) {
18263            // *cough*
18264            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18265            position[1] -= vr.mCurScrollY;
18266        }
18267
18268        location[0] = (int) (position[0] + 0.5f);
18269        location[1] = (int) (position[1] + 0.5f);
18270    }
18271
18272    /**
18273     * {@hide}
18274     * @param id the id of the view to be found
18275     * @return the view of the specified id, null if cannot be found
18276     */
18277    protected View findViewTraversal(@IdRes int id) {
18278        if (id == mID) {
18279            return this;
18280        }
18281        return null;
18282    }
18283
18284    /**
18285     * {@hide}
18286     * @param tag the tag of the view to be found
18287     * @return the view of specified tag, null if cannot be found
18288     */
18289    protected View findViewWithTagTraversal(Object tag) {
18290        if (tag != null && tag.equals(mTag)) {
18291            return this;
18292        }
18293        return null;
18294    }
18295
18296    /**
18297     * {@hide}
18298     * @param predicate The predicate to evaluate.
18299     * @param childToSkip If not null, ignores this child during the recursive traversal.
18300     * @return The first view that matches the predicate or null.
18301     */
18302    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18303        if (predicate.apply(this)) {
18304            return this;
18305        }
18306        return null;
18307    }
18308
18309    /**
18310     * Look for a child view with the given id.  If this view has the given
18311     * id, return this view.
18312     *
18313     * @param id The id to search for.
18314     * @return The view that has the given id in the hierarchy or null
18315     */
18316    @Nullable
18317    public final View findViewById(@IdRes int id) {
18318        if (id < 0) {
18319            return null;
18320        }
18321        return findViewTraversal(id);
18322    }
18323
18324    /**
18325     * Finds a view by its unuque and stable accessibility id.
18326     *
18327     * @param accessibilityId The searched accessibility id.
18328     * @return The found view.
18329     */
18330    final View findViewByAccessibilityId(int accessibilityId) {
18331        if (accessibilityId < 0) {
18332            return null;
18333        }
18334        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18335        if (view != null) {
18336            return view.includeForAccessibility() ? view : null;
18337        }
18338        return null;
18339    }
18340
18341    /**
18342     * Performs the traversal to find a view by its unuque and stable accessibility id.
18343     *
18344     * <strong>Note:</strong>This method does not stop at the root namespace
18345     * boundary since the user can touch the screen at an arbitrary location
18346     * potentially crossing the root namespace bounday which will send an
18347     * accessibility event to accessibility services and they should be able
18348     * to obtain the event source. Also accessibility ids are guaranteed to be
18349     * unique in the window.
18350     *
18351     * @param accessibilityId The accessibility id.
18352     * @return The found view.
18353     *
18354     * @hide
18355     */
18356    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18357        if (getAccessibilityViewId() == accessibilityId) {
18358            return this;
18359        }
18360        return null;
18361    }
18362
18363    /**
18364     * Look for a child view with the given tag.  If this view has the given
18365     * tag, return this view.
18366     *
18367     * @param tag The tag to search for, using "tag.equals(getTag())".
18368     * @return The View that has the given tag in the hierarchy or null
18369     */
18370    public final View findViewWithTag(Object tag) {
18371        if (tag == null) {
18372            return null;
18373        }
18374        return findViewWithTagTraversal(tag);
18375    }
18376
18377    /**
18378     * {@hide}
18379     * Look for a child view that matches the specified predicate.
18380     * If this view matches the predicate, return this view.
18381     *
18382     * @param predicate The predicate to evaluate.
18383     * @return The first view that matches the predicate or null.
18384     */
18385    public final View findViewByPredicate(Predicate<View> predicate) {
18386        return findViewByPredicateTraversal(predicate, null);
18387    }
18388
18389    /**
18390     * {@hide}
18391     * Look for a child view that matches the specified predicate,
18392     * starting with the specified view and its descendents and then
18393     * recusively searching the ancestors and siblings of that view
18394     * until this view is reached.
18395     *
18396     * This method is useful in cases where the predicate does not match
18397     * a single unique view (perhaps multiple views use the same id)
18398     * and we are trying to find the view that is "closest" in scope to the
18399     * starting view.
18400     *
18401     * @param start The view to start from.
18402     * @param predicate The predicate to evaluate.
18403     * @return The first view that matches the predicate or null.
18404     */
18405    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18406        View childToSkip = null;
18407        for (;;) {
18408            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18409            if (view != null || start == this) {
18410                return view;
18411            }
18412
18413            ViewParent parent = start.getParent();
18414            if (parent == null || !(parent instanceof View)) {
18415                return null;
18416            }
18417
18418            childToSkip = start;
18419            start = (View) parent;
18420        }
18421    }
18422
18423    /**
18424     * Sets the identifier for this view. The identifier does not have to be
18425     * unique in this view's hierarchy. The identifier should be a positive
18426     * number.
18427     *
18428     * @see #NO_ID
18429     * @see #getId()
18430     * @see #findViewById(int)
18431     *
18432     * @param id a number used to identify the view
18433     *
18434     * @attr ref android.R.styleable#View_id
18435     */
18436    public void setId(@IdRes int id) {
18437        mID = id;
18438        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18439            mID = generateViewId();
18440        }
18441    }
18442
18443    /**
18444     * {@hide}
18445     *
18446     * @param isRoot true if the view belongs to the root namespace, false
18447     *        otherwise
18448     */
18449    public void setIsRootNamespace(boolean isRoot) {
18450        if (isRoot) {
18451            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18452        } else {
18453            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18454        }
18455    }
18456
18457    /**
18458     * {@hide}
18459     *
18460     * @return true if the view belongs to the root namespace, false otherwise
18461     */
18462    public boolean isRootNamespace() {
18463        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18464    }
18465
18466    /**
18467     * Returns this view's identifier.
18468     *
18469     * @return a positive integer used to identify the view or {@link #NO_ID}
18470     *         if the view has no ID
18471     *
18472     * @see #setId(int)
18473     * @see #findViewById(int)
18474     * @attr ref android.R.styleable#View_id
18475     */
18476    @IdRes
18477    @ViewDebug.CapturedViewProperty
18478    public int getId() {
18479        return mID;
18480    }
18481
18482    /**
18483     * Returns this view's tag.
18484     *
18485     * @return the Object stored in this view as a tag, or {@code null} if not
18486     *         set
18487     *
18488     * @see #setTag(Object)
18489     * @see #getTag(int)
18490     */
18491    @ViewDebug.ExportedProperty
18492    public Object getTag() {
18493        return mTag;
18494    }
18495
18496    /**
18497     * Sets the tag associated with this view. A tag can be used to mark
18498     * a view in its hierarchy and does not have to be unique within the
18499     * hierarchy. Tags can also be used to store data within a view without
18500     * resorting to another data structure.
18501     *
18502     * @param tag an Object to tag the view with
18503     *
18504     * @see #getTag()
18505     * @see #setTag(int, Object)
18506     */
18507    public void setTag(final Object tag) {
18508        mTag = tag;
18509    }
18510
18511    /**
18512     * Returns the tag associated with this view and the specified key.
18513     *
18514     * @param key The key identifying the tag
18515     *
18516     * @return the Object stored in this view as a tag, or {@code null} if not
18517     *         set
18518     *
18519     * @see #setTag(int, Object)
18520     * @see #getTag()
18521     */
18522    public Object getTag(int key) {
18523        if (mKeyedTags != null) return mKeyedTags.get(key);
18524        return null;
18525    }
18526
18527    /**
18528     * Sets a tag associated with this view and a key. A tag can be used
18529     * to mark a view in its hierarchy and does not have to be unique within
18530     * the hierarchy. Tags can also be used to store data within a view
18531     * without resorting to another data structure.
18532     *
18533     * The specified key should be an id declared in the resources of the
18534     * application to ensure it is unique (see the <a
18535     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18536     * Keys identified as belonging to
18537     * the Android framework or not associated with any package will cause
18538     * an {@link IllegalArgumentException} to be thrown.
18539     *
18540     * @param key The key identifying the tag
18541     * @param tag An Object to tag the view with
18542     *
18543     * @throws IllegalArgumentException If they specified key is not valid
18544     *
18545     * @see #setTag(Object)
18546     * @see #getTag(int)
18547     */
18548    public void setTag(int key, final Object tag) {
18549        // If the package id is 0x00 or 0x01, it's either an undefined package
18550        // or a framework id
18551        if ((key >>> 24) < 2) {
18552            throw new IllegalArgumentException("The key must be an application-specific "
18553                    + "resource id.");
18554        }
18555
18556        setKeyedTag(key, tag);
18557    }
18558
18559    /**
18560     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18561     * framework id.
18562     *
18563     * @hide
18564     */
18565    public void setTagInternal(int key, Object tag) {
18566        if ((key >>> 24) != 0x1) {
18567            throw new IllegalArgumentException("The key must be a framework-specific "
18568                    + "resource id.");
18569        }
18570
18571        setKeyedTag(key, tag);
18572    }
18573
18574    private void setKeyedTag(int key, Object tag) {
18575        if (mKeyedTags == null) {
18576            mKeyedTags = new SparseArray<Object>(2);
18577        }
18578
18579        mKeyedTags.put(key, tag);
18580    }
18581
18582    /**
18583     * Prints information about this view in the log output, with the tag
18584     * {@link #VIEW_LOG_TAG}.
18585     *
18586     * @hide
18587     */
18588    public void debug() {
18589        debug(0);
18590    }
18591
18592    /**
18593     * Prints information about this view in the log output, with the tag
18594     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18595     * indentation defined by the <code>depth</code>.
18596     *
18597     * @param depth the indentation level
18598     *
18599     * @hide
18600     */
18601    protected void debug(int depth) {
18602        String output = debugIndent(depth - 1);
18603
18604        output += "+ " + this;
18605        int id = getId();
18606        if (id != -1) {
18607            output += " (id=" + id + ")";
18608        }
18609        Object tag = getTag();
18610        if (tag != null) {
18611            output += " (tag=" + tag + ")";
18612        }
18613        Log.d(VIEW_LOG_TAG, output);
18614
18615        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18616            output = debugIndent(depth) + " FOCUSED";
18617            Log.d(VIEW_LOG_TAG, output);
18618        }
18619
18620        output = debugIndent(depth);
18621        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18622                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18623                + "} ";
18624        Log.d(VIEW_LOG_TAG, output);
18625
18626        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18627                || mPaddingBottom != 0) {
18628            output = debugIndent(depth);
18629            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18630                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18631            Log.d(VIEW_LOG_TAG, output);
18632        }
18633
18634        output = debugIndent(depth);
18635        output += "mMeasureWidth=" + mMeasuredWidth +
18636                " mMeasureHeight=" + mMeasuredHeight;
18637        Log.d(VIEW_LOG_TAG, output);
18638
18639        output = debugIndent(depth);
18640        if (mLayoutParams == null) {
18641            output += "BAD! no layout params";
18642        } else {
18643            output = mLayoutParams.debug(output);
18644        }
18645        Log.d(VIEW_LOG_TAG, output);
18646
18647        output = debugIndent(depth);
18648        output += "flags={";
18649        output += View.printFlags(mViewFlags);
18650        output += "}";
18651        Log.d(VIEW_LOG_TAG, output);
18652
18653        output = debugIndent(depth);
18654        output += "privateFlags={";
18655        output += View.printPrivateFlags(mPrivateFlags);
18656        output += "}";
18657        Log.d(VIEW_LOG_TAG, output);
18658    }
18659
18660    /**
18661     * Creates a string of whitespaces used for indentation.
18662     *
18663     * @param depth the indentation level
18664     * @return a String containing (depth * 2 + 3) * 2 white spaces
18665     *
18666     * @hide
18667     */
18668    protected static String debugIndent(int depth) {
18669        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18670        for (int i = 0; i < (depth * 2) + 3; i++) {
18671            spaces.append(' ').append(' ');
18672        }
18673        return spaces.toString();
18674    }
18675
18676    /**
18677     * <p>Return the offset of the widget's text baseline from the widget's top
18678     * boundary. If this widget does not support baseline alignment, this
18679     * method returns -1. </p>
18680     *
18681     * @return the offset of the baseline within the widget's bounds or -1
18682     *         if baseline alignment is not supported
18683     */
18684    @ViewDebug.ExportedProperty(category = "layout")
18685    public int getBaseline() {
18686        return -1;
18687    }
18688
18689    /**
18690     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18691     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18692     * a layout pass.
18693     *
18694     * @return whether the view hierarchy is currently undergoing a layout pass
18695     */
18696    public boolean isInLayout() {
18697        ViewRootImpl viewRoot = getViewRootImpl();
18698        return (viewRoot != null && viewRoot.isInLayout());
18699    }
18700
18701    /**
18702     * Call this when something has changed which has invalidated the
18703     * layout of this view. This will schedule a layout pass of the view
18704     * tree. This should not be called while the view hierarchy is currently in a layout
18705     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18706     * end of the current layout pass (and then layout will run again) or after the current
18707     * frame is drawn and the next layout occurs.
18708     *
18709     * <p>Subclasses which override this method should call the superclass method to
18710     * handle possible request-during-layout errors correctly.</p>
18711     */
18712    @CallSuper
18713    public void requestLayout() {
18714        if (mMeasureCache != null) mMeasureCache.clear();
18715
18716        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18717            // Only trigger request-during-layout logic if this is the view requesting it,
18718            // not the views in its parent hierarchy
18719            ViewRootImpl viewRoot = getViewRootImpl();
18720            if (viewRoot != null && viewRoot.isInLayout()) {
18721                if (!viewRoot.requestLayoutDuringLayout(this)) {
18722                    return;
18723                }
18724            }
18725            mAttachInfo.mViewRequestingLayout = this;
18726        }
18727
18728        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18729        mPrivateFlags |= PFLAG_INVALIDATED;
18730
18731        if (mParent != null && !mParent.isLayoutRequested()) {
18732            mParent.requestLayout();
18733        }
18734        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18735            mAttachInfo.mViewRequestingLayout = null;
18736        }
18737    }
18738
18739    /**
18740     * Forces this view to be laid out during the next layout pass.
18741     * This method does not call requestLayout() or forceLayout()
18742     * on the parent.
18743     */
18744    public void forceLayout() {
18745        if (mMeasureCache != null) mMeasureCache.clear();
18746
18747        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18748        mPrivateFlags |= PFLAG_INVALIDATED;
18749    }
18750
18751    /**
18752     * <p>
18753     * This is called to find out how big a view should be. The parent
18754     * supplies constraint information in the width and height parameters.
18755     * </p>
18756     *
18757     * <p>
18758     * The actual measurement work of a view is performed in
18759     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18760     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18761     * </p>
18762     *
18763     *
18764     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18765     *        parent
18766     * @param heightMeasureSpec Vertical space requirements as imposed by the
18767     *        parent
18768     *
18769     * @see #onMeasure(int, int)
18770     */
18771    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18772        boolean optical = isLayoutModeOptical(this);
18773        if (optical != isLayoutModeOptical(mParent)) {
18774            Insets insets = getOpticalInsets();
18775            int oWidth  = insets.left + insets.right;
18776            int oHeight = insets.top  + insets.bottom;
18777            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18778            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18779        }
18780
18781        // Suppress sign extension for the low bytes
18782        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18783        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18784
18785        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
18786
18787        // Optimize layout by avoiding an extra EXACTLY pass when the view is
18788        // already measured as the correct size. In API 23 and below, this
18789        // extra pass is required to make LinearLayout re-distribute weight.
18790        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
18791                || heightMeasureSpec != mOldHeightMeasureSpec;
18792        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
18793                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
18794        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
18795                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
18796        final boolean needsLayout = specChanged
18797                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
18798
18799        if (forceLayout || needsLayout) {
18800            // first clears the measured dimension flag
18801            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18802
18803            resolveRtlPropertiesIfNeeded();
18804
18805            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
18806            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18807                // measure ourselves, this should set the measured dimension flag back
18808                onMeasure(widthMeasureSpec, heightMeasureSpec);
18809                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18810            } else {
18811                long value = mMeasureCache.valueAt(cacheIndex);
18812                // Casting a long to int drops the high 32 bits, no mask needed
18813                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18814                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18815            }
18816
18817            // flag not set, setMeasuredDimension() was not invoked, we raise
18818            // an exception to warn the developer
18819            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18820                throw new IllegalStateException("View with id " + getId() + ": "
18821                        + getClass().getName() + "#onMeasure() did not set the"
18822                        + " measured dimension by calling"
18823                        + " setMeasuredDimension()");
18824            }
18825
18826            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18827        }
18828
18829        mOldWidthMeasureSpec = widthMeasureSpec;
18830        mOldHeightMeasureSpec = heightMeasureSpec;
18831
18832        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18833                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18834    }
18835
18836    /**
18837     * <p>
18838     * Measure the view and its content to determine the measured width and the
18839     * measured height. This method is invoked by {@link #measure(int, int)} and
18840     * should be overridden by subclasses to provide accurate and efficient
18841     * measurement of their contents.
18842     * </p>
18843     *
18844     * <p>
18845     * <strong>CONTRACT:</strong> When overriding this method, you
18846     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18847     * measured width and height of this view. Failure to do so will trigger an
18848     * <code>IllegalStateException</code>, thrown by
18849     * {@link #measure(int, int)}. Calling the superclass'
18850     * {@link #onMeasure(int, int)} is a valid use.
18851     * </p>
18852     *
18853     * <p>
18854     * The base class implementation of measure defaults to the background size,
18855     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18856     * override {@link #onMeasure(int, int)} to provide better measurements of
18857     * their content.
18858     * </p>
18859     *
18860     * <p>
18861     * If this method is overridden, it is the subclass's responsibility to make
18862     * sure the measured height and width are at least the view's minimum height
18863     * and width ({@link #getSuggestedMinimumHeight()} and
18864     * {@link #getSuggestedMinimumWidth()}).
18865     * </p>
18866     *
18867     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18868     *                         The requirements are encoded with
18869     *                         {@link android.view.View.MeasureSpec}.
18870     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18871     *                         The requirements are encoded with
18872     *                         {@link android.view.View.MeasureSpec}.
18873     *
18874     * @see #getMeasuredWidth()
18875     * @see #getMeasuredHeight()
18876     * @see #setMeasuredDimension(int, int)
18877     * @see #getSuggestedMinimumHeight()
18878     * @see #getSuggestedMinimumWidth()
18879     * @see android.view.View.MeasureSpec#getMode(int)
18880     * @see android.view.View.MeasureSpec#getSize(int)
18881     */
18882    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18883        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18884                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18885    }
18886
18887    /**
18888     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18889     * measured width and measured height. Failing to do so will trigger an
18890     * exception at measurement time.</p>
18891     *
18892     * @param measuredWidth The measured width of this view.  May be a complex
18893     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18894     * {@link #MEASURED_STATE_TOO_SMALL}.
18895     * @param measuredHeight The measured height of this view.  May be a complex
18896     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18897     * {@link #MEASURED_STATE_TOO_SMALL}.
18898     */
18899    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18900        boolean optical = isLayoutModeOptical(this);
18901        if (optical != isLayoutModeOptical(mParent)) {
18902            Insets insets = getOpticalInsets();
18903            int opticalWidth  = insets.left + insets.right;
18904            int opticalHeight = insets.top  + insets.bottom;
18905
18906            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18907            measuredHeight += optical ? opticalHeight : -opticalHeight;
18908        }
18909        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18910    }
18911
18912    /**
18913     * Sets the measured dimension without extra processing for things like optical bounds.
18914     * Useful for reapplying consistent values that have already been cooked with adjustments
18915     * for optical bounds, etc. such as those from the measurement cache.
18916     *
18917     * @param measuredWidth The measured width of this view.  May be a complex
18918     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18919     * {@link #MEASURED_STATE_TOO_SMALL}.
18920     * @param measuredHeight The measured height of this view.  May be a complex
18921     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18922     * {@link #MEASURED_STATE_TOO_SMALL}.
18923     */
18924    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18925        mMeasuredWidth = measuredWidth;
18926        mMeasuredHeight = measuredHeight;
18927
18928        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18929    }
18930
18931    /**
18932     * Merge two states as returned by {@link #getMeasuredState()}.
18933     * @param curState The current state as returned from a view or the result
18934     * of combining multiple views.
18935     * @param newState The new view state to combine.
18936     * @return Returns a new integer reflecting the combination of the two
18937     * states.
18938     */
18939    public static int combineMeasuredStates(int curState, int newState) {
18940        return curState | newState;
18941    }
18942
18943    /**
18944     * Version of {@link #resolveSizeAndState(int, int, int)}
18945     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18946     */
18947    public static int resolveSize(int size, int measureSpec) {
18948        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18949    }
18950
18951    /**
18952     * Utility to reconcile a desired size and state, with constraints imposed
18953     * by a MeasureSpec. Will take the desired size, unless a different size
18954     * is imposed by the constraints. The returned value is a compound integer,
18955     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18956     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18957     * resulting size is smaller than the size the view wants to be.
18958     *
18959     * @param size How big the view wants to be.
18960     * @param measureSpec Constraints imposed by the parent.
18961     * @param childMeasuredState Size information bit mask for the view's
18962     *                           children.
18963     * @return Size information bit mask as defined by
18964     *         {@link #MEASURED_SIZE_MASK} and
18965     *         {@link #MEASURED_STATE_TOO_SMALL}.
18966     */
18967    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18968        final int specMode = MeasureSpec.getMode(measureSpec);
18969        final int specSize = MeasureSpec.getSize(measureSpec);
18970        final int result;
18971        switch (specMode) {
18972            case MeasureSpec.AT_MOST:
18973                if (specSize < size) {
18974                    result = specSize | MEASURED_STATE_TOO_SMALL;
18975                } else {
18976                    result = size;
18977                }
18978                break;
18979            case MeasureSpec.EXACTLY:
18980                result = specSize;
18981                break;
18982            case MeasureSpec.UNSPECIFIED:
18983            default:
18984                result = size;
18985        }
18986        return result | (childMeasuredState & MEASURED_STATE_MASK);
18987    }
18988
18989    /**
18990     * Utility to return a default size. Uses the supplied size if the
18991     * MeasureSpec imposed no constraints. Will get larger if allowed
18992     * by the MeasureSpec.
18993     *
18994     * @param size Default size for this view
18995     * @param measureSpec Constraints imposed by the parent
18996     * @return The size this view should be.
18997     */
18998    public static int getDefaultSize(int size, int measureSpec) {
18999        int result = size;
19000        int specMode = MeasureSpec.getMode(measureSpec);
19001        int specSize = MeasureSpec.getSize(measureSpec);
19002
19003        switch (specMode) {
19004        case MeasureSpec.UNSPECIFIED:
19005            result = size;
19006            break;
19007        case MeasureSpec.AT_MOST:
19008        case MeasureSpec.EXACTLY:
19009            result = specSize;
19010            break;
19011        }
19012        return result;
19013    }
19014
19015    /**
19016     * Returns the suggested minimum height that the view should use. This
19017     * returns the maximum of the view's minimum height
19018     * and the background's minimum height
19019     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19020     * <p>
19021     * When being used in {@link #onMeasure(int, int)}, the caller should still
19022     * ensure the returned height is within the requirements of the parent.
19023     *
19024     * @return The suggested minimum height of the view.
19025     */
19026    protected int getSuggestedMinimumHeight() {
19027        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19028
19029    }
19030
19031    /**
19032     * Returns the suggested minimum width that the view should use. This
19033     * returns the maximum of the view's minimum width
19034     * and the background's minimum width
19035     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19036     * <p>
19037     * When being used in {@link #onMeasure(int, int)}, the caller should still
19038     * ensure the returned width is within the requirements of the parent.
19039     *
19040     * @return The suggested minimum width of the view.
19041     */
19042    protected int getSuggestedMinimumWidth() {
19043        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19044    }
19045
19046    /**
19047     * Returns the minimum height of the view.
19048     *
19049     * @return the minimum height the view will try to be.
19050     *
19051     * @see #setMinimumHeight(int)
19052     *
19053     * @attr ref android.R.styleable#View_minHeight
19054     */
19055    public int getMinimumHeight() {
19056        return mMinHeight;
19057    }
19058
19059    /**
19060     * Sets the minimum height of the view. It is not guaranteed the view will
19061     * be able to achieve this minimum height (for example, if its parent layout
19062     * constrains it with less available height).
19063     *
19064     * @param minHeight The minimum height the view will try to be.
19065     *
19066     * @see #getMinimumHeight()
19067     *
19068     * @attr ref android.R.styleable#View_minHeight
19069     */
19070    public void setMinimumHeight(int minHeight) {
19071        mMinHeight = minHeight;
19072        requestLayout();
19073    }
19074
19075    /**
19076     * Returns the minimum width of the view.
19077     *
19078     * @return the minimum width the view will try to be.
19079     *
19080     * @see #setMinimumWidth(int)
19081     *
19082     * @attr ref android.R.styleable#View_minWidth
19083     */
19084    public int getMinimumWidth() {
19085        return mMinWidth;
19086    }
19087
19088    /**
19089     * Sets the minimum width of the view. It is not guaranteed the view will
19090     * be able to achieve this minimum width (for example, if its parent layout
19091     * constrains it with less available width).
19092     *
19093     * @param minWidth The minimum width the view will try to be.
19094     *
19095     * @see #getMinimumWidth()
19096     *
19097     * @attr ref android.R.styleable#View_minWidth
19098     */
19099    public void setMinimumWidth(int minWidth) {
19100        mMinWidth = minWidth;
19101        requestLayout();
19102
19103    }
19104
19105    /**
19106     * Get the animation currently associated with this view.
19107     *
19108     * @return The animation that is currently playing or
19109     *         scheduled to play for this view.
19110     */
19111    public Animation getAnimation() {
19112        return mCurrentAnimation;
19113    }
19114
19115    /**
19116     * Start the specified animation now.
19117     *
19118     * @param animation the animation to start now
19119     */
19120    public void startAnimation(Animation animation) {
19121        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19122        setAnimation(animation);
19123        invalidateParentCaches();
19124        invalidate(true);
19125    }
19126
19127    /**
19128     * Cancels any animations for this view.
19129     */
19130    public void clearAnimation() {
19131        if (mCurrentAnimation != null) {
19132            mCurrentAnimation.detach();
19133        }
19134        mCurrentAnimation = null;
19135        invalidateParentIfNeeded();
19136    }
19137
19138    /**
19139     * Sets the next animation to play for this view.
19140     * If you want the animation to play immediately, use
19141     * {@link #startAnimation(android.view.animation.Animation)} instead.
19142     * This method provides allows fine-grained
19143     * control over the start time and invalidation, but you
19144     * must make sure that 1) the animation has a start time set, and
19145     * 2) the view's parent (which controls animations on its children)
19146     * will be invalidated when the animation is supposed to
19147     * start.
19148     *
19149     * @param animation The next animation, or null.
19150     */
19151    public void setAnimation(Animation animation) {
19152        mCurrentAnimation = animation;
19153
19154        if (animation != null) {
19155            // If the screen is off assume the animation start time is now instead of
19156            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19157            // would cause the animation to start when the screen turns back on
19158            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19159                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19160                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19161            }
19162            animation.reset();
19163        }
19164    }
19165
19166    /**
19167     * Invoked by a parent ViewGroup to notify the start of the animation
19168     * currently associated with this view. If you override this method,
19169     * always call super.onAnimationStart();
19170     *
19171     * @see #setAnimation(android.view.animation.Animation)
19172     * @see #getAnimation()
19173     */
19174    @CallSuper
19175    protected void onAnimationStart() {
19176        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19177    }
19178
19179    /**
19180     * Invoked by a parent ViewGroup to notify the end of the animation
19181     * currently associated with this view. If you override this method,
19182     * always call super.onAnimationEnd();
19183     *
19184     * @see #setAnimation(android.view.animation.Animation)
19185     * @see #getAnimation()
19186     */
19187    @CallSuper
19188    protected void onAnimationEnd() {
19189        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19190    }
19191
19192    /**
19193     * Invoked if there is a Transform that involves alpha. Subclass that can
19194     * draw themselves with the specified alpha should return true, and then
19195     * respect that alpha when their onDraw() is called. If this returns false
19196     * then the view may be redirected to draw into an offscreen buffer to
19197     * fulfill the request, which will look fine, but may be slower than if the
19198     * subclass handles it internally. The default implementation returns false.
19199     *
19200     * @param alpha The alpha (0..255) to apply to the view's drawing
19201     * @return true if the view can draw with the specified alpha.
19202     */
19203    protected boolean onSetAlpha(int alpha) {
19204        return false;
19205    }
19206
19207    /**
19208     * This is used by the RootView to perform an optimization when
19209     * the view hierarchy contains one or several SurfaceView.
19210     * SurfaceView is always considered transparent, but its children are not,
19211     * therefore all View objects remove themselves from the global transparent
19212     * region (passed as a parameter to this function).
19213     *
19214     * @param region The transparent region for this ViewAncestor (window).
19215     *
19216     * @return Returns true if the effective visibility of the view at this
19217     * point is opaque, regardless of the transparent region; returns false
19218     * if it is possible for underlying windows to be seen behind the view.
19219     *
19220     * {@hide}
19221     */
19222    public boolean gatherTransparentRegion(Region region) {
19223        final AttachInfo attachInfo = mAttachInfo;
19224        if (region != null && attachInfo != null) {
19225            final int pflags = mPrivateFlags;
19226            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19227                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19228                // remove it from the transparent region.
19229                final int[] location = attachInfo.mTransparentLocation;
19230                getLocationInWindow(location);
19231                region.op(location[0], location[1], location[0] + mRight - mLeft,
19232                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19233            } else {
19234                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19235                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19236                    // the background drawable's non-transparent parts from this transparent region.
19237                    applyDrawableToTransparentRegion(mBackground, region);
19238                }
19239                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19240                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19241                    // Similarly, we remove the foreground drawable's non-transparent parts.
19242                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19243                }
19244            }
19245        }
19246        return true;
19247    }
19248
19249    /**
19250     * Play a sound effect for this view.
19251     *
19252     * <p>The framework will play sound effects for some built in actions, such as
19253     * clicking, but you may wish to play these effects in your widget,
19254     * for instance, for internal navigation.
19255     *
19256     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19257     * {@link #isSoundEffectsEnabled()} is true.
19258     *
19259     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19260     */
19261    public void playSoundEffect(int soundConstant) {
19262        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19263            return;
19264        }
19265        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19266    }
19267
19268    /**
19269     * BZZZTT!!1!
19270     *
19271     * <p>Provide haptic feedback to the user for this view.
19272     *
19273     * <p>The framework will provide haptic feedback for some built in actions,
19274     * such as long presses, but you may wish to provide feedback for your
19275     * own widget.
19276     *
19277     * <p>The feedback will only be performed if
19278     * {@link #isHapticFeedbackEnabled()} is true.
19279     *
19280     * @param feedbackConstant One of the constants defined in
19281     * {@link HapticFeedbackConstants}
19282     */
19283    public boolean performHapticFeedback(int feedbackConstant) {
19284        return performHapticFeedback(feedbackConstant, 0);
19285    }
19286
19287    /**
19288     * BZZZTT!!1!
19289     *
19290     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19291     *
19292     * @param feedbackConstant One of the constants defined in
19293     * {@link HapticFeedbackConstants}
19294     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19295     */
19296    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19297        if (mAttachInfo == null) {
19298            return false;
19299        }
19300        //noinspection SimplifiableIfStatement
19301        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19302                && !isHapticFeedbackEnabled()) {
19303            return false;
19304        }
19305        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19306                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19307    }
19308
19309    /**
19310     * Request that the visibility of the status bar or other screen/window
19311     * decorations be changed.
19312     *
19313     * <p>This method is used to put the over device UI into temporary modes
19314     * where the user's attention is focused more on the application content,
19315     * by dimming or hiding surrounding system affordances.  This is typically
19316     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19317     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19318     * to be placed behind the action bar (and with these flags other system
19319     * affordances) so that smooth transitions between hiding and showing them
19320     * can be done.
19321     *
19322     * <p>Two representative examples of the use of system UI visibility is
19323     * implementing a content browsing application (like a magazine reader)
19324     * and a video playing application.
19325     *
19326     * <p>The first code shows a typical implementation of a View in a content
19327     * browsing application.  In this implementation, the application goes
19328     * into a content-oriented mode by hiding the status bar and action bar,
19329     * and putting the navigation elements into lights out mode.  The user can
19330     * then interact with content while in this mode.  Such an application should
19331     * provide an easy way for the user to toggle out of the mode (such as to
19332     * check information in the status bar or access notifications).  In the
19333     * implementation here, this is done simply by tapping on the content.
19334     *
19335     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19336     *      content}
19337     *
19338     * <p>This second code sample shows a typical implementation of a View
19339     * in a video playing application.  In this situation, while the video is
19340     * playing the application would like to go into a complete full-screen mode,
19341     * to use as much of the display as possible for the video.  When in this state
19342     * the user can not interact with the application; the system intercepts
19343     * touching on the screen to pop the UI out of full screen mode.  See
19344     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19345     *
19346     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19347     *      content}
19348     *
19349     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19350     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19351     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19352     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19353     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19354     */
19355    public void setSystemUiVisibility(int visibility) {
19356        if (visibility != mSystemUiVisibility) {
19357            mSystemUiVisibility = visibility;
19358            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19359                mParent.recomputeViewAttributes(this);
19360            }
19361        }
19362    }
19363
19364    /**
19365     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19366     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19367     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19368     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19369     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19370     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19371     */
19372    public int getSystemUiVisibility() {
19373        return mSystemUiVisibility;
19374    }
19375
19376    /**
19377     * Returns the current system UI visibility that is currently set for
19378     * the entire window.  This is the combination of the
19379     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19380     * views in the window.
19381     */
19382    public int getWindowSystemUiVisibility() {
19383        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19384    }
19385
19386    /**
19387     * Override to find out when the window's requested system UI visibility
19388     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19389     * This is different from the callbacks received through
19390     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19391     * in that this is only telling you about the local request of the window,
19392     * not the actual values applied by the system.
19393     */
19394    public void onWindowSystemUiVisibilityChanged(int visible) {
19395    }
19396
19397    /**
19398     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19399     * the view hierarchy.
19400     */
19401    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19402        onWindowSystemUiVisibilityChanged(visible);
19403    }
19404
19405    /**
19406     * Set a listener to receive callbacks when the visibility of the system bar changes.
19407     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19408     */
19409    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19410        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19411        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19412            mParent.recomputeViewAttributes(this);
19413        }
19414    }
19415
19416    /**
19417     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19418     * the view hierarchy.
19419     */
19420    public void dispatchSystemUiVisibilityChanged(int visibility) {
19421        ListenerInfo li = mListenerInfo;
19422        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19423            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19424                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19425        }
19426    }
19427
19428    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19429        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19430        if (val != mSystemUiVisibility) {
19431            setSystemUiVisibility(val);
19432            return true;
19433        }
19434        return false;
19435    }
19436
19437    /** @hide */
19438    public void setDisabledSystemUiVisibility(int flags) {
19439        if (mAttachInfo != null) {
19440            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19441                mAttachInfo.mDisabledSystemUiVisibility = flags;
19442                if (mParent != null) {
19443                    mParent.recomputeViewAttributes(this);
19444                }
19445            }
19446        }
19447    }
19448
19449    /**
19450     * Creates an image that the system displays during the drag and drop
19451     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19452     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19453     * appearance as the given View. The default also positions the center of the drag shadow
19454     * directly under the touch point. If no View is provided (the constructor with no parameters
19455     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19456     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19457     * default is an invisible drag shadow.
19458     * <p>
19459     * You are not required to use the View you provide to the constructor as the basis of the
19460     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19461     * anything you want as the drag shadow.
19462     * </p>
19463     * <p>
19464     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19465     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19466     *  size and position of the drag shadow. It uses this data to construct a
19467     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19468     *  so that your application can draw the shadow image in the Canvas.
19469     * </p>
19470     *
19471     * <div class="special reference">
19472     * <h3>Developer Guides</h3>
19473     * <p>For a guide to implementing drag and drop features, read the
19474     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19475     * </div>
19476     */
19477    public static class DragShadowBuilder {
19478        private final WeakReference<View> mView;
19479
19480        /**
19481         * Constructs a shadow image builder based on a View. By default, the resulting drag
19482         * shadow will have the same appearance and dimensions as the View, with the touch point
19483         * over the center of the View.
19484         * @param view A View. Any View in scope can be used.
19485         */
19486        public DragShadowBuilder(View view) {
19487            mView = new WeakReference<View>(view);
19488        }
19489
19490        /**
19491         * Construct a shadow builder object with no associated View.  This
19492         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19493         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19494         * to supply the drag shadow's dimensions and appearance without
19495         * reference to any View object. If they are not overridden, then the result is an
19496         * invisible drag shadow.
19497         */
19498        public DragShadowBuilder() {
19499            mView = new WeakReference<View>(null);
19500        }
19501
19502        /**
19503         * Returns the View object that had been passed to the
19504         * {@link #View.DragShadowBuilder(View)}
19505         * constructor.  If that View parameter was {@code null} or if the
19506         * {@link #View.DragShadowBuilder()}
19507         * constructor was used to instantiate the builder object, this method will return
19508         * null.
19509         *
19510         * @return The View object associate with this builder object.
19511         */
19512        @SuppressWarnings({"JavadocReference"})
19513        final public View getView() {
19514            return mView.get();
19515        }
19516
19517        /**
19518         * Provides the metrics for the shadow image. These include the dimensions of
19519         * the shadow image, and the point within that shadow that should
19520         * be centered under the touch location while dragging.
19521         * <p>
19522         * The default implementation sets the dimensions of the shadow to be the
19523         * same as the dimensions of the View itself and centers the shadow under
19524         * the touch point.
19525         * </p>
19526         *
19527         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19528         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19529         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19530         * image.
19531         *
19532         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19533         * shadow image that should be underneath the touch point during the drag and drop
19534         * operation. Your application must set {@link android.graphics.Point#x} to the
19535         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19536         */
19537        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19538            final View view = mView.get();
19539            if (view != null) {
19540                shadowSize.set(view.getWidth(), view.getHeight());
19541                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19542            } else {
19543                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19544            }
19545        }
19546
19547        /**
19548         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19549         * based on the dimensions it received from the
19550         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19551         *
19552         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19553         */
19554        public void onDrawShadow(Canvas canvas) {
19555            final View view = mView.get();
19556            if (view != null) {
19557                view.draw(canvas);
19558            } else {
19559                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19560            }
19561        }
19562    }
19563
19564    /**
19565     * Starts a drag and drop operation. When your application calls this method, it passes a
19566     * {@link android.view.View.DragShadowBuilder} object to the system. The
19567     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19568     * to get metrics for the drag shadow, and then calls the object's
19569     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19570     * <p>
19571     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19572     *  drag events to all the View objects in your application that are currently visible. It does
19573     *  this either by calling the View object's drag listener (an implementation of
19574     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19575     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19576     *  Both are passed a {@link android.view.DragEvent} object that has a
19577     *  {@link android.view.DragEvent#getAction()} value of
19578     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19579     * </p>
19580     * <p>
19581     * Your application can invoke startDrag() on any attached View object. The View object does not
19582     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19583     * be related to the View the user selected for dragging.
19584     * </p>
19585     * @param data A {@link android.content.ClipData} object pointing to the data to be
19586     * transferred by the drag and drop operation.
19587     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19588     * drag shadow.
19589     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19590     * drop operation. This Object is put into every DragEvent object sent by the system during the
19591     * current drag.
19592     * <p>
19593     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19594     * to the target Views. For example, it can contain flags that differentiate between a
19595     * a copy operation and a move operation.
19596     * </p>
19597     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19598     * so the parameter should be set to 0.
19599     * @return {@code true} if the method completes successfully, or
19600     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19601     * do a drag, and so no drag operation is in progress.
19602     */
19603    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19604            Object myLocalState, int flags) {
19605        if (ViewDebug.DEBUG_DRAG) {
19606            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19607        }
19608        boolean okay = false;
19609
19610        Point shadowSize = new Point();
19611        Point shadowTouchPoint = new Point();
19612        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19613
19614        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19615                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19616            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19617        }
19618
19619        if (ViewDebug.DEBUG_DRAG) {
19620            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19621                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19622        }
19623        Surface surface = new Surface();
19624        try {
19625            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19626                    flags, shadowSize.x, shadowSize.y, surface);
19627            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19628                    + " surface=" + surface);
19629            if (token != null) {
19630                Canvas canvas = surface.lockCanvas(null);
19631                try {
19632                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19633                    shadowBuilder.onDrawShadow(canvas);
19634                } finally {
19635                    surface.unlockCanvasAndPost(canvas);
19636                }
19637
19638                final ViewRootImpl root = getViewRootImpl();
19639
19640                // Cache the local state object for delivery with DragEvents
19641                root.setLocalDragState(myLocalState);
19642
19643                // repurpose 'shadowSize' for the last touch point
19644                root.getLastTouchPoint(shadowSize);
19645
19646                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19647                        shadowSize.x, shadowSize.y,
19648                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19649                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19650
19651                // Off and running!  Release our local surface instance; the drag
19652                // shadow surface is now managed by the system process.
19653                surface.release();
19654            }
19655        } catch (Exception e) {
19656            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19657            surface.destroy();
19658        }
19659
19660        return okay;
19661    }
19662
19663    /**
19664     * Handles drag events sent by the system following a call to
19665     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19666     *<p>
19667     * When the system calls this method, it passes a
19668     * {@link android.view.DragEvent} object. A call to
19669     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19670     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19671     * operation.
19672     * @param event The {@link android.view.DragEvent} sent by the system.
19673     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19674     * in DragEvent, indicating the type of drag event represented by this object.
19675     * @return {@code true} if the method was successful, otherwise {@code false}.
19676     * <p>
19677     *  The method should return {@code true} in response to an action type of
19678     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19679     *  operation.
19680     * </p>
19681     * <p>
19682     *  The method should also return {@code true} in response to an action type of
19683     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19684     *  {@code false} if it didn't.
19685     * </p>
19686     */
19687    public boolean onDragEvent(DragEvent event) {
19688        return false;
19689    }
19690
19691    /**
19692     * Detects if this View is enabled and has a drag event listener.
19693     * If both are true, then it calls the drag event listener with the
19694     * {@link android.view.DragEvent} it received. If the drag event listener returns
19695     * {@code true}, then dispatchDragEvent() returns {@code true}.
19696     * <p>
19697     * For all other cases, the method calls the
19698     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19699     * method and returns its result.
19700     * </p>
19701     * <p>
19702     * This ensures that a drag event is always consumed, even if the View does not have a drag
19703     * event listener. However, if the View has a listener and the listener returns true, then
19704     * onDragEvent() is not called.
19705     * </p>
19706     */
19707    public boolean dispatchDragEvent(DragEvent event) {
19708        ListenerInfo li = mListenerInfo;
19709        //noinspection SimplifiableIfStatement
19710        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19711                && li.mOnDragListener.onDrag(this, event)) {
19712            return true;
19713        }
19714        return onDragEvent(event);
19715    }
19716
19717    boolean canAcceptDrag() {
19718        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19719    }
19720
19721    /**
19722     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19723     * it is ever exposed at all.
19724     * @hide
19725     */
19726    public void onCloseSystemDialogs(String reason) {
19727    }
19728
19729    /**
19730     * Given a Drawable whose bounds have been set to draw into this view,
19731     * update a Region being computed for
19732     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19733     * that any non-transparent parts of the Drawable are removed from the
19734     * given transparent region.
19735     *
19736     * @param dr The Drawable whose transparency is to be applied to the region.
19737     * @param region A Region holding the current transparency information,
19738     * where any parts of the region that are set are considered to be
19739     * transparent.  On return, this region will be modified to have the
19740     * transparency information reduced by the corresponding parts of the
19741     * Drawable that are not transparent.
19742     * {@hide}
19743     */
19744    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19745        if (DBG) {
19746            Log.i("View", "Getting transparent region for: " + this);
19747        }
19748        final Region r = dr.getTransparentRegion();
19749        final Rect db = dr.getBounds();
19750        final AttachInfo attachInfo = mAttachInfo;
19751        if (r != null && attachInfo != null) {
19752            final int w = getRight()-getLeft();
19753            final int h = getBottom()-getTop();
19754            if (db.left > 0) {
19755                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19756                r.op(0, 0, db.left, h, Region.Op.UNION);
19757            }
19758            if (db.right < w) {
19759                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19760                r.op(db.right, 0, w, h, Region.Op.UNION);
19761            }
19762            if (db.top > 0) {
19763                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19764                r.op(0, 0, w, db.top, Region.Op.UNION);
19765            }
19766            if (db.bottom < h) {
19767                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19768                r.op(0, db.bottom, w, h, Region.Op.UNION);
19769            }
19770            final int[] location = attachInfo.mTransparentLocation;
19771            getLocationInWindow(location);
19772            r.translate(location[0], location[1]);
19773            region.op(r, Region.Op.INTERSECT);
19774        } else {
19775            region.op(db, Region.Op.DIFFERENCE);
19776        }
19777    }
19778
19779    private void checkForLongClick(int delayOffset) {
19780        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19781            mHasPerformedLongPress = false;
19782
19783            if (mPendingCheckForLongPress == null) {
19784                mPendingCheckForLongPress = new CheckForLongPress();
19785            }
19786            mPendingCheckForLongPress.rememberWindowAttachCount();
19787            postDelayed(mPendingCheckForLongPress,
19788                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19789        }
19790    }
19791
19792    /**
19793     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19794     * LayoutInflater} class, which provides a full range of options for view inflation.
19795     *
19796     * @param context The Context object for your activity or application.
19797     * @param resource The resource ID to inflate
19798     * @param root A view group that will be the parent.  Used to properly inflate the
19799     * layout_* parameters.
19800     * @see LayoutInflater
19801     */
19802    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19803        LayoutInflater factory = LayoutInflater.from(context);
19804        return factory.inflate(resource, root);
19805    }
19806
19807    /**
19808     * Scroll the view with standard behavior for scrolling beyond the normal
19809     * content boundaries. Views that call this method should override
19810     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19811     * results of an over-scroll operation.
19812     *
19813     * Views can use this method to handle any touch or fling-based scrolling.
19814     *
19815     * @param deltaX Change in X in pixels
19816     * @param deltaY Change in Y in pixels
19817     * @param scrollX Current X scroll value in pixels before applying deltaX
19818     * @param scrollY Current Y scroll value in pixels before applying deltaY
19819     * @param scrollRangeX Maximum content scroll range along the X axis
19820     * @param scrollRangeY Maximum content scroll range along the Y axis
19821     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19822     *          along the X axis.
19823     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19824     *          along the Y axis.
19825     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19826     * @return true if scrolling was clamped to an over-scroll boundary along either
19827     *          axis, false otherwise.
19828     */
19829    @SuppressWarnings({"UnusedParameters"})
19830    protected boolean overScrollBy(int deltaX, int deltaY,
19831            int scrollX, int scrollY,
19832            int scrollRangeX, int scrollRangeY,
19833            int maxOverScrollX, int maxOverScrollY,
19834            boolean isTouchEvent) {
19835        final int overScrollMode = mOverScrollMode;
19836        final boolean canScrollHorizontal =
19837                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19838        final boolean canScrollVertical =
19839                computeVerticalScrollRange() > computeVerticalScrollExtent();
19840        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19841                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19842        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19843                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19844
19845        int newScrollX = scrollX + deltaX;
19846        if (!overScrollHorizontal) {
19847            maxOverScrollX = 0;
19848        }
19849
19850        int newScrollY = scrollY + deltaY;
19851        if (!overScrollVertical) {
19852            maxOverScrollY = 0;
19853        }
19854
19855        // Clamp values if at the limits and record
19856        final int left = -maxOverScrollX;
19857        final int right = maxOverScrollX + scrollRangeX;
19858        final int top = -maxOverScrollY;
19859        final int bottom = maxOverScrollY + scrollRangeY;
19860
19861        boolean clampedX = false;
19862        if (newScrollX > right) {
19863            newScrollX = right;
19864            clampedX = true;
19865        } else if (newScrollX < left) {
19866            newScrollX = left;
19867            clampedX = true;
19868        }
19869
19870        boolean clampedY = false;
19871        if (newScrollY > bottom) {
19872            newScrollY = bottom;
19873            clampedY = true;
19874        } else if (newScrollY < top) {
19875            newScrollY = top;
19876            clampedY = true;
19877        }
19878
19879        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19880
19881        return clampedX || clampedY;
19882    }
19883
19884    /**
19885     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19886     * respond to the results of an over-scroll operation.
19887     *
19888     * @param scrollX New X scroll value in pixels
19889     * @param scrollY New Y scroll value in pixels
19890     * @param clampedX True if scrollX was clamped to an over-scroll boundary
19891     * @param clampedY True if scrollY was clamped to an over-scroll boundary
19892     */
19893    protected void onOverScrolled(int scrollX, int scrollY,
19894            boolean clampedX, boolean clampedY) {
19895        // Intentionally empty.
19896    }
19897
19898    /**
19899     * Returns the over-scroll mode for this view. The result will be
19900     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19901     * (allow over-scrolling only if the view content is larger than the container),
19902     * or {@link #OVER_SCROLL_NEVER}.
19903     *
19904     * @return This view's over-scroll mode.
19905     */
19906    public int getOverScrollMode() {
19907        return mOverScrollMode;
19908    }
19909
19910    /**
19911     * Set the over-scroll mode for this view. Valid over-scroll modes are
19912     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19913     * (allow over-scrolling only if the view content is larger than the container),
19914     * or {@link #OVER_SCROLL_NEVER}.
19915     *
19916     * Setting the over-scroll mode of a view will have an effect only if the
19917     * view is capable of scrolling.
19918     *
19919     * @param overScrollMode The new over-scroll mode for this view.
19920     */
19921    public void setOverScrollMode(int overScrollMode) {
19922        if (overScrollMode != OVER_SCROLL_ALWAYS &&
19923                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19924                overScrollMode != OVER_SCROLL_NEVER) {
19925            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19926        }
19927        mOverScrollMode = overScrollMode;
19928    }
19929
19930    /**
19931     * Enable or disable nested scrolling for this view.
19932     *
19933     * <p>If this property is set to true the view will be permitted to initiate nested
19934     * scrolling operations with a compatible parent view in the current hierarchy. If this
19935     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19936     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19937     * the nested scroll.</p>
19938     *
19939     * @param enabled true to enable nested scrolling, false to disable
19940     *
19941     * @see #isNestedScrollingEnabled()
19942     */
19943    public void setNestedScrollingEnabled(boolean enabled) {
19944        if (enabled) {
19945            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19946        } else {
19947            stopNestedScroll();
19948            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19949        }
19950    }
19951
19952    /**
19953     * Returns true if nested scrolling is enabled for this view.
19954     *
19955     * <p>If nested scrolling is enabled and this View class implementation supports it,
19956     * this view will act as a nested scrolling child view when applicable, forwarding data
19957     * about the scroll operation in progress to a compatible and cooperating nested scrolling
19958     * parent.</p>
19959     *
19960     * @return true if nested scrolling is enabled
19961     *
19962     * @see #setNestedScrollingEnabled(boolean)
19963     */
19964    public boolean isNestedScrollingEnabled() {
19965        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19966                PFLAG3_NESTED_SCROLLING_ENABLED;
19967    }
19968
19969    /**
19970     * Begin a nestable scroll operation along the given axes.
19971     *
19972     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19973     *
19974     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19975     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19976     * In the case of touch scrolling the nested scroll will be terminated automatically in
19977     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19978     * In the event of programmatic scrolling the caller must explicitly call
19979     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19980     *
19981     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19982     * If it returns false the caller may ignore the rest of this contract until the next scroll.
19983     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19984     *
19985     * <p>At each incremental step of the scroll the caller should invoke
19986     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19987     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19988     * parent at least partially consumed the scroll and the caller should adjust the amount it
19989     * scrolls by.</p>
19990     *
19991     * <p>After applying the remainder of the scroll delta the caller should invoke
19992     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19993     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19994     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19995     * </p>
19996     *
19997     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19998     *             {@link #SCROLL_AXIS_VERTICAL}.
19999     * @return true if a cooperative parent was found and nested scrolling has been enabled for
20000     *         the current gesture.
20001     *
20002     * @see #stopNestedScroll()
20003     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20004     * @see #dispatchNestedScroll(int, int, int, int, int[])
20005     */
20006    public boolean startNestedScroll(int axes) {
20007        if (hasNestedScrollingParent()) {
20008            // Already in progress
20009            return true;
20010        }
20011        if (isNestedScrollingEnabled()) {
20012            ViewParent p = getParent();
20013            View child = this;
20014            while (p != null) {
20015                try {
20016                    if (p.onStartNestedScroll(child, this, axes)) {
20017                        mNestedScrollingParent = p;
20018                        p.onNestedScrollAccepted(child, this, axes);
20019                        return true;
20020                    }
20021                } catch (AbstractMethodError e) {
20022                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20023                            "method onStartNestedScroll", e);
20024                    // Allow the search upward to continue
20025                }
20026                if (p instanceof View) {
20027                    child = (View) p;
20028                }
20029                p = p.getParent();
20030            }
20031        }
20032        return false;
20033    }
20034
20035    /**
20036     * Stop a nested scroll in progress.
20037     *
20038     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20039     *
20040     * @see #startNestedScroll(int)
20041     */
20042    public void stopNestedScroll() {
20043        if (mNestedScrollingParent != null) {
20044            mNestedScrollingParent.onStopNestedScroll(this);
20045            mNestedScrollingParent = null;
20046        }
20047    }
20048
20049    /**
20050     * Returns true if this view has a nested scrolling parent.
20051     *
20052     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20053     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20054     *
20055     * @return whether this view has a nested scrolling parent
20056     */
20057    public boolean hasNestedScrollingParent() {
20058        return mNestedScrollingParent != null;
20059    }
20060
20061    /**
20062     * Dispatch one step of a nested scroll in progress.
20063     *
20064     * <p>Implementations of views that support nested scrolling should call this to report
20065     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20066     * is not currently in progress or nested scrolling is not
20067     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20068     *
20069     * <p>Compatible View implementations should also call
20070     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20071     * consuming a component of the scroll event themselves.</p>
20072     *
20073     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20074     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20075     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20076     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20077     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20078     *                       in local view coordinates of this view from before this operation
20079     *                       to after it completes. View implementations may use this to adjust
20080     *                       expected input coordinate tracking.
20081     * @return true if the event was dispatched, false if it could not be dispatched.
20082     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20083     */
20084    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20085            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20086        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20087            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20088                int startX = 0;
20089                int startY = 0;
20090                if (offsetInWindow != null) {
20091                    getLocationInWindow(offsetInWindow);
20092                    startX = offsetInWindow[0];
20093                    startY = offsetInWindow[1];
20094                }
20095
20096                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20097                        dxUnconsumed, dyUnconsumed);
20098
20099                if (offsetInWindow != null) {
20100                    getLocationInWindow(offsetInWindow);
20101                    offsetInWindow[0] -= startX;
20102                    offsetInWindow[1] -= startY;
20103                }
20104                return true;
20105            } else if (offsetInWindow != null) {
20106                // No motion, no dispatch. Keep offsetInWindow up to date.
20107                offsetInWindow[0] = 0;
20108                offsetInWindow[1] = 0;
20109            }
20110        }
20111        return false;
20112    }
20113
20114    /**
20115     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20116     *
20117     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20118     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20119     * scrolling operation to consume some or all of the scroll operation before the child view
20120     * consumes it.</p>
20121     *
20122     * @param dx Horizontal scroll distance in pixels
20123     * @param dy Vertical scroll distance in pixels
20124     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20125     *                 and consumed[1] the consumed dy.
20126     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20127     *                       in local view coordinates of this view from before this operation
20128     *                       to after it completes. View implementations may use this to adjust
20129     *                       expected input coordinate tracking.
20130     * @return true if the parent consumed some or all of the scroll delta
20131     * @see #dispatchNestedScroll(int, int, int, int, int[])
20132     */
20133    public boolean dispatchNestedPreScroll(int dx, int dy,
20134            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20135        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20136            if (dx != 0 || dy != 0) {
20137                int startX = 0;
20138                int startY = 0;
20139                if (offsetInWindow != null) {
20140                    getLocationInWindow(offsetInWindow);
20141                    startX = offsetInWindow[0];
20142                    startY = offsetInWindow[1];
20143                }
20144
20145                if (consumed == null) {
20146                    if (mTempNestedScrollConsumed == null) {
20147                        mTempNestedScrollConsumed = new int[2];
20148                    }
20149                    consumed = mTempNestedScrollConsumed;
20150                }
20151                consumed[0] = 0;
20152                consumed[1] = 0;
20153                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20154
20155                if (offsetInWindow != null) {
20156                    getLocationInWindow(offsetInWindow);
20157                    offsetInWindow[0] -= startX;
20158                    offsetInWindow[1] -= startY;
20159                }
20160                return consumed[0] != 0 || consumed[1] != 0;
20161            } else if (offsetInWindow != null) {
20162                offsetInWindow[0] = 0;
20163                offsetInWindow[1] = 0;
20164            }
20165        }
20166        return false;
20167    }
20168
20169    /**
20170     * Dispatch a fling to a nested scrolling parent.
20171     *
20172     * <p>This method should be used to indicate that a nested scrolling child has detected
20173     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20174     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20175     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20176     * along a scrollable axis.</p>
20177     *
20178     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20179     * its own content, it can use this method to delegate the fling to its nested scrolling
20180     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20181     *
20182     * @param velocityX Horizontal fling velocity in pixels per second
20183     * @param velocityY Vertical fling velocity in pixels per second
20184     * @param consumed true if the child consumed the fling, false otherwise
20185     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20186     */
20187    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20188        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20189            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20190        }
20191        return false;
20192    }
20193
20194    /**
20195     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20196     *
20197     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20198     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20199     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20200     * before the child view consumes it. If this method returns <code>true</code>, a nested
20201     * parent view consumed the fling and this view should not scroll as a result.</p>
20202     *
20203     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20204     * the fling at a time. If a parent view consumed the fling this method will return false.
20205     * Custom view implementations should account for this in two ways:</p>
20206     *
20207     * <ul>
20208     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20209     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20210     *     position regardless.</li>
20211     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20212     *     even to settle back to a valid idle position.</li>
20213     * </ul>
20214     *
20215     * <p>Views should also not offer fling velocities to nested parent views along an axis
20216     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20217     * should not offer a horizontal fling velocity to its parents since scrolling along that
20218     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20219     *
20220     * @param velocityX Horizontal fling velocity in pixels per second
20221     * @param velocityY Vertical fling velocity in pixels per second
20222     * @return true if a nested scrolling parent consumed the fling
20223     */
20224    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20225        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20226            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20227        }
20228        return false;
20229    }
20230
20231    /**
20232     * Gets a scale factor that determines the distance the view should scroll
20233     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20234     * @return The vertical scroll scale factor.
20235     * @hide
20236     */
20237    protected float getVerticalScrollFactor() {
20238        if (mVerticalScrollFactor == 0) {
20239            TypedValue outValue = new TypedValue();
20240            if (!mContext.getTheme().resolveAttribute(
20241                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20242                throw new IllegalStateException(
20243                        "Expected theme to define listPreferredItemHeight.");
20244            }
20245            mVerticalScrollFactor = outValue.getDimension(
20246                    mContext.getResources().getDisplayMetrics());
20247        }
20248        return mVerticalScrollFactor;
20249    }
20250
20251    /**
20252     * Gets a scale factor that determines the distance the view should scroll
20253     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20254     * @return The horizontal scroll scale factor.
20255     * @hide
20256     */
20257    protected float getHorizontalScrollFactor() {
20258        // TODO: Should use something else.
20259        return getVerticalScrollFactor();
20260    }
20261
20262    /**
20263     * Return the value specifying the text direction or policy that was set with
20264     * {@link #setTextDirection(int)}.
20265     *
20266     * @return the defined text direction. It can be one of:
20267     *
20268     * {@link #TEXT_DIRECTION_INHERIT},
20269     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20270     * {@link #TEXT_DIRECTION_ANY_RTL},
20271     * {@link #TEXT_DIRECTION_LTR},
20272     * {@link #TEXT_DIRECTION_RTL},
20273     * {@link #TEXT_DIRECTION_LOCALE},
20274     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20275     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20276     *
20277     * @attr ref android.R.styleable#View_textDirection
20278     *
20279     * @hide
20280     */
20281    @ViewDebug.ExportedProperty(category = "text", mapping = {
20282            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20283            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20284            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20285            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20286            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20287            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20288            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20289            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20290    })
20291    public int getRawTextDirection() {
20292        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20293    }
20294
20295    /**
20296     * Set the text direction.
20297     *
20298     * @param textDirection the direction to set. Should be one of:
20299     *
20300     * {@link #TEXT_DIRECTION_INHERIT},
20301     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20302     * {@link #TEXT_DIRECTION_ANY_RTL},
20303     * {@link #TEXT_DIRECTION_LTR},
20304     * {@link #TEXT_DIRECTION_RTL},
20305     * {@link #TEXT_DIRECTION_LOCALE}
20306     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20307     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20308     *
20309     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20310     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20311     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20312     *
20313     * @attr ref android.R.styleable#View_textDirection
20314     */
20315    public void setTextDirection(int textDirection) {
20316        if (getRawTextDirection() != textDirection) {
20317            // Reset the current text direction and the resolved one
20318            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20319            resetResolvedTextDirection();
20320            // Set the new text direction
20321            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20322            // Do resolution
20323            resolveTextDirection();
20324            // Notify change
20325            onRtlPropertiesChanged(getLayoutDirection());
20326            // Refresh
20327            requestLayout();
20328            invalidate(true);
20329        }
20330    }
20331
20332    /**
20333     * Return the resolved text direction.
20334     *
20335     * @return the resolved text direction. Returns one of:
20336     *
20337     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20338     * {@link #TEXT_DIRECTION_ANY_RTL},
20339     * {@link #TEXT_DIRECTION_LTR},
20340     * {@link #TEXT_DIRECTION_RTL},
20341     * {@link #TEXT_DIRECTION_LOCALE},
20342     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20343     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20344     *
20345     * @attr ref android.R.styleable#View_textDirection
20346     */
20347    @ViewDebug.ExportedProperty(category = "text", mapping = {
20348            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20349            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20350            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20351            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20352            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20353            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20354            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20355            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20356    })
20357    public int getTextDirection() {
20358        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20359    }
20360
20361    /**
20362     * Resolve the text direction.
20363     *
20364     * @return true if resolution has been done, false otherwise.
20365     *
20366     * @hide
20367     */
20368    public boolean resolveTextDirection() {
20369        // Reset any previous text direction resolution
20370        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20371
20372        if (hasRtlSupport()) {
20373            // Set resolved text direction flag depending on text direction flag
20374            final int textDirection = getRawTextDirection();
20375            switch(textDirection) {
20376                case TEXT_DIRECTION_INHERIT:
20377                    if (!canResolveTextDirection()) {
20378                        // We cannot do the resolution if there is no parent, so use the default one
20379                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20380                        // Resolution will need to happen again later
20381                        return false;
20382                    }
20383
20384                    // Parent has not yet resolved, so we still return the default
20385                    try {
20386                        if (!mParent.isTextDirectionResolved()) {
20387                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20388                            // Resolution will need to happen again later
20389                            return false;
20390                        }
20391                    } catch (AbstractMethodError e) {
20392                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20393                                " does not fully implement ViewParent", e);
20394                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20395                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20396                        return true;
20397                    }
20398
20399                    // Set current resolved direction to the same value as the parent's one
20400                    int parentResolvedDirection;
20401                    try {
20402                        parentResolvedDirection = mParent.getTextDirection();
20403                    } catch (AbstractMethodError e) {
20404                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20405                                " does not fully implement ViewParent", e);
20406                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20407                    }
20408                    switch (parentResolvedDirection) {
20409                        case TEXT_DIRECTION_FIRST_STRONG:
20410                        case TEXT_DIRECTION_ANY_RTL:
20411                        case TEXT_DIRECTION_LTR:
20412                        case TEXT_DIRECTION_RTL:
20413                        case TEXT_DIRECTION_LOCALE:
20414                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20415                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20416                            mPrivateFlags2 |=
20417                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20418                            break;
20419                        default:
20420                            // Default resolved direction is "first strong" heuristic
20421                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20422                    }
20423                    break;
20424                case TEXT_DIRECTION_FIRST_STRONG:
20425                case TEXT_DIRECTION_ANY_RTL:
20426                case TEXT_DIRECTION_LTR:
20427                case TEXT_DIRECTION_RTL:
20428                case TEXT_DIRECTION_LOCALE:
20429                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20430                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20431                    // Resolved direction is the same as text direction
20432                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20433                    break;
20434                default:
20435                    // Default resolved direction is "first strong" heuristic
20436                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20437            }
20438        } else {
20439            // Default resolved direction is "first strong" heuristic
20440            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20441        }
20442
20443        // Set to resolved
20444        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20445        return true;
20446    }
20447
20448    /**
20449     * Check if text direction resolution can be done.
20450     *
20451     * @return true if text direction resolution can be done otherwise return false.
20452     */
20453    public boolean canResolveTextDirection() {
20454        switch (getRawTextDirection()) {
20455            case TEXT_DIRECTION_INHERIT:
20456                if (mParent != null) {
20457                    try {
20458                        return mParent.canResolveTextDirection();
20459                    } catch (AbstractMethodError e) {
20460                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20461                                " does not fully implement ViewParent", e);
20462                    }
20463                }
20464                return false;
20465
20466            default:
20467                return true;
20468        }
20469    }
20470
20471    /**
20472     * Reset resolved text direction. Text direction will be resolved during a call to
20473     * {@link #onMeasure(int, int)}.
20474     *
20475     * @hide
20476     */
20477    public void resetResolvedTextDirection() {
20478        // Reset any previous text direction resolution
20479        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20480        // Set to default value
20481        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20482    }
20483
20484    /**
20485     * @return true if text direction is inherited.
20486     *
20487     * @hide
20488     */
20489    public boolean isTextDirectionInherited() {
20490        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20491    }
20492
20493    /**
20494     * @return true if text direction is resolved.
20495     */
20496    public boolean isTextDirectionResolved() {
20497        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20498    }
20499
20500    /**
20501     * Return the value specifying the text alignment or policy that was set with
20502     * {@link #setTextAlignment(int)}.
20503     *
20504     * @return the defined text alignment. It can be one of:
20505     *
20506     * {@link #TEXT_ALIGNMENT_INHERIT},
20507     * {@link #TEXT_ALIGNMENT_GRAVITY},
20508     * {@link #TEXT_ALIGNMENT_CENTER},
20509     * {@link #TEXT_ALIGNMENT_TEXT_START},
20510     * {@link #TEXT_ALIGNMENT_TEXT_END},
20511     * {@link #TEXT_ALIGNMENT_VIEW_START},
20512     * {@link #TEXT_ALIGNMENT_VIEW_END}
20513     *
20514     * @attr ref android.R.styleable#View_textAlignment
20515     *
20516     * @hide
20517     */
20518    @ViewDebug.ExportedProperty(category = "text", mapping = {
20519            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20520            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20521            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20522            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20523            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20524            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20525            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20526    })
20527    @TextAlignment
20528    public int getRawTextAlignment() {
20529        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20530    }
20531
20532    /**
20533     * Set the text alignment.
20534     *
20535     * @param textAlignment The text alignment to set. Should be one of
20536     *
20537     * {@link #TEXT_ALIGNMENT_INHERIT},
20538     * {@link #TEXT_ALIGNMENT_GRAVITY},
20539     * {@link #TEXT_ALIGNMENT_CENTER},
20540     * {@link #TEXT_ALIGNMENT_TEXT_START},
20541     * {@link #TEXT_ALIGNMENT_TEXT_END},
20542     * {@link #TEXT_ALIGNMENT_VIEW_START},
20543     * {@link #TEXT_ALIGNMENT_VIEW_END}
20544     *
20545     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20546     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20547     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20548     *
20549     * @attr ref android.R.styleable#View_textAlignment
20550     */
20551    public void setTextAlignment(@TextAlignment int textAlignment) {
20552        if (textAlignment != getRawTextAlignment()) {
20553            // Reset the current and resolved text alignment
20554            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20555            resetResolvedTextAlignment();
20556            // Set the new text alignment
20557            mPrivateFlags2 |=
20558                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20559            // Do resolution
20560            resolveTextAlignment();
20561            // Notify change
20562            onRtlPropertiesChanged(getLayoutDirection());
20563            // Refresh
20564            requestLayout();
20565            invalidate(true);
20566        }
20567    }
20568
20569    /**
20570     * Return the resolved text alignment.
20571     *
20572     * @return the resolved text alignment. Returns one of:
20573     *
20574     * {@link #TEXT_ALIGNMENT_GRAVITY},
20575     * {@link #TEXT_ALIGNMENT_CENTER},
20576     * {@link #TEXT_ALIGNMENT_TEXT_START},
20577     * {@link #TEXT_ALIGNMENT_TEXT_END},
20578     * {@link #TEXT_ALIGNMENT_VIEW_START},
20579     * {@link #TEXT_ALIGNMENT_VIEW_END}
20580     *
20581     * @attr ref android.R.styleable#View_textAlignment
20582     */
20583    @ViewDebug.ExportedProperty(category = "text", mapping = {
20584            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20585            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20586            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20587            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20588            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20589            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20590            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20591    })
20592    @TextAlignment
20593    public int getTextAlignment() {
20594        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20595                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20596    }
20597
20598    /**
20599     * Resolve the text alignment.
20600     *
20601     * @return true if resolution has been done, false otherwise.
20602     *
20603     * @hide
20604     */
20605    public boolean resolveTextAlignment() {
20606        // Reset any previous text alignment resolution
20607        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20608
20609        if (hasRtlSupport()) {
20610            // Set resolved text alignment flag depending on text alignment flag
20611            final int textAlignment = getRawTextAlignment();
20612            switch (textAlignment) {
20613                case TEXT_ALIGNMENT_INHERIT:
20614                    // Check if we can resolve the text alignment
20615                    if (!canResolveTextAlignment()) {
20616                        // We cannot do the resolution if there is no parent so use the default
20617                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20618                        // Resolution will need to happen again later
20619                        return false;
20620                    }
20621
20622                    // Parent has not yet resolved, so we still return the default
20623                    try {
20624                        if (!mParent.isTextAlignmentResolved()) {
20625                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20626                            // Resolution will need to happen again later
20627                            return false;
20628                        }
20629                    } catch (AbstractMethodError e) {
20630                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20631                                " does not fully implement ViewParent", e);
20632                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20633                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20634                        return true;
20635                    }
20636
20637                    int parentResolvedTextAlignment;
20638                    try {
20639                        parentResolvedTextAlignment = mParent.getTextAlignment();
20640                    } catch (AbstractMethodError e) {
20641                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20642                                " does not fully implement ViewParent", e);
20643                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20644                    }
20645                    switch (parentResolvedTextAlignment) {
20646                        case TEXT_ALIGNMENT_GRAVITY:
20647                        case TEXT_ALIGNMENT_TEXT_START:
20648                        case TEXT_ALIGNMENT_TEXT_END:
20649                        case TEXT_ALIGNMENT_CENTER:
20650                        case TEXT_ALIGNMENT_VIEW_START:
20651                        case TEXT_ALIGNMENT_VIEW_END:
20652                            // Resolved text alignment is the same as the parent resolved
20653                            // text alignment
20654                            mPrivateFlags2 |=
20655                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20656                            break;
20657                        default:
20658                            // Use default resolved text alignment
20659                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20660                    }
20661                    break;
20662                case TEXT_ALIGNMENT_GRAVITY:
20663                case TEXT_ALIGNMENT_TEXT_START:
20664                case TEXT_ALIGNMENT_TEXT_END:
20665                case TEXT_ALIGNMENT_CENTER:
20666                case TEXT_ALIGNMENT_VIEW_START:
20667                case TEXT_ALIGNMENT_VIEW_END:
20668                    // Resolved text alignment is the same as text alignment
20669                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20670                    break;
20671                default:
20672                    // Use default resolved text alignment
20673                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20674            }
20675        } else {
20676            // Use default resolved text alignment
20677            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20678        }
20679
20680        // Set the resolved
20681        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20682        return true;
20683    }
20684
20685    /**
20686     * Check if text alignment resolution can be done.
20687     *
20688     * @return true if text alignment resolution can be done otherwise return false.
20689     */
20690    public boolean canResolveTextAlignment() {
20691        switch (getRawTextAlignment()) {
20692            case TEXT_DIRECTION_INHERIT:
20693                if (mParent != null) {
20694                    try {
20695                        return mParent.canResolveTextAlignment();
20696                    } catch (AbstractMethodError e) {
20697                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20698                                " does not fully implement ViewParent", e);
20699                    }
20700                }
20701                return false;
20702
20703            default:
20704                return true;
20705        }
20706    }
20707
20708    /**
20709     * Reset resolved text alignment. Text alignment will be resolved during a call to
20710     * {@link #onMeasure(int, int)}.
20711     *
20712     * @hide
20713     */
20714    public void resetResolvedTextAlignment() {
20715        // Reset any previous text alignment resolution
20716        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20717        // Set to default
20718        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20719    }
20720
20721    /**
20722     * @return true if text alignment is inherited.
20723     *
20724     * @hide
20725     */
20726    public boolean isTextAlignmentInherited() {
20727        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20728    }
20729
20730    /**
20731     * @return true if text alignment is resolved.
20732     */
20733    public boolean isTextAlignmentResolved() {
20734        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20735    }
20736
20737    /**
20738     * Generate a value suitable for use in {@link #setId(int)}.
20739     * This value will not collide with ID values generated at build time by aapt for R.id.
20740     *
20741     * @return a generated ID value
20742     */
20743    public static int generateViewId() {
20744        for (;;) {
20745            final int result = sNextGeneratedId.get();
20746            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20747            int newValue = result + 1;
20748            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20749            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20750                return result;
20751            }
20752        }
20753    }
20754
20755    /**
20756     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20757     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20758     *                           a normal View or a ViewGroup with
20759     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20760     * @hide
20761     */
20762    public void captureTransitioningViews(List<View> transitioningViews) {
20763        if (getVisibility() == View.VISIBLE) {
20764            transitioningViews.add(this);
20765        }
20766    }
20767
20768    /**
20769     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20770     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20771     * @hide
20772     */
20773    public void findNamedViews(Map<String, View> namedElements) {
20774        if (getVisibility() == VISIBLE || mGhostView != null) {
20775            String transitionName = getTransitionName();
20776            if (transitionName != null) {
20777                namedElements.put(transitionName, this);
20778            }
20779        }
20780    }
20781
20782    //
20783    // Properties
20784    //
20785    /**
20786     * A Property wrapper around the <code>alpha</code> functionality handled by the
20787     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20788     */
20789    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20790        @Override
20791        public void setValue(View object, float value) {
20792            object.setAlpha(value);
20793        }
20794
20795        @Override
20796        public Float get(View object) {
20797            return object.getAlpha();
20798        }
20799    };
20800
20801    /**
20802     * A Property wrapper around the <code>translationX</code> functionality handled by the
20803     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20804     */
20805    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20806        @Override
20807        public void setValue(View object, float value) {
20808            object.setTranslationX(value);
20809        }
20810
20811                @Override
20812        public Float get(View object) {
20813            return object.getTranslationX();
20814        }
20815    };
20816
20817    /**
20818     * A Property wrapper around the <code>translationY</code> functionality handled by the
20819     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20820     */
20821    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20822        @Override
20823        public void setValue(View object, float value) {
20824            object.setTranslationY(value);
20825        }
20826
20827        @Override
20828        public Float get(View object) {
20829            return object.getTranslationY();
20830        }
20831    };
20832
20833    /**
20834     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20835     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20836     */
20837    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20838        @Override
20839        public void setValue(View object, float value) {
20840            object.setTranslationZ(value);
20841        }
20842
20843        @Override
20844        public Float get(View object) {
20845            return object.getTranslationZ();
20846        }
20847    };
20848
20849    /**
20850     * A Property wrapper around the <code>x</code> functionality handled by the
20851     * {@link View#setX(float)} and {@link View#getX()} methods.
20852     */
20853    public static final Property<View, Float> X = new FloatProperty<View>("x") {
20854        @Override
20855        public void setValue(View object, float value) {
20856            object.setX(value);
20857        }
20858
20859        @Override
20860        public Float get(View object) {
20861            return object.getX();
20862        }
20863    };
20864
20865    /**
20866     * A Property wrapper around the <code>y</code> functionality handled by the
20867     * {@link View#setY(float)} and {@link View#getY()} methods.
20868     */
20869    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20870        @Override
20871        public void setValue(View object, float value) {
20872            object.setY(value);
20873        }
20874
20875        @Override
20876        public Float get(View object) {
20877            return object.getY();
20878        }
20879    };
20880
20881    /**
20882     * A Property wrapper around the <code>z</code> functionality handled by the
20883     * {@link View#setZ(float)} and {@link View#getZ()} methods.
20884     */
20885    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20886        @Override
20887        public void setValue(View object, float value) {
20888            object.setZ(value);
20889        }
20890
20891        @Override
20892        public Float get(View object) {
20893            return object.getZ();
20894        }
20895    };
20896
20897    /**
20898     * A Property wrapper around the <code>rotation</code> functionality handled by the
20899     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20900     */
20901    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20902        @Override
20903        public void setValue(View object, float value) {
20904            object.setRotation(value);
20905        }
20906
20907        @Override
20908        public Float get(View object) {
20909            return object.getRotation();
20910        }
20911    };
20912
20913    /**
20914     * A Property wrapper around the <code>rotationX</code> functionality handled by the
20915     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20916     */
20917    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20918        @Override
20919        public void setValue(View object, float value) {
20920            object.setRotationX(value);
20921        }
20922
20923        @Override
20924        public Float get(View object) {
20925            return object.getRotationX();
20926        }
20927    };
20928
20929    /**
20930     * A Property wrapper around the <code>rotationY</code> functionality handled by the
20931     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20932     */
20933    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20934        @Override
20935        public void setValue(View object, float value) {
20936            object.setRotationY(value);
20937        }
20938
20939        @Override
20940        public Float get(View object) {
20941            return object.getRotationY();
20942        }
20943    };
20944
20945    /**
20946     * A Property wrapper around the <code>scaleX</code> functionality handled by the
20947     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20948     */
20949    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20950        @Override
20951        public void setValue(View object, float value) {
20952            object.setScaleX(value);
20953        }
20954
20955        @Override
20956        public Float get(View object) {
20957            return object.getScaleX();
20958        }
20959    };
20960
20961    /**
20962     * A Property wrapper around the <code>scaleY</code> functionality handled by the
20963     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20964     */
20965    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20966        @Override
20967        public void setValue(View object, float value) {
20968            object.setScaleY(value);
20969        }
20970
20971        @Override
20972        public Float get(View object) {
20973            return object.getScaleY();
20974        }
20975    };
20976
20977    /**
20978     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20979     * Each MeasureSpec represents a requirement for either the width or the height.
20980     * A MeasureSpec is comprised of a size and a mode. There are three possible
20981     * modes:
20982     * <dl>
20983     * <dt>UNSPECIFIED</dt>
20984     * <dd>
20985     * The parent has not imposed any constraint on the child. It can be whatever size
20986     * it wants.
20987     * </dd>
20988     *
20989     * <dt>EXACTLY</dt>
20990     * <dd>
20991     * The parent has determined an exact size for the child. The child is going to be
20992     * given those bounds regardless of how big it wants to be.
20993     * </dd>
20994     *
20995     * <dt>AT_MOST</dt>
20996     * <dd>
20997     * The child can be as large as it wants up to the specified size.
20998     * </dd>
20999     * </dl>
21000     *
21001     * MeasureSpecs are implemented as ints to reduce object allocation. This class
21002     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
21003     */
21004    public static class MeasureSpec {
21005        private static final int MODE_SHIFT = 30;
21006        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21007
21008        /**
21009         * Measure specification mode: The parent has not imposed any constraint
21010         * on the child. It can be whatever size it wants.
21011         */
21012        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21013
21014        /**
21015         * Measure specification mode: The parent has determined an exact size
21016         * for the child. The child is going to be given those bounds regardless
21017         * of how big it wants to be.
21018         */
21019        public static final int EXACTLY     = 1 << MODE_SHIFT;
21020
21021        /**
21022         * Measure specification mode: The child can be as large as it wants up
21023         * to the specified size.
21024         */
21025        public static final int AT_MOST     = 2 << MODE_SHIFT;
21026
21027        /**
21028         * Creates a measure specification based on the supplied size and mode.
21029         *
21030         * The mode must always be one of the following:
21031         * <ul>
21032         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21033         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21034         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21035         * </ul>
21036         *
21037         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21038         * implementation was such that the order of arguments did not matter
21039         * and overflow in either value could impact the resulting MeasureSpec.
21040         * {@link android.widget.RelativeLayout} was affected by this bug.
21041         * Apps targeting API levels greater than 17 will get the fixed, more strict
21042         * behavior.</p>
21043         *
21044         * @param size the size of the measure specification
21045         * @param mode the mode of the measure specification
21046         * @return the measure specification based on size and mode
21047         */
21048        public static int makeMeasureSpec(int size, int mode) {
21049            if (sUseBrokenMakeMeasureSpec) {
21050                return size + mode;
21051            } else {
21052                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21053            }
21054        }
21055
21056        /**
21057         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21058         * will automatically get a size of 0. Older apps expect this.
21059         *
21060         * @hide internal use only for compatibility with system widgets and older apps
21061         */
21062        public static int makeSafeMeasureSpec(int size, int mode) {
21063            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21064                return 0;
21065            }
21066            return makeMeasureSpec(size, mode);
21067        }
21068
21069        /**
21070         * Extracts the mode from the supplied measure specification.
21071         *
21072         * @param measureSpec the measure specification to extract the mode from
21073         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21074         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21075         *         {@link android.view.View.MeasureSpec#EXACTLY}
21076         */
21077        public static int getMode(int measureSpec) {
21078            return (measureSpec & MODE_MASK);
21079        }
21080
21081        /**
21082         * Extracts the size from the supplied measure specification.
21083         *
21084         * @param measureSpec the measure specification to extract the size from
21085         * @return the size in pixels defined in the supplied measure specification
21086         */
21087        public static int getSize(int measureSpec) {
21088            return (measureSpec & ~MODE_MASK);
21089        }
21090
21091        static int adjust(int measureSpec, int delta) {
21092            final int mode = getMode(measureSpec);
21093            int size = getSize(measureSpec);
21094            if (mode == UNSPECIFIED) {
21095                // No need to adjust size for UNSPECIFIED mode.
21096                return makeMeasureSpec(size, UNSPECIFIED);
21097            }
21098            size += delta;
21099            if (size < 0) {
21100                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21101                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21102                size = 0;
21103            }
21104            return makeMeasureSpec(size, mode);
21105        }
21106
21107        /**
21108         * Returns a String representation of the specified measure
21109         * specification.
21110         *
21111         * @param measureSpec the measure specification to convert to a String
21112         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21113         */
21114        public static String toString(int measureSpec) {
21115            int mode = getMode(measureSpec);
21116            int size = getSize(measureSpec);
21117
21118            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21119
21120            if (mode == UNSPECIFIED)
21121                sb.append("UNSPECIFIED ");
21122            else if (mode == EXACTLY)
21123                sb.append("EXACTLY ");
21124            else if (mode == AT_MOST)
21125                sb.append("AT_MOST ");
21126            else
21127                sb.append(mode).append(" ");
21128
21129            sb.append(size);
21130            return sb.toString();
21131        }
21132    }
21133
21134    private final class CheckForLongPress implements Runnable {
21135        private int mOriginalWindowAttachCount;
21136
21137        @Override
21138        public void run() {
21139            if (isPressed() && (mParent != null)
21140                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21141                if (performLongClick()) {
21142                    mHasPerformedLongPress = true;
21143                }
21144            }
21145        }
21146
21147        public void rememberWindowAttachCount() {
21148            mOriginalWindowAttachCount = mWindowAttachCount;
21149        }
21150    }
21151
21152    private final class CheckForTap implements Runnable {
21153        public float x;
21154        public float y;
21155
21156        @Override
21157        public void run() {
21158            mPrivateFlags &= ~PFLAG_PREPRESSED;
21159            setPressed(true, x, y);
21160            checkForLongClick(ViewConfiguration.getTapTimeout());
21161        }
21162    }
21163
21164    private final class PerformClick implements Runnable {
21165        @Override
21166        public void run() {
21167            performClick();
21168        }
21169    }
21170
21171    /**
21172     * This method returns a ViewPropertyAnimator object, which can be used to animate
21173     * specific properties on this View.
21174     *
21175     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21176     */
21177    public ViewPropertyAnimator animate() {
21178        if (mAnimator == null) {
21179            mAnimator = new ViewPropertyAnimator(this);
21180        }
21181        return mAnimator;
21182    }
21183
21184    /**
21185     * Sets the name of the View to be used to identify Views in Transitions.
21186     * Names should be unique in the View hierarchy.
21187     *
21188     * @param transitionName The name of the View to uniquely identify it for Transitions.
21189     */
21190    public final void setTransitionName(String transitionName) {
21191        mTransitionName = transitionName;
21192    }
21193
21194    /**
21195     * Returns the name of the View to be used to identify Views in Transitions.
21196     * Names should be unique in the View hierarchy.
21197     *
21198     * <p>This returns null if the View has not been given a name.</p>
21199     *
21200     * @return The name used of the View to be used to identify Views in Transitions or null
21201     * if no name has been given.
21202     */
21203    @ViewDebug.ExportedProperty
21204    public String getTransitionName() {
21205        return mTransitionName;
21206    }
21207
21208    /**
21209     * Interface definition for a callback to be invoked when a hardware key event is
21210     * dispatched to this view. The callback will be invoked before the key event is
21211     * given to the view. This is only useful for hardware keyboards; a software input
21212     * method has no obligation to trigger this listener.
21213     */
21214    public interface OnKeyListener {
21215        /**
21216         * Called when a hardware key is dispatched to a view. This allows listeners to
21217         * get a chance to respond before the target view.
21218         * <p>Key presses in software keyboards will generally NOT trigger this method,
21219         * although some may elect to do so in some situations. Do not assume a
21220         * software input method has to be key-based; even if it is, it may use key presses
21221         * in a different way than you expect, so there is no way to reliably catch soft
21222         * input key presses.
21223         *
21224         * @param v The view the key has been dispatched to.
21225         * @param keyCode The code for the physical key that was pressed
21226         * @param event The KeyEvent object containing full information about
21227         *        the event.
21228         * @return True if the listener has consumed the event, false otherwise.
21229         */
21230        boolean onKey(View v, int keyCode, KeyEvent event);
21231    }
21232
21233    /**
21234     * Interface definition for a callback to be invoked when a touch event is
21235     * dispatched to this view. The callback will be invoked before the touch
21236     * event is given to the view.
21237     */
21238    public interface OnTouchListener {
21239        /**
21240         * Called when a touch event is dispatched to a view. This allows listeners to
21241         * get a chance to respond before the target view.
21242         *
21243         * @param v The view the touch event has been dispatched to.
21244         * @param event The MotionEvent object containing full information about
21245         *        the event.
21246         * @return True if the listener has consumed the event, false otherwise.
21247         */
21248        boolean onTouch(View v, MotionEvent event);
21249    }
21250
21251    /**
21252     * Interface definition for a callback to be invoked when a hover event is
21253     * dispatched to this view. The callback will be invoked before the hover
21254     * event is given to the view.
21255     */
21256    public interface OnHoverListener {
21257        /**
21258         * Called when a hover event is dispatched to a view. This allows listeners to
21259         * get a chance to respond before the target view.
21260         *
21261         * @param v The view the hover event has been dispatched to.
21262         * @param event The MotionEvent object containing full information about
21263         *        the event.
21264         * @return True if the listener has consumed the event, false otherwise.
21265         */
21266        boolean onHover(View v, MotionEvent event);
21267    }
21268
21269    /**
21270     * Interface definition for a callback to be invoked when a generic motion event is
21271     * dispatched to this view. The callback will be invoked before the generic motion
21272     * event is given to the view.
21273     */
21274    public interface OnGenericMotionListener {
21275        /**
21276         * Called when a generic motion event is dispatched to a view. This allows listeners to
21277         * get a chance to respond before the target view.
21278         *
21279         * @param v The view the generic motion event has been dispatched to.
21280         * @param event The MotionEvent object containing full information about
21281         *        the event.
21282         * @return True if the listener has consumed the event, false otherwise.
21283         */
21284        boolean onGenericMotion(View v, MotionEvent event);
21285    }
21286
21287    /**
21288     * Interface definition for a callback to be invoked when a view has been clicked and held.
21289     */
21290    public interface OnLongClickListener {
21291        /**
21292         * Called when a view has been clicked and held.
21293         *
21294         * @param v The view that was clicked and held.
21295         *
21296         * @return true if the callback consumed the long click, false otherwise.
21297         */
21298        boolean onLongClick(View v);
21299    }
21300
21301    /**
21302     * Interface definition for a callback to be invoked when a drag is being dispatched
21303     * to this view.  The callback will be invoked before the hosting view's own
21304     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21305     * onDrag(event) behavior, it should return 'false' from this callback.
21306     *
21307     * <div class="special reference">
21308     * <h3>Developer Guides</h3>
21309     * <p>For a guide to implementing drag and drop features, read the
21310     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21311     * </div>
21312     */
21313    public interface OnDragListener {
21314        /**
21315         * Called when a drag event is dispatched to a view. This allows listeners
21316         * to get a chance to override base View behavior.
21317         *
21318         * @param v The View that received the drag event.
21319         * @param event The {@link android.view.DragEvent} object for the drag event.
21320         * @return {@code true} if the drag event was handled successfully, or {@code false}
21321         * if the drag event was not handled. Note that {@code false} will trigger the View
21322         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21323         */
21324        boolean onDrag(View v, DragEvent event);
21325    }
21326
21327    /**
21328     * Interface definition for a callback to be invoked when the focus state of
21329     * a view changed.
21330     */
21331    public interface OnFocusChangeListener {
21332        /**
21333         * Called when the focus state of a view has changed.
21334         *
21335         * @param v The view whose state has changed.
21336         * @param hasFocus The new focus state of v.
21337         */
21338        void onFocusChange(View v, boolean hasFocus);
21339    }
21340
21341    /**
21342     * Interface definition for a callback to be invoked when a view is clicked.
21343     */
21344    public interface OnClickListener {
21345        /**
21346         * Called when a view has been clicked.
21347         *
21348         * @param v The view that was clicked.
21349         */
21350        void onClick(View v);
21351    }
21352
21353    /**
21354     * Interface definition for a callback to be invoked when a view is context clicked.
21355     */
21356    public interface OnContextClickListener {
21357        /**
21358         * Called when a view is context clicked.
21359         *
21360         * @param v The view that has been context clicked.
21361         * @return true if the callback consumed the context click, false otherwise.
21362         */
21363        boolean onContextClick(View v);
21364    }
21365
21366    /**
21367     * Interface definition for a callback to be invoked when the context menu
21368     * for this view is being built.
21369     */
21370    public interface OnCreateContextMenuListener {
21371        /**
21372         * Called when the context menu for this view is being built. It is not
21373         * safe to hold onto the menu after this method returns.
21374         *
21375         * @param menu The context menu that is being built
21376         * @param v The view for which the context menu is being built
21377         * @param menuInfo Extra information about the item for which the
21378         *            context menu should be shown. This information will vary
21379         *            depending on the class of v.
21380         */
21381        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21382    }
21383
21384    /**
21385     * Interface definition for a callback to be invoked when the status bar changes
21386     * visibility.  This reports <strong>global</strong> changes to the system UI
21387     * state, not what the application is requesting.
21388     *
21389     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21390     */
21391    public interface OnSystemUiVisibilityChangeListener {
21392        /**
21393         * Called when the status bar changes visibility because of a call to
21394         * {@link View#setSystemUiVisibility(int)}.
21395         *
21396         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21397         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21398         * This tells you the <strong>global</strong> state of these UI visibility
21399         * flags, not what your app is currently applying.
21400         */
21401        public void onSystemUiVisibilityChange(int visibility);
21402    }
21403
21404    /**
21405     * Interface definition for a callback to be invoked when this view is attached
21406     * or detached from its window.
21407     */
21408    public interface OnAttachStateChangeListener {
21409        /**
21410         * Called when the view is attached to a window.
21411         * @param v The view that was attached
21412         */
21413        public void onViewAttachedToWindow(View v);
21414        /**
21415         * Called when the view is detached from a window.
21416         * @param v The view that was detached
21417         */
21418        public void onViewDetachedFromWindow(View v);
21419    }
21420
21421    /**
21422     * Listener for applying window insets on a view in a custom way.
21423     *
21424     * <p>Apps may choose to implement this interface if they want to apply custom policy
21425     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21426     * is set, its
21427     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21428     * method will be called instead of the View's own
21429     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21430     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21431     * the View's normal behavior as part of its own.</p>
21432     */
21433    public interface OnApplyWindowInsetsListener {
21434        /**
21435         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21436         * on a View, this listener method will be called instead of the view's own
21437         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21438         *
21439         * @param v The view applying window insets
21440         * @param insets The insets to apply
21441         * @return The insets supplied, minus any insets that were consumed
21442         */
21443        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21444    }
21445
21446    private final class UnsetPressedState implements Runnable {
21447        @Override
21448        public void run() {
21449            setPressed(false);
21450        }
21451    }
21452
21453    /**
21454     * Base class for derived classes that want to save and restore their own
21455     * state in {@link android.view.View#onSaveInstanceState()}.
21456     */
21457    public static class BaseSavedState extends AbsSavedState {
21458        String mStartActivityRequestWhoSaved;
21459
21460        /**
21461         * Constructor used when reading from a parcel. Reads the state of the superclass.
21462         *
21463         * @param source
21464         */
21465        public BaseSavedState(Parcel source) {
21466            super(source);
21467            mStartActivityRequestWhoSaved = source.readString();
21468        }
21469
21470        /**
21471         * Constructor called by derived classes when creating their SavedState objects
21472         *
21473         * @param superState The state of the superclass of this view
21474         */
21475        public BaseSavedState(Parcelable superState) {
21476            super(superState);
21477        }
21478
21479        @Override
21480        public void writeToParcel(Parcel out, int flags) {
21481            super.writeToParcel(out, flags);
21482            out.writeString(mStartActivityRequestWhoSaved);
21483        }
21484
21485        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21486                new Parcelable.Creator<BaseSavedState>() {
21487            public BaseSavedState createFromParcel(Parcel in) {
21488                return new BaseSavedState(in);
21489            }
21490
21491            public BaseSavedState[] newArray(int size) {
21492                return new BaseSavedState[size];
21493            }
21494        };
21495    }
21496
21497    /**
21498     * A set of information given to a view when it is attached to its parent
21499     * window.
21500     */
21501    final static class AttachInfo {
21502        interface Callbacks {
21503            void playSoundEffect(int effectId);
21504            boolean performHapticFeedback(int effectId, boolean always);
21505        }
21506
21507        /**
21508         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21509         * to a Handler. This class contains the target (View) to invalidate and
21510         * the coordinates of the dirty rectangle.
21511         *
21512         * For performance purposes, this class also implements a pool of up to
21513         * POOL_LIMIT objects that get reused. This reduces memory allocations
21514         * whenever possible.
21515         */
21516        static class InvalidateInfo {
21517            private static final int POOL_LIMIT = 10;
21518
21519            private static final SynchronizedPool<InvalidateInfo> sPool =
21520                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21521
21522            View target;
21523
21524            int left;
21525            int top;
21526            int right;
21527            int bottom;
21528
21529            public static InvalidateInfo obtain() {
21530                InvalidateInfo instance = sPool.acquire();
21531                return (instance != null) ? instance : new InvalidateInfo();
21532            }
21533
21534            public void recycle() {
21535                target = null;
21536                sPool.release(this);
21537            }
21538        }
21539
21540        final IWindowSession mSession;
21541
21542        final IWindow mWindow;
21543
21544        final IBinder mWindowToken;
21545
21546        final Display mDisplay;
21547
21548        final Callbacks mRootCallbacks;
21549
21550        IWindowId mIWindowId;
21551        WindowId mWindowId;
21552
21553        /**
21554         * The top view of the hierarchy.
21555         */
21556        View mRootView;
21557
21558        IBinder mPanelParentWindowToken;
21559
21560        boolean mHardwareAccelerated;
21561        boolean mHardwareAccelerationRequested;
21562        HardwareRenderer mHardwareRenderer;
21563        List<RenderNode> mPendingAnimatingRenderNodes;
21564
21565        /**
21566         * The state of the display to which the window is attached, as reported
21567         * by {@link Display#getState()}.  Note that the display state constants
21568         * declared by {@link Display} do not exactly line up with the screen state
21569         * constants declared by {@link View} (there are more display states than
21570         * screen states).
21571         */
21572        int mDisplayState = Display.STATE_UNKNOWN;
21573
21574        /**
21575         * Scale factor used by the compatibility mode
21576         */
21577        float mApplicationScale;
21578
21579        /**
21580         * Indicates whether the application is in compatibility mode
21581         */
21582        boolean mScalingRequired;
21583
21584        /**
21585         * Left position of this view's window
21586         */
21587        int mWindowLeft;
21588
21589        /**
21590         * Top position of this view's window
21591         */
21592        int mWindowTop;
21593
21594        /**
21595         * Indicates whether views need to use 32-bit drawing caches
21596         */
21597        boolean mUse32BitDrawingCache;
21598
21599        /**
21600         * For windows that are full-screen but using insets to layout inside
21601         * of the screen areas, these are the current insets to appear inside
21602         * the overscan area of the display.
21603         */
21604        final Rect mOverscanInsets = new Rect();
21605
21606        /**
21607         * For windows that are full-screen but using insets to layout inside
21608         * of the screen decorations, these are the current insets for the
21609         * content of the window.
21610         */
21611        final Rect mContentInsets = new Rect();
21612
21613        /**
21614         * For windows that are full-screen but using insets to layout inside
21615         * of the screen decorations, these are the current insets for the
21616         * actual visible parts of the window.
21617         */
21618        final Rect mVisibleInsets = new Rect();
21619
21620        /**
21621         * For windows that are full-screen but using insets to layout inside
21622         * of the screen decorations, these are the current insets for the
21623         * stable system windows.
21624         */
21625        final Rect mStableInsets = new Rect();
21626
21627        /**
21628         * For windows that include areas that are not covered by real surface these are the outsets
21629         * for real surface.
21630         */
21631        final Rect mOutsets = new Rect();
21632
21633        /**
21634         * The internal insets given by this window.  This value is
21635         * supplied by the client (through
21636         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21637         * be given to the window manager when changed to be used in laying
21638         * out windows behind it.
21639         */
21640        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21641                = new ViewTreeObserver.InternalInsetsInfo();
21642
21643        /**
21644         * Set to true when mGivenInternalInsets is non-empty.
21645         */
21646        boolean mHasNonEmptyGivenInternalInsets;
21647
21648        /**
21649         * All views in the window's hierarchy that serve as scroll containers,
21650         * used to determine if the window can be resized or must be panned
21651         * to adjust for a soft input area.
21652         */
21653        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21654
21655        final KeyEvent.DispatcherState mKeyDispatchState
21656                = new KeyEvent.DispatcherState();
21657
21658        /**
21659         * Indicates whether the view's window currently has the focus.
21660         */
21661        boolean mHasWindowFocus;
21662
21663        /**
21664         * The current visibility of the window.
21665         */
21666        int mWindowVisibility;
21667
21668        /**
21669         * Indicates the time at which drawing started to occur.
21670         */
21671        long mDrawingTime;
21672
21673        /**
21674         * Indicates whether or not ignoring the DIRTY_MASK flags.
21675         */
21676        boolean mIgnoreDirtyState;
21677
21678        /**
21679         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21680         * to avoid clearing that flag prematurely.
21681         */
21682        boolean mSetIgnoreDirtyState = false;
21683
21684        /**
21685         * Indicates whether the view's window is currently in touch mode.
21686         */
21687        boolean mInTouchMode;
21688
21689        /**
21690         * Indicates whether the view has requested unbuffered input dispatching for the current
21691         * event stream.
21692         */
21693        boolean mUnbufferedDispatchRequested;
21694
21695        /**
21696         * Indicates that ViewAncestor should trigger a global layout change
21697         * the next time it performs a traversal
21698         */
21699        boolean mRecomputeGlobalAttributes;
21700
21701        /**
21702         * Always report new attributes at next traversal.
21703         */
21704        boolean mForceReportNewAttributes;
21705
21706        /**
21707         * Set during a traveral if any views want to keep the screen on.
21708         */
21709        boolean mKeepScreenOn;
21710
21711        /**
21712         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21713         */
21714        int mSystemUiVisibility;
21715
21716        /**
21717         * Hack to force certain system UI visibility flags to be cleared.
21718         */
21719        int mDisabledSystemUiVisibility;
21720
21721        /**
21722         * Last global system UI visibility reported by the window manager.
21723         */
21724        int mGlobalSystemUiVisibility;
21725
21726        /**
21727         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21728         * attached.
21729         */
21730        boolean mHasSystemUiListeners;
21731
21732        /**
21733         * Set if the window has requested to extend into the overscan region
21734         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21735         */
21736        boolean mOverscanRequested;
21737
21738        /**
21739         * Set if the visibility of any views has changed.
21740         */
21741        boolean mViewVisibilityChanged;
21742
21743        /**
21744         * Set to true if a view has been scrolled.
21745         */
21746        boolean mViewScrollChanged;
21747
21748        /**
21749         * Set to true if high contrast mode enabled
21750         */
21751        boolean mHighContrastText;
21752
21753        /**
21754         * Global to the view hierarchy used as a temporary for dealing with
21755         * x/y points in the transparent region computations.
21756         */
21757        final int[] mTransparentLocation = new int[2];
21758
21759        /**
21760         * Global to the view hierarchy used as a temporary for dealing with
21761         * x/y points in the ViewGroup.invalidateChild implementation.
21762         */
21763        final int[] mInvalidateChildLocation = new int[2];
21764
21765        /**
21766         * Global to the view hierarchy used as a temporary for dealng with
21767         * computing absolute on-screen location.
21768         */
21769        final int[] mTmpLocation = new int[2];
21770
21771        /**
21772         * Global to the view hierarchy used as a temporary for dealing with
21773         * x/y location when view is transformed.
21774         */
21775        final float[] mTmpTransformLocation = new float[2];
21776
21777        /**
21778         * The view tree observer used to dispatch global events like
21779         * layout, pre-draw, touch mode change, etc.
21780         */
21781        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21782
21783        /**
21784         * A Canvas used by the view hierarchy to perform bitmap caching.
21785         */
21786        Canvas mCanvas;
21787
21788        /**
21789         * The view root impl.
21790         */
21791        final ViewRootImpl mViewRootImpl;
21792
21793        /**
21794         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21795         * handler can be used to pump events in the UI events queue.
21796         */
21797        final Handler mHandler;
21798
21799        /**
21800         * Temporary for use in computing invalidate rectangles while
21801         * calling up the hierarchy.
21802         */
21803        final Rect mTmpInvalRect = new Rect();
21804
21805        /**
21806         * Temporary for use in computing hit areas with transformed views
21807         */
21808        final RectF mTmpTransformRect = new RectF();
21809
21810        /**
21811         * Temporary for use in computing hit areas with transformed views
21812         */
21813        final RectF mTmpTransformRect1 = new RectF();
21814
21815        /**
21816         * Temporary list of rectanges.
21817         */
21818        final List<RectF> mTmpRectList = new ArrayList<>();
21819
21820        /**
21821         * Temporary for use in transforming invalidation rect
21822         */
21823        final Matrix mTmpMatrix = new Matrix();
21824
21825        /**
21826         * Temporary for use in transforming invalidation rect
21827         */
21828        final Transformation mTmpTransformation = new Transformation();
21829
21830        /**
21831         * Temporary for use in querying outlines from OutlineProviders
21832         */
21833        final Outline mTmpOutline = new Outline();
21834
21835        /**
21836         * Temporary list for use in collecting focusable descendents of a view.
21837         */
21838        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21839
21840        /**
21841         * The id of the window for accessibility purposes.
21842         */
21843        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21844
21845        /**
21846         * Flags related to accessibility processing.
21847         *
21848         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21849         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21850         */
21851        int mAccessibilityFetchFlags;
21852
21853        /**
21854         * The drawable for highlighting accessibility focus.
21855         */
21856        Drawable mAccessibilityFocusDrawable;
21857
21858        /**
21859         * Show where the margins, bounds and layout bounds are for each view.
21860         */
21861        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21862
21863        /**
21864         * Point used to compute visible regions.
21865         */
21866        final Point mPoint = new Point();
21867
21868        /**
21869         * Used to track which View originated a requestLayout() call, used when
21870         * requestLayout() is called during layout.
21871         */
21872        View mViewRequestingLayout;
21873
21874        /**
21875         * Creates a new set of attachment information with the specified
21876         * events handler and thread.
21877         *
21878         * @param handler the events handler the view must use
21879         */
21880        AttachInfo(IWindowSession session, IWindow window, Display display,
21881                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21882            mSession = session;
21883            mWindow = window;
21884            mWindowToken = window.asBinder();
21885            mDisplay = display;
21886            mViewRootImpl = viewRootImpl;
21887            mHandler = handler;
21888            mRootCallbacks = effectPlayer;
21889        }
21890    }
21891
21892    /**
21893     * <p>ScrollabilityCache holds various fields used by a View when scrolling
21894     * is supported. This avoids keeping too many unused fields in most
21895     * instances of View.</p>
21896     */
21897    private static class ScrollabilityCache implements Runnable {
21898
21899        /**
21900         * Scrollbars are not visible
21901         */
21902        public static final int OFF = 0;
21903
21904        /**
21905         * Scrollbars are visible
21906         */
21907        public static final int ON = 1;
21908
21909        /**
21910         * Scrollbars are fading away
21911         */
21912        public static final int FADING = 2;
21913
21914        public boolean fadeScrollBars;
21915
21916        public int fadingEdgeLength;
21917        public int scrollBarDefaultDelayBeforeFade;
21918        public int scrollBarFadeDuration;
21919
21920        public int scrollBarSize;
21921        public ScrollBarDrawable scrollBar;
21922        public float[] interpolatorValues;
21923        public View host;
21924
21925        public final Paint paint;
21926        public final Matrix matrix;
21927        public Shader shader;
21928
21929        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21930
21931        private static final float[] OPAQUE = { 255 };
21932        private static final float[] TRANSPARENT = { 0.0f };
21933
21934        /**
21935         * When fading should start. This time moves into the future every time
21936         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21937         */
21938        public long fadeStartTime;
21939
21940
21941        /**
21942         * The current state of the scrollbars: ON, OFF, or FADING
21943         */
21944        public int state = OFF;
21945
21946        private int mLastColor;
21947
21948        public ScrollabilityCache(ViewConfiguration configuration, View host) {
21949            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21950            scrollBarSize = configuration.getScaledScrollBarSize();
21951            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21952            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21953
21954            paint = new Paint();
21955            matrix = new Matrix();
21956            // use use a height of 1, and then wack the matrix each time we
21957            // actually use it.
21958            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21959            paint.setShader(shader);
21960            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21961
21962            this.host = host;
21963        }
21964
21965        public void setFadeColor(int color) {
21966            if (color != mLastColor) {
21967                mLastColor = color;
21968
21969                if (color != 0) {
21970                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21971                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21972                    paint.setShader(shader);
21973                    // Restore the default transfer mode (src_over)
21974                    paint.setXfermode(null);
21975                } else {
21976                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21977                    paint.setShader(shader);
21978                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21979                }
21980            }
21981        }
21982
21983        public void run() {
21984            long now = AnimationUtils.currentAnimationTimeMillis();
21985            if (now >= fadeStartTime) {
21986
21987                // the animation fades the scrollbars out by changing
21988                // the opacity (alpha) from fully opaque to fully
21989                // transparent
21990                int nextFrame = (int) now;
21991                int framesCount = 0;
21992
21993                Interpolator interpolator = scrollBarInterpolator;
21994
21995                // Start opaque
21996                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21997
21998                // End transparent
21999                nextFrame += scrollBarFadeDuration;
22000                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
22001
22002                state = FADING;
22003
22004                // Kick off the fade animation
22005                host.invalidate(true);
22006            }
22007        }
22008    }
22009
22010    /**
22011     * Resuable callback for sending
22012     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22013     */
22014    private class SendViewScrolledAccessibilityEvent implements Runnable {
22015        public volatile boolean mIsPending;
22016
22017        public void run() {
22018            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22019            mIsPending = false;
22020        }
22021    }
22022
22023    /**
22024     * <p>
22025     * This class represents a delegate that can be registered in a {@link View}
22026     * to enhance accessibility support via composition rather via inheritance.
22027     * It is specifically targeted to widget developers that extend basic View
22028     * classes i.e. classes in package android.view, that would like their
22029     * applications to be backwards compatible.
22030     * </p>
22031     * <div class="special reference">
22032     * <h3>Developer Guides</h3>
22033     * <p>For more information about making applications accessible, read the
22034     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22035     * developer guide.</p>
22036     * </div>
22037     * <p>
22038     * A scenario in which a developer would like to use an accessibility delegate
22039     * is overriding a method introduced in a later API version then the minimal API
22040     * version supported by the application. For example, the method
22041     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22042     * in API version 4 when the accessibility APIs were first introduced. If a
22043     * developer would like his application to run on API version 4 devices (assuming
22044     * all other APIs used by the application are version 4 or lower) and take advantage
22045     * of this method, instead of overriding the method which would break the application's
22046     * backwards compatibility, he can override the corresponding method in this
22047     * delegate and register the delegate in the target View if the API version of
22048     * the system is high enough i.e. the API version is same or higher to the API
22049     * version that introduced
22050     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22051     * </p>
22052     * <p>
22053     * Here is an example implementation:
22054     * </p>
22055     * <code><pre><p>
22056     * if (Build.VERSION.SDK_INT >= 14) {
22057     *     // If the API version is equal of higher than the version in
22058     *     // which onInitializeAccessibilityNodeInfo was introduced we
22059     *     // register a delegate with a customized implementation.
22060     *     View view = findViewById(R.id.view_id);
22061     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22062     *         public void onInitializeAccessibilityNodeInfo(View host,
22063     *                 AccessibilityNodeInfo info) {
22064     *             // Let the default implementation populate the info.
22065     *             super.onInitializeAccessibilityNodeInfo(host, info);
22066     *             // Set some other information.
22067     *             info.setEnabled(host.isEnabled());
22068     *         }
22069     *     });
22070     * }
22071     * </code></pre></p>
22072     * <p>
22073     * This delegate contains methods that correspond to the accessibility methods
22074     * in View. If a delegate has been specified the implementation in View hands
22075     * off handling to the corresponding method in this delegate. The default
22076     * implementation the delegate methods behaves exactly as the corresponding
22077     * method in View for the case of no accessibility delegate been set. Hence,
22078     * to customize the behavior of a View method, clients can override only the
22079     * corresponding delegate method without altering the behavior of the rest
22080     * accessibility related methods of the host view.
22081     * </p>
22082     */
22083    public static class AccessibilityDelegate {
22084
22085        /**
22086         * Sends an accessibility event of the given type. If accessibility is not
22087         * enabled this method has no effect.
22088         * <p>
22089         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22090         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22091         * been set.
22092         * </p>
22093         *
22094         * @param host The View hosting the delegate.
22095         * @param eventType The type of the event to send.
22096         *
22097         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22098         */
22099        public void sendAccessibilityEvent(View host, int eventType) {
22100            host.sendAccessibilityEventInternal(eventType);
22101        }
22102
22103        /**
22104         * Performs the specified accessibility action on the view. For
22105         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22106         * <p>
22107         * The default implementation behaves as
22108         * {@link View#performAccessibilityAction(int, Bundle)
22109         *  View#performAccessibilityAction(int, Bundle)} for the case of
22110         *  no accessibility delegate been set.
22111         * </p>
22112         *
22113         * @param action The action to perform.
22114         * @return Whether the action was performed.
22115         *
22116         * @see View#performAccessibilityAction(int, Bundle)
22117         *      View#performAccessibilityAction(int, Bundle)
22118         */
22119        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22120            return host.performAccessibilityActionInternal(action, args);
22121        }
22122
22123        /**
22124         * Sends an accessibility event. This method behaves exactly as
22125         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22126         * empty {@link AccessibilityEvent} and does not perform a check whether
22127         * accessibility is enabled.
22128         * <p>
22129         * The default implementation behaves as
22130         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22131         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22132         * the case of no accessibility delegate been set.
22133         * </p>
22134         *
22135         * @param host The View hosting the delegate.
22136         * @param event The event to send.
22137         *
22138         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22139         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22140         */
22141        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22142            host.sendAccessibilityEventUncheckedInternal(event);
22143        }
22144
22145        /**
22146         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22147         * to its children for adding their text content to the event.
22148         * <p>
22149         * The default implementation behaves as
22150         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22151         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22152         * the case of no accessibility delegate been set.
22153         * </p>
22154         *
22155         * @param host The View hosting the delegate.
22156         * @param event The event.
22157         * @return True if the event population was completed.
22158         *
22159         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22160         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22161         */
22162        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22163            return host.dispatchPopulateAccessibilityEventInternal(event);
22164        }
22165
22166        /**
22167         * Gives a chance to the host View to populate the accessibility event with its
22168         * text content.
22169         * <p>
22170         * The default implementation behaves as
22171         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22172         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22173         * the case of no accessibility delegate been set.
22174         * </p>
22175         *
22176         * @param host The View hosting the delegate.
22177         * @param event The accessibility event which to populate.
22178         *
22179         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22180         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22181         */
22182        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22183            host.onPopulateAccessibilityEventInternal(event);
22184        }
22185
22186        /**
22187         * Initializes an {@link AccessibilityEvent} with information about the
22188         * the host View which is the event source.
22189         * <p>
22190         * The default implementation behaves as
22191         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22192         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22193         * the case of no accessibility delegate been set.
22194         * </p>
22195         *
22196         * @param host The View hosting the delegate.
22197         * @param event The event to initialize.
22198         *
22199         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22200         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22201         */
22202        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22203            host.onInitializeAccessibilityEventInternal(event);
22204        }
22205
22206        /**
22207         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22208         * <p>
22209         * The default implementation behaves as
22210         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22211         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22212         * the case of no accessibility delegate been set.
22213         * </p>
22214         *
22215         * @param host The View hosting the delegate.
22216         * @param info The instance to initialize.
22217         *
22218         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22219         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22220         */
22221        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22222            host.onInitializeAccessibilityNodeInfoInternal(info);
22223        }
22224
22225        /**
22226         * Called when a child of the host View has requested sending an
22227         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22228         * to augment the event.
22229         * <p>
22230         * The default implementation behaves as
22231         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22232         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22233         * the case of no accessibility delegate been set.
22234         * </p>
22235         *
22236         * @param host The View hosting the delegate.
22237         * @param child The child which requests sending the event.
22238         * @param event The event to be sent.
22239         * @return True if the event should be sent
22240         *
22241         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22242         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22243         */
22244        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22245                AccessibilityEvent event) {
22246            return host.onRequestSendAccessibilityEventInternal(child, event);
22247        }
22248
22249        /**
22250         * Gets the provider for managing a virtual view hierarchy rooted at this View
22251         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22252         * that explore the window content.
22253         * <p>
22254         * The default implementation behaves as
22255         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22256         * the case of no accessibility delegate been set.
22257         * </p>
22258         *
22259         * @return The provider.
22260         *
22261         * @see AccessibilityNodeProvider
22262         */
22263        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22264            return null;
22265        }
22266
22267        /**
22268         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22269         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22270         * This method is responsible for obtaining an accessibility node info from a
22271         * pool of reusable instances and calling
22272         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22273         * view to initialize the former.
22274         * <p>
22275         * <strong>Note:</strong> The client is responsible for recycling the obtained
22276         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22277         * creation.
22278         * </p>
22279         * <p>
22280         * The default implementation behaves as
22281         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22282         * the case of no accessibility delegate been set.
22283         * </p>
22284         * @return A populated {@link AccessibilityNodeInfo}.
22285         *
22286         * @see AccessibilityNodeInfo
22287         *
22288         * @hide
22289         */
22290        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22291            return host.createAccessibilityNodeInfoInternal();
22292        }
22293    }
22294
22295    private class MatchIdPredicate implements Predicate<View> {
22296        public int mId;
22297
22298        @Override
22299        public boolean apply(View view) {
22300            return (view.mID == mId);
22301        }
22302    }
22303
22304    private class MatchLabelForPredicate implements Predicate<View> {
22305        private int mLabeledId;
22306
22307        @Override
22308        public boolean apply(View view) {
22309            return (view.mLabelForId == mLabeledId);
22310        }
22311    }
22312
22313    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22314        private int mChangeTypes = 0;
22315        private boolean mPosted;
22316        private boolean mPostedWithDelay;
22317        private long mLastEventTimeMillis;
22318
22319        @Override
22320        public void run() {
22321            mPosted = false;
22322            mPostedWithDelay = false;
22323            mLastEventTimeMillis = SystemClock.uptimeMillis();
22324            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22325                final AccessibilityEvent event = AccessibilityEvent.obtain();
22326                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22327                event.setContentChangeTypes(mChangeTypes);
22328                sendAccessibilityEventUnchecked(event);
22329            }
22330            mChangeTypes = 0;
22331        }
22332
22333        public void runOrPost(int changeType) {
22334            mChangeTypes |= changeType;
22335
22336            // If this is a live region or the child of a live region, collect
22337            // all events from this frame and send them on the next frame.
22338            if (inLiveRegion()) {
22339                // If we're already posted with a delay, remove that.
22340                if (mPostedWithDelay) {
22341                    removeCallbacks(this);
22342                    mPostedWithDelay = false;
22343                }
22344                // Only post if we're not already posted.
22345                if (!mPosted) {
22346                    post(this);
22347                    mPosted = true;
22348                }
22349                return;
22350            }
22351
22352            if (mPosted) {
22353                return;
22354            }
22355
22356            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22357            final long minEventIntevalMillis =
22358                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22359            if (timeSinceLastMillis >= minEventIntevalMillis) {
22360                removeCallbacks(this);
22361                run();
22362            } else {
22363                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22364                mPostedWithDelay = true;
22365            }
22366        }
22367    }
22368
22369    private boolean inLiveRegion() {
22370        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22371            return true;
22372        }
22373
22374        ViewParent parent = getParent();
22375        while (parent instanceof View) {
22376            if (((View) parent).getAccessibilityLiveRegion()
22377                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22378                return true;
22379            }
22380            parent = parent.getParent();
22381        }
22382
22383        return false;
22384    }
22385
22386    /**
22387     * Dump all private flags in readable format, useful for documentation and
22388     * sanity checking.
22389     */
22390    private static void dumpFlags() {
22391        final HashMap<String, String> found = Maps.newHashMap();
22392        try {
22393            for (Field field : View.class.getDeclaredFields()) {
22394                final int modifiers = field.getModifiers();
22395                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22396                    if (field.getType().equals(int.class)) {
22397                        final int value = field.getInt(null);
22398                        dumpFlag(found, field.getName(), value);
22399                    } else if (field.getType().equals(int[].class)) {
22400                        final int[] values = (int[]) field.get(null);
22401                        for (int i = 0; i < values.length; i++) {
22402                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22403                        }
22404                    }
22405                }
22406            }
22407        } catch (IllegalAccessException e) {
22408            throw new RuntimeException(e);
22409        }
22410
22411        final ArrayList<String> keys = Lists.newArrayList();
22412        keys.addAll(found.keySet());
22413        Collections.sort(keys);
22414        for (String key : keys) {
22415            Log.d(VIEW_LOG_TAG, found.get(key));
22416        }
22417    }
22418
22419    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22420        // Sort flags by prefix, then by bits, always keeping unique keys
22421        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22422        final int prefix = name.indexOf('_');
22423        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22424        final String output = bits + " " + name;
22425        found.put(key, output);
22426    }
22427
22428    /** {@hide} */
22429    public void encode(@NonNull ViewHierarchyEncoder stream) {
22430        stream.beginObject(this);
22431        encodeProperties(stream);
22432        stream.endObject();
22433    }
22434
22435    /** {@hide} */
22436    @CallSuper
22437    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22438        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22439        if (resolveId instanceof String) {
22440            stream.addProperty("id", (String) resolveId);
22441        } else {
22442            stream.addProperty("id", mID);
22443        }
22444
22445        stream.addProperty("misc:transformation.alpha",
22446                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22447        stream.addProperty("misc:transitionName", getTransitionName());
22448
22449        // layout
22450        stream.addProperty("layout:left", mLeft);
22451        stream.addProperty("layout:right", mRight);
22452        stream.addProperty("layout:top", mTop);
22453        stream.addProperty("layout:bottom", mBottom);
22454        stream.addProperty("layout:width", getWidth());
22455        stream.addProperty("layout:height", getHeight());
22456        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22457        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22458        stream.addProperty("layout:hasTransientState", hasTransientState());
22459        stream.addProperty("layout:baseline", getBaseline());
22460
22461        // layout params
22462        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22463        if (layoutParams != null) {
22464            stream.addPropertyKey("layoutParams");
22465            layoutParams.encode(stream);
22466        }
22467
22468        // scrolling
22469        stream.addProperty("scrolling:scrollX", mScrollX);
22470        stream.addProperty("scrolling:scrollY", mScrollY);
22471
22472        // padding
22473        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22474        stream.addProperty("padding:paddingRight", mPaddingRight);
22475        stream.addProperty("padding:paddingTop", mPaddingTop);
22476        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22477        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22478        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22479        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22480        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22481        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22482
22483        // measurement
22484        stream.addProperty("measurement:minHeight", mMinHeight);
22485        stream.addProperty("measurement:minWidth", mMinWidth);
22486        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22487        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22488
22489        // drawing
22490        stream.addProperty("drawing:elevation", getElevation());
22491        stream.addProperty("drawing:translationX", getTranslationX());
22492        stream.addProperty("drawing:translationY", getTranslationY());
22493        stream.addProperty("drawing:translationZ", getTranslationZ());
22494        stream.addProperty("drawing:rotation", getRotation());
22495        stream.addProperty("drawing:rotationX", getRotationX());
22496        stream.addProperty("drawing:rotationY", getRotationY());
22497        stream.addProperty("drawing:scaleX", getScaleX());
22498        stream.addProperty("drawing:scaleY", getScaleY());
22499        stream.addProperty("drawing:pivotX", getPivotX());
22500        stream.addProperty("drawing:pivotY", getPivotY());
22501        stream.addProperty("drawing:opaque", isOpaque());
22502        stream.addProperty("drawing:alpha", getAlpha());
22503        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22504        stream.addProperty("drawing:shadow", hasShadow());
22505        stream.addProperty("drawing:solidColor", getSolidColor());
22506        stream.addProperty("drawing:layerType", mLayerType);
22507        stream.addProperty("drawing:willNotDraw", willNotDraw());
22508        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22509        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22510        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22511        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22512
22513        // focus
22514        stream.addProperty("focus:hasFocus", hasFocus());
22515        stream.addProperty("focus:isFocused", isFocused());
22516        stream.addProperty("focus:isFocusable", isFocusable());
22517        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22518
22519        stream.addProperty("misc:clickable", isClickable());
22520        stream.addProperty("misc:pressed", isPressed());
22521        stream.addProperty("misc:selected", isSelected());
22522        stream.addProperty("misc:touchMode", isInTouchMode());
22523        stream.addProperty("misc:hovered", isHovered());
22524        stream.addProperty("misc:activated", isActivated());
22525
22526        stream.addProperty("misc:visibility", getVisibility());
22527        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22528        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22529
22530        stream.addProperty("misc:enabled", isEnabled());
22531        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22532        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22533
22534        // theme attributes
22535        Resources.Theme theme = getContext().getTheme();
22536        if (theme != null) {
22537            stream.addPropertyKey("theme");
22538            theme.encode(stream);
22539        }
22540
22541        // view attribute information
22542        int n = mAttributes != null ? mAttributes.length : 0;
22543        stream.addProperty("meta:__attrCount__", n/2);
22544        for (int i = 0; i < n; i += 2) {
22545            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22546        }
22547
22548        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22549
22550        // text
22551        stream.addProperty("text:textDirection", getTextDirection());
22552        stream.addProperty("text:textAlignment", getTextAlignment());
22553
22554        // accessibility
22555        CharSequence contentDescription = getContentDescription();
22556        stream.addProperty("accessibility:contentDescription",
22557                contentDescription == null ? "" : contentDescription.toString());
22558        stream.addProperty("accessibility:labelFor", getLabelFor());
22559        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22560    }
22561}
22562