View.java revision d35dcb13115ca1dd8c07e397f43a186cd7fd1a01
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     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
757     * calling setFlags.
758     */
759    private static final int NOT_FOCUSABLE = 0x00000000;
760
761    /**
762     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
763     * setFlags.
764     */
765    private static final int FOCUSABLE = 0x00000001;
766
767    /**
768     * Mask for use with setFlags indicating bits used for focus.
769     */
770    private static final int FOCUSABLE_MASK = 0x00000001;
771
772    /**
773     * This view will adjust its padding to fit sytem windows (e.g. status bar)
774     */
775    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
776
777    /** @hide */
778    @IntDef({VISIBLE, INVISIBLE, GONE})
779    @Retention(RetentionPolicy.SOURCE)
780    public @interface Visibility {}
781
782    /**
783     * This view is visible.
784     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
785     * android:visibility}.
786     */
787    public static final int VISIBLE = 0x00000000;
788
789    /**
790     * This view is invisible, but it still takes up space for layout purposes.
791     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
792     * android:visibility}.
793     */
794    public static final int INVISIBLE = 0x00000004;
795
796    /**
797     * This view is invisible, and it doesn't take any space for layout
798     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
799     * android:visibility}.
800     */
801    public static final int GONE = 0x00000008;
802
803    /**
804     * Mask for use with setFlags indicating bits used for visibility.
805     * {@hide}
806     */
807    static final int VISIBILITY_MASK = 0x0000000C;
808
809    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
810
811    /**
812     * This view is enabled. Interpretation varies by subclass.
813     * Use with ENABLED_MASK when calling setFlags.
814     * {@hide}
815     */
816    static final int ENABLED = 0x00000000;
817
818    /**
819     * This view is disabled. Interpretation varies by subclass.
820     * Use with ENABLED_MASK when calling setFlags.
821     * {@hide}
822     */
823    static final int DISABLED = 0x00000020;
824
825   /**
826    * Mask for use with setFlags indicating bits used for indicating whether
827    * this view is enabled
828    * {@hide}
829    */
830    static final int ENABLED_MASK = 0x00000020;
831
832    /**
833     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
834     * called and further optimizations will be performed. It is okay to have
835     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
836     * {@hide}
837     */
838    static final int WILL_NOT_DRAW = 0x00000080;
839
840    /**
841     * Mask for use with setFlags indicating bits used for indicating whether
842     * this view is will draw
843     * {@hide}
844     */
845    static final int DRAW_MASK = 0x00000080;
846
847    /**
848     * <p>This view doesn't show scrollbars.</p>
849     * {@hide}
850     */
851    static final int SCROLLBARS_NONE = 0x00000000;
852
853    /**
854     * <p>This view shows horizontal scrollbars.</p>
855     * {@hide}
856     */
857    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
858
859    /**
860     * <p>This view shows vertical scrollbars.</p>
861     * {@hide}
862     */
863    static final int SCROLLBARS_VERTICAL = 0x00000200;
864
865    /**
866     * <p>Mask for use with setFlags indicating bits used for indicating which
867     * scrollbars are enabled.</p>
868     * {@hide}
869     */
870    static final int SCROLLBARS_MASK = 0x00000300;
871
872    /**
873     * Indicates that the view should filter touches when its window is obscured.
874     * Refer to the class comments for more information about this security feature.
875     * {@hide}
876     */
877    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
878
879    /**
880     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
881     * that they are optional and should be skipped if the window has
882     * requested system UI flags that ignore those insets for layout.
883     */
884    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
885
886    /**
887     * <p>This view doesn't show fading edges.</p>
888     * {@hide}
889     */
890    static final int FADING_EDGE_NONE = 0x00000000;
891
892    /**
893     * <p>This view shows horizontal fading edges.</p>
894     * {@hide}
895     */
896    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
897
898    /**
899     * <p>This view shows vertical fading edges.</p>
900     * {@hide}
901     */
902    static final int FADING_EDGE_VERTICAL = 0x00002000;
903
904    /**
905     * <p>Mask for use with setFlags indicating bits used for indicating which
906     * fading edges are enabled.</p>
907     * {@hide}
908     */
909    static final int FADING_EDGE_MASK = 0x00003000;
910
911    /**
912     * <p>Indicates this view can be clicked. When clickable, a View reacts
913     * to clicks by notifying the OnClickListener.<p>
914     * {@hide}
915     */
916    static final int CLICKABLE = 0x00004000;
917
918    /**
919     * <p>Indicates this view is caching its drawing into a bitmap.</p>
920     * {@hide}
921     */
922    static final int DRAWING_CACHE_ENABLED = 0x00008000;
923
924    /**
925     * <p>Indicates that no icicle should be saved for this view.<p>
926     * {@hide}
927     */
928    static final int SAVE_DISABLED = 0x000010000;
929
930    /**
931     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
932     * property.</p>
933     * {@hide}
934     */
935    static final int SAVE_DISABLED_MASK = 0x000010000;
936
937    /**
938     * <p>Indicates that no drawing cache should ever be created for this view.<p>
939     * {@hide}
940     */
941    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
942
943    /**
944     * <p>Indicates this view can take / keep focus when int touch mode.</p>
945     * {@hide}
946     */
947    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
948
949    /** @hide */
950    @Retention(RetentionPolicy.SOURCE)
951    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
952    public @interface DrawingCacheQuality {}
953
954    /**
955     * <p>Enables low quality mode for the drawing cache.</p>
956     */
957    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
958
959    /**
960     * <p>Enables high quality mode for the drawing cache.</p>
961     */
962    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
963
964    /**
965     * <p>Enables automatic quality mode for the drawing cache.</p>
966     */
967    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
968
969    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
970            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
971    };
972
973    /**
974     * <p>Mask for use with setFlags indicating bits used for the cache
975     * quality property.</p>
976     * {@hide}
977     */
978    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
979
980    /**
981     * <p>
982     * Indicates this view can be long clicked. When long clickable, a View
983     * reacts to long clicks by notifying the OnLongClickListener or showing a
984     * context menu.
985     * </p>
986     * {@hide}
987     */
988    static final int LONG_CLICKABLE = 0x00200000;
989
990    /**
991     * <p>Indicates that this view gets its drawable states from its direct parent
992     * and ignores its original internal states.</p>
993     *
994     * @hide
995     */
996    static final int DUPLICATE_PARENT_STATE = 0x00400000;
997
998    /**
999     * <p>
1000     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1001     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1002     * OnContextClickListener.
1003     * </p>
1004     * {@hide}
1005     */
1006    static final int CONTEXT_CLICKABLE = 0x00800000;
1007
1008
1009    /** @hide */
1010    @IntDef({
1011        SCROLLBARS_INSIDE_OVERLAY,
1012        SCROLLBARS_INSIDE_INSET,
1013        SCROLLBARS_OUTSIDE_OVERLAY,
1014        SCROLLBARS_OUTSIDE_INSET
1015    })
1016    @Retention(RetentionPolicy.SOURCE)
1017    public @interface ScrollBarStyle {}
1018
1019    /**
1020     * The scrollbar style to display the scrollbars inside the content area,
1021     * without increasing the padding. The scrollbars will be overlaid with
1022     * translucency on the view's content.
1023     */
1024    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1025
1026    /**
1027     * The scrollbar style to display the scrollbars inside the padded area,
1028     * increasing the padding of the view. The scrollbars will not overlap the
1029     * content area of the view.
1030     */
1031    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1032
1033    /**
1034     * The scrollbar style to display the scrollbars at the edge of the view,
1035     * without increasing the padding. The scrollbars will be overlaid with
1036     * translucency.
1037     */
1038    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1039
1040    /**
1041     * The scrollbar style to display the scrollbars at the edge of the view,
1042     * increasing the padding of the view. The scrollbars will only overlap the
1043     * background, if any.
1044     */
1045    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1046
1047    /**
1048     * Mask to check if the scrollbar style is overlay or inset.
1049     * {@hide}
1050     */
1051    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1052
1053    /**
1054     * Mask to check if the scrollbar style is inside or outside.
1055     * {@hide}
1056     */
1057    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1058
1059    /**
1060     * Mask for scrollbar style.
1061     * {@hide}
1062     */
1063    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1064
1065    /**
1066     * View flag indicating that the screen should remain on while the
1067     * window containing this view is visible to the user.  This effectively
1068     * takes care of automatically setting the WindowManager's
1069     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1070     */
1071    public static final int KEEP_SCREEN_ON = 0x04000000;
1072
1073    /**
1074     * View flag indicating whether this view should have sound effects enabled
1075     * for events such as clicking and touching.
1076     */
1077    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1078
1079    /**
1080     * View flag indicating whether this view should have haptic feedback
1081     * enabled for events such as long presses.
1082     */
1083    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1084
1085    /**
1086     * <p>Indicates that the view hierarchy should stop saving state when
1087     * it reaches this view.  If state saving is initiated immediately at
1088     * the view, it will be allowed.
1089     * {@hide}
1090     */
1091    static final int PARENT_SAVE_DISABLED = 0x20000000;
1092
1093    /**
1094     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1095     * {@hide}
1096     */
1097    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1098
1099    /** @hide */
1100    @IntDef(flag = true,
1101            value = {
1102                FOCUSABLES_ALL,
1103                FOCUSABLES_TOUCH_MODE
1104            })
1105    @Retention(RetentionPolicy.SOURCE)
1106    public @interface FocusableMode {}
1107
1108    /**
1109     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1110     * should add all focusable Views regardless if they are focusable in touch mode.
1111     */
1112    public static final int FOCUSABLES_ALL = 0x00000000;
1113
1114    /**
1115     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1116     * should add only Views focusable in touch mode.
1117     */
1118    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1119
1120    /** @hide */
1121    @IntDef({
1122            FOCUS_BACKWARD,
1123            FOCUS_FORWARD,
1124            FOCUS_LEFT,
1125            FOCUS_UP,
1126            FOCUS_RIGHT,
1127            FOCUS_DOWN
1128    })
1129    @Retention(RetentionPolicy.SOURCE)
1130    public @interface FocusDirection {}
1131
1132    /** @hide */
1133    @IntDef({
1134            FOCUS_LEFT,
1135            FOCUS_UP,
1136            FOCUS_RIGHT,
1137            FOCUS_DOWN
1138    })
1139    @Retention(RetentionPolicy.SOURCE)
1140    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1141
1142    /**
1143     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1144     * item.
1145     */
1146    public static final int FOCUS_BACKWARD = 0x00000001;
1147
1148    /**
1149     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1150     * item.
1151     */
1152    public static final int FOCUS_FORWARD = 0x00000002;
1153
1154    /**
1155     * Use with {@link #focusSearch(int)}. Move focus to the left.
1156     */
1157    public static final int FOCUS_LEFT = 0x00000011;
1158
1159    /**
1160     * Use with {@link #focusSearch(int)}. Move focus up.
1161     */
1162    public static final int FOCUS_UP = 0x00000021;
1163
1164    /**
1165     * Use with {@link #focusSearch(int)}. Move focus to the right.
1166     */
1167    public static final int FOCUS_RIGHT = 0x00000042;
1168
1169    /**
1170     * Use with {@link #focusSearch(int)}. Move focus down.
1171     */
1172    public static final int FOCUS_DOWN = 0x00000082;
1173
1174    /**
1175     * Bits of {@link #getMeasuredWidthAndState()} and
1176     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1177     */
1178    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1179
1180    /**
1181     * Bits of {@link #getMeasuredWidthAndState()} and
1182     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1183     */
1184    public static final int MEASURED_STATE_MASK = 0xff000000;
1185
1186    /**
1187     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1188     * for functions that combine both width and height into a single int,
1189     * such as {@link #getMeasuredState()} and the childState argument of
1190     * {@link #resolveSizeAndState(int, int, int)}.
1191     */
1192    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1193
1194    /**
1195     * Bit of {@link #getMeasuredWidthAndState()} and
1196     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1197     * is smaller that the space the view would like to have.
1198     */
1199    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1200
1201    /**
1202     * Base View state sets
1203     */
1204    // Singles
1205    /**
1206     * Indicates the view has no states set. States are used with
1207     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1208     * view depending on its state.
1209     *
1210     * @see android.graphics.drawable.Drawable
1211     * @see #getDrawableState()
1212     */
1213    protected static final int[] EMPTY_STATE_SET;
1214    /**
1215     * Indicates the view is enabled. States are used with
1216     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1217     * view depending on its state.
1218     *
1219     * @see android.graphics.drawable.Drawable
1220     * @see #getDrawableState()
1221     */
1222    protected static final int[] ENABLED_STATE_SET;
1223    /**
1224     * Indicates the view is focused. States are used with
1225     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1226     * view depending on its state.
1227     *
1228     * @see android.graphics.drawable.Drawable
1229     * @see #getDrawableState()
1230     */
1231    protected static final int[] FOCUSED_STATE_SET;
1232    /**
1233     * Indicates the view is selected. States are used with
1234     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1235     * view depending on its state.
1236     *
1237     * @see android.graphics.drawable.Drawable
1238     * @see #getDrawableState()
1239     */
1240    protected static final int[] SELECTED_STATE_SET;
1241    /**
1242     * Indicates the view is pressed. States are used with
1243     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1244     * view depending on its state.
1245     *
1246     * @see android.graphics.drawable.Drawable
1247     * @see #getDrawableState()
1248     */
1249    protected static final int[] PRESSED_STATE_SET;
1250    /**
1251     * Indicates the view's window has focus. States are used with
1252     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1253     * view depending on its state.
1254     *
1255     * @see android.graphics.drawable.Drawable
1256     * @see #getDrawableState()
1257     */
1258    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1259    // Doubles
1260    /**
1261     * Indicates the view is enabled and has the focus.
1262     *
1263     * @see #ENABLED_STATE_SET
1264     * @see #FOCUSED_STATE_SET
1265     */
1266    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1267    /**
1268     * Indicates the view is enabled and selected.
1269     *
1270     * @see #ENABLED_STATE_SET
1271     * @see #SELECTED_STATE_SET
1272     */
1273    protected static final int[] ENABLED_SELECTED_STATE_SET;
1274    /**
1275     * Indicates the view is enabled and that its window has focus.
1276     *
1277     * @see #ENABLED_STATE_SET
1278     * @see #WINDOW_FOCUSED_STATE_SET
1279     */
1280    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1281    /**
1282     * Indicates the view is focused and selected.
1283     *
1284     * @see #FOCUSED_STATE_SET
1285     * @see #SELECTED_STATE_SET
1286     */
1287    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1288    /**
1289     * Indicates the view has the focus and that its window has the focus.
1290     *
1291     * @see #FOCUSED_STATE_SET
1292     * @see #WINDOW_FOCUSED_STATE_SET
1293     */
1294    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1295    /**
1296     * Indicates the view is selected and that its window has the focus.
1297     *
1298     * @see #SELECTED_STATE_SET
1299     * @see #WINDOW_FOCUSED_STATE_SET
1300     */
1301    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1302    // Triples
1303    /**
1304     * Indicates the view is enabled, focused and selected.
1305     *
1306     * @see #ENABLED_STATE_SET
1307     * @see #FOCUSED_STATE_SET
1308     * @see #SELECTED_STATE_SET
1309     */
1310    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1311    /**
1312     * Indicates the view is enabled, focused and its window has the focus.
1313     *
1314     * @see #ENABLED_STATE_SET
1315     * @see #FOCUSED_STATE_SET
1316     * @see #WINDOW_FOCUSED_STATE_SET
1317     */
1318    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1319    /**
1320     * Indicates the view is enabled, selected and its window has the focus.
1321     *
1322     * @see #ENABLED_STATE_SET
1323     * @see #SELECTED_STATE_SET
1324     * @see #WINDOW_FOCUSED_STATE_SET
1325     */
1326    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1327    /**
1328     * Indicates the view is focused, selected and its window has the focus.
1329     *
1330     * @see #FOCUSED_STATE_SET
1331     * @see #SELECTED_STATE_SET
1332     * @see #WINDOW_FOCUSED_STATE_SET
1333     */
1334    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1335    /**
1336     * Indicates the view is enabled, focused, selected and its window
1337     * has the focus.
1338     *
1339     * @see #ENABLED_STATE_SET
1340     * @see #FOCUSED_STATE_SET
1341     * @see #SELECTED_STATE_SET
1342     * @see #WINDOW_FOCUSED_STATE_SET
1343     */
1344    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1345    /**
1346     * Indicates the view is pressed and its window has the focus.
1347     *
1348     * @see #PRESSED_STATE_SET
1349     * @see #WINDOW_FOCUSED_STATE_SET
1350     */
1351    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1352    /**
1353     * Indicates the view is pressed and selected.
1354     *
1355     * @see #PRESSED_STATE_SET
1356     * @see #SELECTED_STATE_SET
1357     */
1358    protected static final int[] PRESSED_SELECTED_STATE_SET;
1359    /**
1360     * Indicates the view is pressed, selected and its window has the focus.
1361     *
1362     * @see #PRESSED_STATE_SET
1363     * @see #SELECTED_STATE_SET
1364     * @see #WINDOW_FOCUSED_STATE_SET
1365     */
1366    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1367    /**
1368     * Indicates the view is pressed and focused.
1369     *
1370     * @see #PRESSED_STATE_SET
1371     * @see #FOCUSED_STATE_SET
1372     */
1373    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1374    /**
1375     * Indicates the view is pressed, focused and its window has the focus.
1376     *
1377     * @see #PRESSED_STATE_SET
1378     * @see #FOCUSED_STATE_SET
1379     * @see #WINDOW_FOCUSED_STATE_SET
1380     */
1381    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1382    /**
1383     * Indicates the view is pressed, focused and selected.
1384     *
1385     * @see #PRESSED_STATE_SET
1386     * @see #SELECTED_STATE_SET
1387     * @see #FOCUSED_STATE_SET
1388     */
1389    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1390    /**
1391     * Indicates the view is pressed, focused, selected and its window has the focus.
1392     *
1393     * @see #PRESSED_STATE_SET
1394     * @see #FOCUSED_STATE_SET
1395     * @see #SELECTED_STATE_SET
1396     * @see #WINDOW_FOCUSED_STATE_SET
1397     */
1398    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1399    /**
1400     * Indicates the view is pressed and enabled.
1401     *
1402     * @see #PRESSED_STATE_SET
1403     * @see #ENABLED_STATE_SET
1404     */
1405    protected static final int[] PRESSED_ENABLED_STATE_SET;
1406    /**
1407     * Indicates the view is pressed, enabled and its window has the focus.
1408     *
1409     * @see #PRESSED_STATE_SET
1410     * @see #ENABLED_STATE_SET
1411     * @see #WINDOW_FOCUSED_STATE_SET
1412     */
1413    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1414    /**
1415     * Indicates the view is pressed, enabled and selected.
1416     *
1417     * @see #PRESSED_STATE_SET
1418     * @see #ENABLED_STATE_SET
1419     * @see #SELECTED_STATE_SET
1420     */
1421    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1422    /**
1423     * Indicates the view is pressed, enabled, selected and its window has the
1424     * focus.
1425     *
1426     * @see #PRESSED_STATE_SET
1427     * @see #ENABLED_STATE_SET
1428     * @see #SELECTED_STATE_SET
1429     * @see #WINDOW_FOCUSED_STATE_SET
1430     */
1431    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1432    /**
1433     * Indicates the view is pressed, enabled and focused.
1434     *
1435     * @see #PRESSED_STATE_SET
1436     * @see #ENABLED_STATE_SET
1437     * @see #FOCUSED_STATE_SET
1438     */
1439    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1440    /**
1441     * Indicates the view is pressed, enabled, focused and its window has the
1442     * focus.
1443     *
1444     * @see #PRESSED_STATE_SET
1445     * @see #ENABLED_STATE_SET
1446     * @see #FOCUSED_STATE_SET
1447     * @see #WINDOW_FOCUSED_STATE_SET
1448     */
1449    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1450    /**
1451     * Indicates the view is pressed, enabled, focused and selected.
1452     *
1453     * @see #PRESSED_STATE_SET
1454     * @see #ENABLED_STATE_SET
1455     * @see #SELECTED_STATE_SET
1456     * @see #FOCUSED_STATE_SET
1457     */
1458    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1459    /**
1460     * Indicates the view is pressed, enabled, focused, selected and its window
1461     * has the focus.
1462     *
1463     * @see #PRESSED_STATE_SET
1464     * @see #ENABLED_STATE_SET
1465     * @see #SELECTED_STATE_SET
1466     * @see #FOCUSED_STATE_SET
1467     * @see #WINDOW_FOCUSED_STATE_SET
1468     */
1469    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1470
1471    static {
1472        EMPTY_STATE_SET = StateSet.get(0);
1473
1474        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1475
1476        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1477        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1478                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1479
1480        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1481        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1482                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1483        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1484                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1485        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1486                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1487                        | StateSet.VIEW_STATE_FOCUSED);
1488
1489        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1490        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1491                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1492        ENABLED_SELECTED_STATE_SET = StateSet.get(
1493                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1494        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1495                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1496                        | StateSet.VIEW_STATE_ENABLED);
1497        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1498                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1499        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1500                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1501                        | StateSet.VIEW_STATE_ENABLED);
1502        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1503                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1504                        | StateSet.VIEW_STATE_ENABLED);
1505        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1506                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1507                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1508
1509        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1510        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1511                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1512        PRESSED_SELECTED_STATE_SET = StateSet.get(
1513                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1514        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1515                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1516                        | StateSet.VIEW_STATE_PRESSED);
1517        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1518                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1519        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1520                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1521                        | StateSet.VIEW_STATE_PRESSED);
1522        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1523                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1524                        | StateSet.VIEW_STATE_PRESSED);
1525        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1526                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1527                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1528        PRESSED_ENABLED_STATE_SET = StateSet.get(
1529                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1530        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1532                        | StateSet.VIEW_STATE_PRESSED);
1533        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1534                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1535                        | StateSet.VIEW_STATE_PRESSED);
1536        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1537                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1538                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1539        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1540                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1541                        | StateSet.VIEW_STATE_PRESSED);
1542        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1543                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1544                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1545        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1546                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1547                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1548        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1549                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1550                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1551                        | StateSet.VIEW_STATE_PRESSED);
1552    }
1553
1554    /**
1555     * Accessibility event types that are dispatched for text population.
1556     */
1557    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1558            AccessibilityEvent.TYPE_VIEW_CLICKED
1559            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1560            | AccessibilityEvent.TYPE_VIEW_SELECTED
1561            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1562            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1563            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1564            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1565            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1566            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1567            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1568            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1569
1570    /**
1571     * Temporary Rect currently for use in setBackground().  This will probably
1572     * be extended in the future to hold our own class with more than just
1573     * a Rect. :)
1574     */
1575    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1576
1577    /**
1578     * Map used to store views' tags.
1579     */
1580    private SparseArray<Object> mKeyedTags;
1581
1582    /**
1583     * The next available accessibility id.
1584     */
1585    private static int sNextAccessibilityViewId;
1586
1587    /**
1588     * The animation currently associated with this view.
1589     * @hide
1590     */
1591    protected Animation mCurrentAnimation = null;
1592
1593    /**
1594     * Width as measured during measure pass.
1595     * {@hide}
1596     */
1597    @ViewDebug.ExportedProperty(category = "measurement")
1598    int mMeasuredWidth;
1599
1600    /**
1601     * Height as measured during measure pass.
1602     * {@hide}
1603     */
1604    @ViewDebug.ExportedProperty(category = "measurement")
1605    int mMeasuredHeight;
1606
1607    /**
1608     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1609     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1610     * its display list. This flag, used only when hw accelerated, allows us to clear the
1611     * flag while retaining this information until it's needed (at getDisplayList() time and
1612     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1613     *
1614     * {@hide}
1615     */
1616    boolean mRecreateDisplayList = false;
1617
1618    /**
1619     * The view's identifier.
1620     * {@hide}
1621     *
1622     * @see #setId(int)
1623     * @see #getId()
1624     */
1625    @IdRes
1626    @ViewDebug.ExportedProperty(resolveId = true)
1627    int mID = NO_ID;
1628
1629    /**
1630     * The stable ID of this view for accessibility purposes.
1631     */
1632    int mAccessibilityViewId = NO_ID;
1633
1634    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1635
1636    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1637
1638    /**
1639     * The view's tag.
1640     * {@hide}
1641     *
1642     * @see #setTag(Object)
1643     * @see #getTag()
1644     */
1645    protected Object mTag = null;
1646
1647    // for mPrivateFlags:
1648    /** {@hide} */
1649    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1650    /** {@hide} */
1651    static final int PFLAG_FOCUSED                     = 0x00000002;
1652    /** {@hide} */
1653    static final int PFLAG_SELECTED                    = 0x00000004;
1654    /** {@hide} */
1655    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1656    /** {@hide} */
1657    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1658    /** {@hide} */
1659    static final int PFLAG_DRAWN                       = 0x00000020;
1660    /**
1661     * When this flag is set, this view is running an animation on behalf of its
1662     * children and should therefore not cancel invalidate requests, even if they
1663     * lie outside of this view's bounds.
1664     *
1665     * {@hide}
1666     */
1667    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1668    /** {@hide} */
1669    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1670    /** {@hide} */
1671    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1672    /** {@hide} */
1673    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1674    /** {@hide} */
1675    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1676    /** {@hide} */
1677    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1678    /** {@hide} */
1679    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1680
1681    private static final int PFLAG_PRESSED             = 0x00004000;
1682
1683    /** {@hide} */
1684    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1685    /**
1686     * Flag used to indicate that this view should be drawn once more (and only once
1687     * more) after its animation has completed.
1688     * {@hide}
1689     */
1690    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1691
1692    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1693
1694    /**
1695     * Indicates that the View returned true when onSetAlpha() was called and that
1696     * the alpha must be restored.
1697     * {@hide}
1698     */
1699    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1700
1701    /**
1702     * Set by {@link #setScrollContainer(boolean)}.
1703     */
1704    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1705
1706    /**
1707     * Set by {@link #setScrollContainer(boolean)}.
1708     */
1709    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1710
1711    /**
1712     * View flag indicating whether this view was invalidated (fully or partially.)
1713     *
1714     * @hide
1715     */
1716    static final int PFLAG_DIRTY                       = 0x00200000;
1717
1718    /**
1719     * View flag indicating whether this view was invalidated by an opaque
1720     * invalidate request.
1721     *
1722     * @hide
1723     */
1724    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1725
1726    /**
1727     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1728     *
1729     * @hide
1730     */
1731    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1732
1733    /**
1734     * Indicates whether the background is opaque.
1735     *
1736     * @hide
1737     */
1738    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1739
1740    /**
1741     * Indicates whether the scrollbars are opaque.
1742     *
1743     * @hide
1744     */
1745    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1746
1747    /**
1748     * Indicates whether the view is opaque.
1749     *
1750     * @hide
1751     */
1752    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1753
1754    /**
1755     * Indicates a prepressed state;
1756     * the short time between ACTION_DOWN and recognizing
1757     * a 'real' press. Prepressed is used to recognize quick taps
1758     * even when they are shorter than ViewConfiguration.getTapTimeout().
1759     *
1760     * @hide
1761     */
1762    private static final int PFLAG_PREPRESSED          = 0x02000000;
1763
1764    /**
1765     * Indicates whether the view is temporarily detached.
1766     *
1767     * @hide
1768     */
1769    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1770
1771    /**
1772     * Indicates that we should awaken scroll bars once attached
1773     *
1774     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1775     * during window attachment and it is no longer needed. Feel free to repurpose it.
1776     *
1777     * @hide
1778     */
1779    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1780
1781    /**
1782     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1783     * @hide
1784     */
1785    private static final int PFLAG_HOVERED             = 0x10000000;
1786
1787    /**
1788     * no longer needed, should be reused
1789     */
1790    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1791
1792    /** {@hide} */
1793    static final int PFLAG_ACTIVATED                   = 0x40000000;
1794
1795    /**
1796     * Indicates that this view was specifically invalidated, not just dirtied because some
1797     * child view was invalidated. The flag is used to determine when we need to recreate
1798     * a view's display list (as opposed to just returning a reference to its existing
1799     * display list).
1800     *
1801     * @hide
1802     */
1803    static final int PFLAG_INVALIDATED                 = 0x80000000;
1804
1805    /**
1806     * Masks for mPrivateFlags2, as generated by dumpFlags():
1807     *
1808     * |-------|-------|-------|-------|
1809     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1810     *                                1  PFLAG2_DRAG_HOVERED
1811     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1812     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1813     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1814     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1815     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1816     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1817     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1818     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1819     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1820     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1821     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1822     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1823     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1824     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1825     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1826     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1827     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1828     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1829     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1830     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1831     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1832     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1833     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1834     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1835     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1836     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1837     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1838     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1839     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1840     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1841     *    1                              PFLAG2_PADDING_RESOLVED
1842     *   1                               PFLAG2_DRAWABLE_RESOLVED
1843     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1844     * |-------|-------|-------|-------|
1845     */
1846
1847    /**
1848     * Indicates that this view has reported that it can accept the current drag's content.
1849     * Cleared when the drag operation concludes.
1850     * @hide
1851     */
1852    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1853
1854    /**
1855     * Indicates that this view is currently directly under the drag location in a
1856     * drag-and-drop operation involving content that it can accept.  Cleared when
1857     * the drag exits the view, or when the drag operation concludes.
1858     * @hide
1859     */
1860    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1861
1862    /** @hide */
1863    @IntDef({
1864        LAYOUT_DIRECTION_LTR,
1865        LAYOUT_DIRECTION_RTL,
1866        LAYOUT_DIRECTION_INHERIT,
1867        LAYOUT_DIRECTION_LOCALE
1868    })
1869    @Retention(RetentionPolicy.SOURCE)
1870    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1871    public @interface LayoutDir {}
1872
1873    /** @hide */
1874    @IntDef({
1875        LAYOUT_DIRECTION_LTR,
1876        LAYOUT_DIRECTION_RTL
1877    })
1878    @Retention(RetentionPolicy.SOURCE)
1879    public @interface ResolvedLayoutDir {}
1880
1881    /**
1882     * A flag to indicate that the layout direction of this view has not been defined yet.
1883     * @hide
1884     */
1885    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1886
1887    /**
1888     * Horizontal layout direction of this view is from Left to Right.
1889     * Use with {@link #setLayoutDirection}.
1890     */
1891    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1892
1893    /**
1894     * Horizontal layout direction of this view is from Right to Left.
1895     * Use with {@link #setLayoutDirection}.
1896     */
1897    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1898
1899    /**
1900     * Horizontal layout direction of this view is inherited from its parent.
1901     * Use with {@link #setLayoutDirection}.
1902     */
1903    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1904
1905    /**
1906     * Horizontal layout direction of this view is from deduced from the default language
1907     * script for the locale. Use with {@link #setLayoutDirection}.
1908     */
1909    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1910
1911    /**
1912     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1913     * @hide
1914     */
1915    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1916
1917    /**
1918     * Mask for use with private flags indicating bits used for horizontal layout direction.
1919     * @hide
1920     */
1921    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1922
1923    /**
1924     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1925     * right-to-left direction.
1926     * @hide
1927     */
1928    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1929
1930    /**
1931     * Indicates whether the view horizontal layout direction has been resolved.
1932     * @hide
1933     */
1934    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1935
1936    /**
1937     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1938     * @hide
1939     */
1940    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1941            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1942
1943    /*
1944     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1945     * flag value.
1946     * @hide
1947     */
1948    private static final int[] LAYOUT_DIRECTION_FLAGS = {
1949            LAYOUT_DIRECTION_LTR,
1950            LAYOUT_DIRECTION_RTL,
1951            LAYOUT_DIRECTION_INHERIT,
1952            LAYOUT_DIRECTION_LOCALE
1953    };
1954
1955    /**
1956     * Default horizontal layout direction.
1957     */
1958    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
1959
1960    /**
1961     * Default horizontal layout direction.
1962     * @hide
1963     */
1964    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
1965
1966    /**
1967     * Text direction is inherited through {@link ViewGroup}
1968     */
1969    public static final int TEXT_DIRECTION_INHERIT = 0;
1970
1971    /**
1972     * Text direction is using "first strong algorithm". The first strong directional character
1973     * determines the paragraph direction. If there is no strong directional character, the
1974     * paragraph direction is the view's resolved layout direction.
1975     */
1976    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1977
1978    /**
1979     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1980     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1981     * If there are neither, the paragraph direction is the view's resolved layout direction.
1982     */
1983    public static final int TEXT_DIRECTION_ANY_RTL = 2;
1984
1985    /**
1986     * Text direction is forced to LTR.
1987     */
1988    public static final int TEXT_DIRECTION_LTR = 3;
1989
1990    /**
1991     * Text direction is forced to RTL.
1992     */
1993    public static final int TEXT_DIRECTION_RTL = 4;
1994
1995    /**
1996     * Text direction is coming from the system Locale.
1997     */
1998    public static final int TEXT_DIRECTION_LOCALE = 5;
1999
2000    /**
2001     * Text direction is using "first strong algorithm". The first strong directional character
2002     * determines the paragraph direction. If there is no strong directional character, the
2003     * paragraph direction is LTR.
2004     */
2005    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2006
2007    /**
2008     * Text direction is using "first strong algorithm". The first strong directional character
2009     * determines the paragraph direction. If there is no strong directional character, the
2010     * paragraph direction is RTL.
2011     */
2012    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2013
2014    /**
2015     * Default text direction is inherited
2016     */
2017    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2018
2019    /**
2020     * Default resolved text direction
2021     * @hide
2022     */
2023    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2024
2025    /**
2026     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2027     * @hide
2028     */
2029    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2030
2031    /**
2032     * Mask for use with private flags indicating bits used for text direction.
2033     * @hide
2034     */
2035    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2036            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2037
2038    /**
2039     * Array of text direction flags for mapping attribute "textDirection" to correct
2040     * flag value.
2041     * @hide
2042     */
2043    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2044            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2045            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2046            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2047            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2048            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2049            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2050            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2051            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2052    };
2053
2054    /**
2055     * Indicates whether the view text direction has been resolved.
2056     * @hide
2057     */
2058    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2059            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2060
2061    /**
2062     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2063     * @hide
2064     */
2065    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2066
2067    /**
2068     * Mask for use with private flags indicating bits used for resolved text direction.
2069     * @hide
2070     */
2071    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2072            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2073
2074    /**
2075     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2076     * @hide
2077     */
2078    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2079            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2080
2081    /** @hide */
2082    @IntDef({
2083        TEXT_ALIGNMENT_INHERIT,
2084        TEXT_ALIGNMENT_GRAVITY,
2085        TEXT_ALIGNMENT_CENTER,
2086        TEXT_ALIGNMENT_TEXT_START,
2087        TEXT_ALIGNMENT_TEXT_END,
2088        TEXT_ALIGNMENT_VIEW_START,
2089        TEXT_ALIGNMENT_VIEW_END
2090    })
2091    @Retention(RetentionPolicy.SOURCE)
2092    public @interface TextAlignment {}
2093
2094    /**
2095     * Default text alignment. The text alignment of this View is inherited from its parent.
2096     * Use with {@link #setTextAlignment(int)}
2097     */
2098    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2099
2100    /**
2101     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2102     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2103     *
2104     * Use with {@link #setTextAlignment(int)}
2105     */
2106    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2107
2108    /**
2109     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2110     *
2111     * Use with {@link #setTextAlignment(int)}
2112     */
2113    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2114
2115    /**
2116     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2117     *
2118     * Use with {@link #setTextAlignment(int)}
2119     */
2120    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2121
2122    /**
2123     * Center the paragraph, e.g. ALIGN_CENTER.
2124     *
2125     * Use with {@link #setTextAlignment(int)}
2126     */
2127    public static final int TEXT_ALIGNMENT_CENTER = 4;
2128
2129    /**
2130     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2131     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2132     *
2133     * Use with {@link #setTextAlignment(int)}
2134     */
2135    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2136
2137    /**
2138     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2139     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2140     *
2141     * Use with {@link #setTextAlignment(int)}
2142     */
2143    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2144
2145    /**
2146     * Default text alignment is inherited
2147     */
2148    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2149
2150    /**
2151     * Default resolved text alignment
2152     * @hide
2153     */
2154    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2155
2156    /**
2157      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2158      * @hide
2159      */
2160    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2161
2162    /**
2163      * Mask for use with private flags indicating bits used for text alignment.
2164      * @hide
2165      */
2166    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2167
2168    /**
2169     * Array of text direction flags for mapping attribute "textAlignment" to correct
2170     * flag value.
2171     * @hide
2172     */
2173    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2174            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2175            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2176            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2177            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2178            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2179            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2180            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2181    };
2182
2183    /**
2184     * Indicates whether the view text alignment has been resolved.
2185     * @hide
2186     */
2187    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2188
2189    /**
2190     * Bit shift to get the resolved text alignment.
2191     * @hide
2192     */
2193    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2194
2195    /**
2196     * Mask for use with private flags indicating bits used for text alignment.
2197     * @hide
2198     */
2199    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2200            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2201
2202    /**
2203     * Indicates whether if the view text alignment has been resolved to gravity
2204     */
2205    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2206            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2207
2208    // Accessiblity constants for mPrivateFlags2
2209
2210    /**
2211     * Shift for the bits in {@link #mPrivateFlags2} related to the
2212     * "importantForAccessibility" attribute.
2213     */
2214    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2215
2216    /**
2217     * Automatically determine whether a view is important for accessibility.
2218     */
2219    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2220
2221    /**
2222     * The view is important for accessibility.
2223     */
2224    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2225
2226    /**
2227     * The view is not important for accessibility.
2228     */
2229    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2230
2231    /**
2232     * The view is not important for accessibility, nor are any of its
2233     * descendant views.
2234     */
2235    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2236
2237    /**
2238     * The default whether the view is important for accessibility.
2239     */
2240    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2241
2242    /**
2243     * Mask for obtainig the bits which specify how to determine
2244     * whether a view is important for accessibility.
2245     */
2246    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2247        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2248        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2249        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2250
2251    /**
2252     * Shift for the bits in {@link #mPrivateFlags2} related to the
2253     * "accessibilityLiveRegion" attribute.
2254     */
2255    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2256
2257    /**
2258     * Live region mode specifying that accessibility services should not
2259     * automatically announce changes to this view. This is the default live
2260     * region mode for most views.
2261     * <p>
2262     * Use with {@link #setAccessibilityLiveRegion(int)}.
2263     */
2264    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2265
2266    /**
2267     * Live region mode specifying that accessibility services should announce
2268     * changes to this view.
2269     * <p>
2270     * Use with {@link #setAccessibilityLiveRegion(int)}.
2271     */
2272    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2273
2274    /**
2275     * Live region mode specifying that accessibility services should interrupt
2276     * ongoing speech to immediately announce changes to this view.
2277     * <p>
2278     * Use with {@link #setAccessibilityLiveRegion(int)}.
2279     */
2280    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2281
2282    /**
2283     * The default whether the view is important for accessibility.
2284     */
2285    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2286
2287    /**
2288     * Mask for obtaining the bits which specify a view's accessibility live
2289     * region mode.
2290     */
2291    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2292            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2293            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2294
2295    /**
2296     * Flag indicating whether a view has accessibility focus.
2297     */
2298    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2299
2300    /**
2301     * Flag whether the accessibility state of the subtree rooted at this view changed.
2302     */
2303    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2304
2305    /**
2306     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2307     * is used to check whether later changes to the view's transform should invalidate the
2308     * view to force the quickReject test to run again.
2309     */
2310    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2311
2312    /**
2313     * Flag indicating that start/end padding has been resolved into left/right padding
2314     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2315     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2316     * during measurement. In some special cases this is required such as when an adapter-based
2317     * view measures prospective children without attaching them to a window.
2318     */
2319    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2320
2321    /**
2322     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2323     */
2324    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2325
2326    /**
2327     * Indicates that the view is tracking some sort of transient state
2328     * that the app should not need to be aware of, but that the framework
2329     * should take special care to preserve.
2330     */
2331    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2332
2333    /**
2334     * Group of bits indicating that RTL properties resolution is done.
2335     */
2336    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2337            PFLAG2_TEXT_DIRECTION_RESOLVED |
2338            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2339            PFLAG2_PADDING_RESOLVED |
2340            PFLAG2_DRAWABLE_RESOLVED;
2341
2342    // There are a couple of flags left in mPrivateFlags2
2343
2344    /* End of masks for mPrivateFlags2 */
2345
2346    /**
2347     * Masks for mPrivateFlags3, as generated by dumpFlags():
2348     *
2349     * |-------|-------|-------|-------|
2350     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2351     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2352     *                               1   PFLAG3_IS_LAID_OUT
2353     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2354     *                             1     PFLAG3_CALLED_SUPER
2355     *                            1      PFLAG3_APPLYING_INSETS
2356     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2357     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2358     *                         1         PFLAG3_ASSIST_BLOCKED
2359     * |-------|-------|-------|-------|
2360     */
2361
2362    /**
2363     * Flag indicating that view has a transform animation set on it. This is used to track whether
2364     * an animation is cleared between successive frames, in order to tell the associated
2365     * DisplayList to clear its animation matrix.
2366     */
2367    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2368
2369    /**
2370     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2371     * animation is cleared between successive frames, in order to tell the associated
2372     * DisplayList to restore its alpha value.
2373     */
2374    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2375
2376    /**
2377     * Flag indicating that the view has been through at least one layout since it
2378     * was last attached to a window.
2379     */
2380    static final int PFLAG3_IS_LAID_OUT = 0x4;
2381
2382    /**
2383     * Flag indicating that a call to measure() was skipped and should be done
2384     * instead when layout() is invoked.
2385     */
2386    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2387
2388    /**
2389     * Flag indicating that an overridden method correctly called down to
2390     * the superclass implementation as required by the API spec.
2391     */
2392    static final int PFLAG3_CALLED_SUPER = 0x10;
2393
2394    /**
2395     * Flag indicating that we're in the process of applying window insets.
2396     */
2397    static final int PFLAG3_APPLYING_INSETS = 0x20;
2398
2399    /**
2400     * Flag indicating that we're in the process of fitting system windows using the old method.
2401     */
2402    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2403
2404    /**
2405     * Flag indicating that nested scrolling is enabled for this view.
2406     * The view will optionally cooperate with views up its parent chain to allow for
2407     * integrated nested scrolling along the same axis.
2408     */
2409    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2410
2411    /**
2412     * Flag indicating that the bottom scroll indicator should be displayed
2413     * when this view can scroll up.
2414     */
2415    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2416
2417    /**
2418     * Flag indicating that the bottom scroll indicator should be displayed
2419     * when this view can scroll down.
2420     */
2421    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2422
2423    /**
2424     * Flag indicating that the left scroll indicator should be displayed
2425     * when this view can scroll left.
2426     */
2427    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2428
2429    /**
2430     * Flag indicating that the right scroll indicator should be displayed
2431     * when this view can scroll right.
2432     */
2433    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2434
2435    /**
2436     * Flag indicating that the start scroll indicator should be displayed
2437     * when this view can scroll in the start direction.
2438     */
2439    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2440
2441    /**
2442     * Flag indicating that the end scroll indicator should be displayed
2443     * when this view can scroll in the end direction.
2444     */
2445    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2446
2447    /* End of masks for mPrivateFlags3 */
2448
2449    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2450
2451    static final int SCROLL_INDICATORS_NONE = 0x0000;
2452
2453    /**
2454     * Mask for use with setFlags indicating bits used for indicating which
2455     * scroll indicators are enabled.
2456     */
2457    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2458            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2459            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2460            | PFLAG3_SCROLL_INDICATOR_END;
2461
2462    /**
2463     * Left-shift required to translate between public scroll indicator flags
2464     * and internal PFLAGS3 flags. When used as a right-shift, translates
2465     * PFLAGS3 flags to public flags.
2466     */
2467    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2468
2469    /** @hide */
2470    @Retention(RetentionPolicy.SOURCE)
2471    @IntDef(flag = true,
2472            value = {
2473                    SCROLL_INDICATOR_TOP,
2474                    SCROLL_INDICATOR_BOTTOM,
2475                    SCROLL_INDICATOR_LEFT,
2476                    SCROLL_INDICATOR_RIGHT,
2477                    SCROLL_INDICATOR_START,
2478                    SCROLL_INDICATOR_END,
2479            })
2480    public @interface ScrollIndicators {}
2481
2482    /**
2483     * Scroll indicator direction for the top edge of the view.
2484     *
2485     * @see #setScrollIndicators(int)
2486     * @see #setScrollIndicators(int, int)
2487     * @see #getScrollIndicators()
2488     */
2489    public static final int SCROLL_INDICATOR_TOP =
2490            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2491
2492    /**
2493     * Scroll indicator direction for the bottom edge of the view.
2494     *
2495     * @see #setScrollIndicators(int)
2496     * @see #setScrollIndicators(int, int)
2497     * @see #getScrollIndicators()
2498     */
2499    public static final int SCROLL_INDICATOR_BOTTOM =
2500            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2501
2502    /**
2503     * Scroll indicator direction for the left edge of the view.
2504     *
2505     * @see #setScrollIndicators(int)
2506     * @see #setScrollIndicators(int, int)
2507     * @see #getScrollIndicators()
2508     */
2509    public static final int SCROLL_INDICATOR_LEFT =
2510            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2511
2512    /**
2513     * Scroll indicator direction for the right edge of the view.
2514     *
2515     * @see #setScrollIndicators(int)
2516     * @see #setScrollIndicators(int, int)
2517     * @see #getScrollIndicators()
2518     */
2519    public static final int SCROLL_INDICATOR_RIGHT =
2520            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2521
2522    /**
2523     * Scroll indicator direction for the starting edge of the view.
2524     * <p>
2525     * Resolved according to the view's layout direction, see
2526     * {@link #getLayoutDirection()} for more information.
2527     *
2528     * @see #setScrollIndicators(int)
2529     * @see #setScrollIndicators(int, int)
2530     * @see #getScrollIndicators()
2531     */
2532    public static final int SCROLL_INDICATOR_START =
2533            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2534
2535    /**
2536     * Scroll indicator direction for the ending edge of the view.
2537     * <p>
2538     * Resolved according to the view's layout direction, see
2539     * {@link #getLayoutDirection()} for more information.
2540     *
2541     * @see #setScrollIndicators(int)
2542     * @see #setScrollIndicators(int, int)
2543     * @see #getScrollIndicators()
2544     */
2545    public static final int SCROLL_INDICATOR_END =
2546            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2547
2548    /**
2549     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2550     * into this view.<p>
2551     */
2552    static final int PFLAG3_ASSIST_BLOCKED = 0x100;
2553
2554    /**
2555     * Always allow a user to over-scroll this view, provided it is a
2556     * view that can scroll.
2557     *
2558     * @see #getOverScrollMode()
2559     * @see #setOverScrollMode(int)
2560     */
2561    public static final int OVER_SCROLL_ALWAYS = 0;
2562
2563    /**
2564     * Allow a user to over-scroll this view only if the content is large
2565     * enough to meaningfully scroll, provided it is a view that can scroll.
2566     *
2567     * @see #getOverScrollMode()
2568     * @see #setOverScrollMode(int)
2569     */
2570    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2571
2572    /**
2573     * Never allow a user to over-scroll this view.
2574     *
2575     * @see #getOverScrollMode()
2576     * @see #setOverScrollMode(int)
2577     */
2578    public static final int OVER_SCROLL_NEVER = 2;
2579
2580    /**
2581     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2582     * requested the system UI (status bar) to be visible (the default).
2583     *
2584     * @see #setSystemUiVisibility(int)
2585     */
2586    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2587
2588    /**
2589     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2590     * system UI to enter an unobtrusive "low profile" mode.
2591     *
2592     * <p>This is for use in games, book readers, video players, or any other
2593     * "immersive" application where the usual system chrome is deemed too distracting.
2594     *
2595     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2596     *
2597     * @see #setSystemUiVisibility(int)
2598     */
2599    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2600
2601    /**
2602     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2603     * system navigation be temporarily hidden.
2604     *
2605     * <p>This is an even less obtrusive state than that called for by
2606     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2607     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2608     * those to disappear. This is useful (in conjunction with the
2609     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2610     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2611     * window flags) for displaying content using every last pixel on the display.
2612     *
2613     * <p>There is a limitation: because navigation controls are so important, the least user
2614     * interaction will cause them to reappear immediately.  When this happens, both
2615     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2616     * so that both elements reappear at the same time.
2617     *
2618     * @see #setSystemUiVisibility(int)
2619     */
2620    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2621
2622    /**
2623     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2624     * into the normal fullscreen mode so that its content can take over the screen
2625     * while still allowing the user to interact with the application.
2626     *
2627     * <p>This has the same visual effect as
2628     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2629     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2630     * meaning that non-critical screen decorations (such as the status bar) will be
2631     * hidden while the user is in the View's window, focusing the experience on
2632     * that content.  Unlike the window flag, if you are using ActionBar in
2633     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2634     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2635     * hide the action bar.
2636     *
2637     * <p>This approach to going fullscreen is best used over the window flag when
2638     * it is a transient state -- that is, the application does this at certain
2639     * points in its user interaction where it wants to allow the user to focus
2640     * on content, but not as a continuous state.  For situations where the application
2641     * would like to simply stay full screen the entire time (such as a game that
2642     * wants to take over the screen), the
2643     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2644     * is usually a better approach.  The state set here will be removed by the system
2645     * in various situations (such as the user moving to another application) like
2646     * the other system UI states.
2647     *
2648     * <p>When using this flag, the application should provide some easy facility
2649     * for the user to go out of it.  A common example would be in an e-book
2650     * reader, where tapping on the screen brings back whatever screen and UI
2651     * decorations that had been hidden while the user was immersed in reading
2652     * the book.
2653     *
2654     * @see #setSystemUiVisibility(int)
2655     */
2656    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2657
2658    /**
2659     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2660     * flags, we would like a stable view of the content insets given to
2661     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2662     * will always represent the worst case that the application can expect
2663     * as a continuous state.  In the stock Android UI this is the space for
2664     * the system bar, nav bar, and status bar, but not more transient elements
2665     * such as an input method.
2666     *
2667     * The stable layout your UI sees is based on the system UI modes you can
2668     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2669     * then you will get a stable layout for changes of the
2670     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2671     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2672     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2673     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2674     * with a stable layout.  (Note that you should avoid using
2675     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2676     *
2677     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2678     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2679     * then a hidden status bar will be considered a "stable" state for purposes
2680     * here.  This allows your UI to continually hide the status bar, while still
2681     * using the system UI flags to hide the action bar while still retaining
2682     * a stable layout.  Note that changing the window fullscreen flag will never
2683     * provide a stable layout for a clean transition.
2684     *
2685     * <p>If you are using ActionBar in
2686     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2687     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2688     * insets it adds to those given to the application.
2689     */
2690    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2691
2692    /**
2693     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2694     * to be laid out as if it has requested
2695     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2696     * allows it to avoid artifacts when switching in and out of that mode, at
2697     * the expense that some of its user interface may be covered by screen
2698     * decorations when they are shown.  You can perform layout of your inner
2699     * UI elements to account for the navigation system UI through the
2700     * {@link #fitSystemWindows(Rect)} method.
2701     */
2702    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2703
2704    /**
2705     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2706     * to be laid out as if it has requested
2707     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2708     * allows it to avoid artifacts when switching in and out of that mode, at
2709     * the expense that some of its user interface may be covered by screen
2710     * decorations when they are shown.  You can perform layout of your inner
2711     * UI elements to account for non-fullscreen system UI through the
2712     * {@link #fitSystemWindows(Rect)} method.
2713     */
2714    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2715
2716    /**
2717     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2718     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2719     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2720     * user interaction.
2721     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2722     * has an effect when used in combination with that flag.</p>
2723     */
2724    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2725
2726    /**
2727     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2728     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2729     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2730     * experience while also hiding the system bars.  If this flag is not set,
2731     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2732     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2733     * if the user swipes from the top of the screen.
2734     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2735     * system gestures, such as swiping from the top of the screen.  These transient system bars
2736     * will overlay app’s content, may have some degree of transparency, and will automatically
2737     * hide after a short timeout.
2738     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2739     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2740     * with one or both of those flags.</p>
2741     */
2742    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2743
2744    /**
2745     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2746     * is compatible with light status bar backgrounds.
2747     *
2748     * <p>For this to take effect, the window must request
2749     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2750     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2751     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2752     *         FLAG_TRANSLUCENT_STATUS}.
2753     *
2754     * @see android.R.attr#windowLightStatusBar
2755     */
2756    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2757
2758    /**
2759     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2760     */
2761    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2762
2763    /**
2764     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2765     */
2766    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2767
2768    /**
2769     * @hide
2770     *
2771     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2772     * out of the public fields to keep the undefined bits out of the developer's way.
2773     *
2774     * Flag to make the status bar not expandable.  Unless you also
2775     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2776     */
2777    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2778
2779    /**
2780     * @hide
2781     *
2782     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2783     * out of the public fields to keep the undefined bits out of the developer's way.
2784     *
2785     * Flag to hide notification icons and scrolling ticker text.
2786     */
2787    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2788
2789    /**
2790     * @hide
2791     *
2792     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2793     * out of the public fields to keep the undefined bits out of the developer's way.
2794     *
2795     * Flag to disable incoming notification alerts.  This will not block
2796     * icons, but it will block sound, vibrating and other visual or aural notifications.
2797     */
2798    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2799
2800    /**
2801     * @hide
2802     *
2803     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2804     * out of the public fields to keep the undefined bits out of the developer's way.
2805     *
2806     * Flag to hide only the scrolling ticker.  Note that
2807     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2808     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2809     */
2810    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2811
2812    /**
2813     * @hide
2814     *
2815     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2816     * out of the public fields to keep the undefined bits out of the developer's way.
2817     *
2818     * Flag to hide the center system info area.
2819     */
2820    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2821
2822    /**
2823     * @hide
2824     *
2825     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2826     * out of the public fields to keep the undefined bits out of the developer's way.
2827     *
2828     * Flag to hide only the home button.  Don't use this
2829     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2830     */
2831    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2832
2833    /**
2834     * @hide
2835     *
2836     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2837     * out of the public fields to keep the undefined bits out of the developer's way.
2838     *
2839     * Flag to hide only the back button. Don't use this
2840     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2841     */
2842    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2843
2844    /**
2845     * @hide
2846     *
2847     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2848     * out of the public fields to keep the undefined bits out of the developer's way.
2849     *
2850     * Flag to hide only the clock.  You might use this if your activity has
2851     * its own clock making the status bar's clock redundant.
2852     */
2853    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2854
2855    /**
2856     * @hide
2857     *
2858     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2859     * out of the public fields to keep the undefined bits out of the developer's way.
2860     *
2861     * Flag to hide only the recent apps button. Don't use this
2862     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2863     */
2864    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2865
2866    /**
2867     * @hide
2868     *
2869     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2870     * out of the public fields to keep the undefined bits out of the developer's way.
2871     *
2872     * Flag to disable the global search gesture. Don't use this
2873     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2874     */
2875    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2876
2877    /**
2878     * @hide
2879     *
2880     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2881     * out of the public fields to keep the undefined bits out of the developer's way.
2882     *
2883     * Flag to specify that the status bar is displayed in transient mode.
2884     */
2885    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2886
2887    /**
2888     * @hide
2889     *
2890     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2891     * out of the public fields to keep the undefined bits out of the developer's way.
2892     *
2893     * Flag to specify that the navigation bar is displayed in transient mode.
2894     */
2895    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2896
2897    /**
2898     * @hide
2899     *
2900     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2901     * out of the public fields to keep the undefined bits out of the developer's way.
2902     *
2903     * Flag to specify that the hidden status bar would like to be shown.
2904     */
2905    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2906
2907    /**
2908     * @hide
2909     *
2910     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2911     * out of the public fields to keep the undefined bits out of the developer's way.
2912     *
2913     * Flag to specify that the hidden navigation bar would like to be shown.
2914     */
2915    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2916
2917    /**
2918     * @hide
2919     *
2920     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2921     * out of the public fields to keep the undefined bits out of the developer's way.
2922     *
2923     * Flag to specify that the status bar is displayed in translucent mode.
2924     */
2925    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2926
2927    /**
2928     * @hide
2929     *
2930     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2931     * out of the public fields to keep the undefined bits out of the developer's way.
2932     *
2933     * Flag to specify that the navigation bar is displayed in translucent mode.
2934     */
2935    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2936
2937    /**
2938     * @hide
2939     *
2940     * Whether Recents is visible or not.
2941     */
2942    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2943
2944    /**
2945     * @hide
2946     *
2947     * Makes system ui transparent.
2948     */
2949    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2950
2951    /**
2952     * @hide
2953     */
2954    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2955
2956    /**
2957     * These are the system UI flags that can be cleared by events outside
2958     * of an application.  Currently this is just the ability to tap on the
2959     * screen while hiding the navigation bar to have it return.
2960     * @hide
2961     */
2962    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2963            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2964            | SYSTEM_UI_FLAG_FULLSCREEN;
2965
2966    /**
2967     * Flags that can impact the layout in relation to system UI.
2968     */
2969    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2970            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2971            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2972
2973    /** @hide */
2974    @IntDef(flag = true,
2975            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2976    @Retention(RetentionPolicy.SOURCE)
2977    public @interface FindViewFlags {}
2978
2979    /**
2980     * Find views that render the specified text.
2981     *
2982     * @see #findViewsWithText(ArrayList, CharSequence, int)
2983     */
2984    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2985
2986    /**
2987     * Find find views that contain the specified content description.
2988     *
2989     * @see #findViewsWithText(ArrayList, CharSequence, int)
2990     */
2991    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2992
2993    /**
2994     * Find views that contain {@link AccessibilityNodeProvider}. Such
2995     * a View is a root of virtual view hierarchy and may contain the searched
2996     * text. If this flag is set Views with providers are automatically
2997     * added and it is a responsibility of the client to call the APIs of
2998     * the provider to determine whether the virtual tree rooted at this View
2999     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3000     * representing the virtual views with this text.
3001     *
3002     * @see #findViewsWithText(ArrayList, CharSequence, int)
3003     *
3004     * @hide
3005     */
3006    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3007
3008    /**
3009     * The undefined cursor position.
3010     *
3011     * @hide
3012     */
3013    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3014
3015    /**
3016     * Indicates that the screen has changed state and is now off.
3017     *
3018     * @see #onScreenStateChanged(int)
3019     */
3020    public static final int SCREEN_STATE_OFF = 0x0;
3021
3022    /**
3023     * Indicates that the screen has changed state and is now on.
3024     *
3025     * @see #onScreenStateChanged(int)
3026     */
3027    public static final int SCREEN_STATE_ON = 0x1;
3028
3029    /**
3030     * Indicates no axis of view scrolling.
3031     */
3032    public static final int SCROLL_AXIS_NONE = 0;
3033
3034    /**
3035     * Indicates scrolling along the horizontal axis.
3036     */
3037    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3038
3039    /**
3040     * Indicates scrolling along the vertical axis.
3041     */
3042    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3043
3044    /**
3045     * Controls the over-scroll mode for this view.
3046     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3047     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3048     * and {@link #OVER_SCROLL_NEVER}.
3049     */
3050    private int mOverScrollMode;
3051
3052    /**
3053     * The parent this view is attached to.
3054     * {@hide}
3055     *
3056     * @see #getParent()
3057     */
3058    protected ViewParent mParent;
3059
3060    /**
3061     * {@hide}
3062     */
3063    AttachInfo mAttachInfo;
3064
3065    /**
3066     * {@hide}
3067     */
3068    @ViewDebug.ExportedProperty(flagMapping = {
3069        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3070                name = "FORCE_LAYOUT"),
3071        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3072                name = "LAYOUT_REQUIRED"),
3073        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3074            name = "DRAWING_CACHE_INVALID", outputIf = false),
3075        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3076        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3077        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3078        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3079    }, formatToHexString = true)
3080    int mPrivateFlags;
3081    int mPrivateFlags2;
3082    int mPrivateFlags3;
3083
3084    /**
3085     * This view's request for the visibility of the status bar.
3086     * @hide
3087     */
3088    @ViewDebug.ExportedProperty(flagMapping = {
3089        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3090                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3091                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3092        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3093                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3094                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3095        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3096                                equals = SYSTEM_UI_FLAG_VISIBLE,
3097                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3098    }, formatToHexString = true)
3099    int mSystemUiVisibility;
3100
3101    /**
3102     * Reference count for transient state.
3103     * @see #setHasTransientState(boolean)
3104     */
3105    int mTransientStateCount = 0;
3106
3107    /**
3108     * Count of how many windows this view has been attached to.
3109     */
3110    int mWindowAttachCount;
3111
3112    /**
3113     * The layout parameters associated with this view and used by the parent
3114     * {@link android.view.ViewGroup} to determine how this view should be
3115     * laid out.
3116     * {@hide}
3117     */
3118    protected ViewGroup.LayoutParams mLayoutParams;
3119
3120    /**
3121     * The view flags hold various views states.
3122     * {@hide}
3123     */
3124    @ViewDebug.ExportedProperty(formatToHexString = true)
3125    int mViewFlags;
3126
3127    static class TransformationInfo {
3128        /**
3129         * The transform matrix for the View. This transform is calculated internally
3130         * based on the translation, rotation, and scale properties.
3131         *
3132         * Do *not* use this variable directly; instead call getMatrix(), which will
3133         * load the value from the View's RenderNode.
3134         */
3135        private final Matrix mMatrix = new Matrix();
3136
3137        /**
3138         * The inverse transform matrix for the View. This transform is calculated
3139         * internally based on the translation, rotation, and scale properties.
3140         *
3141         * Do *not* use this variable directly; instead call getInverseMatrix(),
3142         * which will load the value from the View's RenderNode.
3143         */
3144        private Matrix mInverseMatrix;
3145
3146        /**
3147         * The opacity of the View. This is a value from 0 to 1, where 0 means
3148         * completely transparent and 1 means completely opaque.
3149         */
3150        @ViewDebug.ExportedProperty
3151        float mAlpha = 1f;
3152
3153        /**
3154         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3155         * property only used by transitions, which is composited with the other alpha
3156         * values to calculate the final visual alpha value.
3157         */
3158        float mTransitionAlpha = 1f;
3159    }
3160
3161    TransformationInfo mTransformationInfo;
3162
3163    /**
3164     * Current clip bounds. to which all drawing of this view are constrained.
3165     */
3166    Rect mClipBounds = null;
3167
3168    private boolean mLastIsOpaque;
3169
3170    /**
3171     * The distance in pixels from the left edge of this view's parent
3172     * to the left edge of this view.
3173     * {@hide}
3174     */
3175    @ViewDebug.ExportedProperty(category = "layout")
3176    protected int mLeft;
3177    /**
3178     * The distance in pixels from the left edge of this view's parent
3179     * to the right edge of this view.
3180     * {@hide}
3181     */
3182    @ViewDebug.ExportedProperty(category = "layout")
3183    protected int mRight;
3184    /**
3185     * The distance in pixels from the top edge of this view's parent
3186     * to the top edge of this view.
3187     * {@hide}
3188     */
3189    @ViewDebug.ExportedProperty(category = "layout")
3190    protected int mTop;
3191    /**
3192     * The distance in pixels from the top edge of this view's parent
3193     * to the bottom edge of this view.
3194     * {@hide}
3195     */
3196    @ViewDebug.ExportedProperty(category = "layout")
3197    protected int mBottom;
3198
3199    /**
3200     * The offset, in pixels, by which the content of this view is scrolled
3201     * horizontally.
3202     * {@hide}
3203     */
3204    @ViewDebug.ExportedProperty(category = "scrolling")
3205    protected int mScrollX;
3206    /**
3207     * The offset, in pixels, by which the content of this view is scrolled
3208     * vertically.
3209     * {@hide}
3210     */
3211    @ViewDebug.ExportedProperty(category = "scrolling")
3212    protected int mScrollY;
3213
3214    /**
3215     * The left padding in pixels, that is the distance in pixels between the
3216     * left edge of this view and the left edge of its content.
3217     * {@hide}
3218     */
3219    @ViewDebug.ExportedProperty(category = "padding")
3220    protected int mPaddingLeft = 0;
3221    /**
3222     * The right padding in pixels, that is the distance in pixels between the
3223     * right edge of this view and the right edge of its content.
3224     * {@hide}
3225     */
3226    @ViewDebug.ExportedProperty(category = "padding")
3227    protected int mPaddingRight = 0;
3228    /**
3229     * The top padding in pixels, that is the distance in pixels between the
3230     * top edge of this view and the top edge of its content.
3231     * {@hide}
3232     */
3233    @ViewDebug.ExportedProperty(category = "padding")
3234    protected int mPaddingTop;
3235    /**
3236     * The bottom padding in pixels, that is the distance in pixels between the
3237     * bottom edge of this view and the bottom edge of its content.
3238     * {@hide}
3239     */
3240    @ViewDebug.ExportedProperty(category = "padding")
3241    protected int mPaddingBottom;
3242
3243    /**
3244     * The layout insets in pixels, that is the distance in pixels between the
3245     * visible edges of this view its bounds.
3246     */
3247    private Insets mLayoutInsets;
3248
3249    /**
3250     * Briefly describes the view and is primarily used for accessibility support.
3251     */
3252    private CharSequence mContentDescription;
3253
3254    /**
3255     * Specifies the id of a view for which this view serves as a label for
3256     * accessibility purposes.
3257     */
3258    private int mLabelForId = View.NO_ID;
3259
3260    /**
3261     * Predicate for matching labeled view id with its label for
3262     * accessibility purposes.
3263     */
3264    private MatchLabelForPredicate mMatchLabelForPredicate;
3265
3266    /**
3267     * Specifies a view before which this one is visited in accessibility traversal.
3268     */
3269    private int mAccessibilityTraversalBeforeId = NO_ID;
3270
3271    /**
3272     * Specifies a view after which this one is visited in accessibility traversal.
3273     */
3274    private int mAccessibilityTraversalAfterId = NO_ID;
3275
3276    /**
3277     * Predicate for matching a view by its id.
3278     */
3279    private MatchIdPredicate mMatchIdPredicate;
3280
3281    /**
3282     * Cache the paddingRight set by the user to append to the scrollbar's size.
3283     *
3284     * @hide
3285     */
3286    @ViewDebug.ExportedProperty(category = "padding")
3287    protected int mUserPaddingRight;
3288
3289    /**
3290     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3291     *
3292     * @hide
3293     */
3294    @ViewDebug.ExportedProperty(category = "padding")
3295    protected int mUserPaddingBottom;
3296
3297    /**
3298     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3299     *
3300     * @hide
3301     */
3302    @ViewDebug.ExportedProperty(category = "padding")
3303    protected int mUserPaddingLeft;
3304
3305    /**
3306     * Cache the paddingStart set by the user to append to the scrollbar's size.
3307     *
3308     */
3309    @ViewDebug.ExportedProperty(category = "padding")
3310    int mUserPaddingStart;
3311
3312    /**
3313     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3314     *
3315     */
3316    @ViewDebug.ExportedProperty(category = "padding")
3317    int mUserPaddingEnd;
3318
3319    /**
3320     * Cache initial left padding.
3321     *
3322     * @hide
3323     */
3324    int mUserPaddingLeftInitial;
3325
3326    /**
3327     * Cache initial right padding.
3328     *
3329     * @hide
3330     */
3331    int mUserPaddingRightInitial;
3332
3333    /**
3334     * Default undefined padding
3335     */
3336    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3337
3338    /**
3339     * Cache if a left padding has been defined
3340     */
3341    private boolean mLeftPaddingDefined = false;
3342
3343    /**
3344     * Cache if a right padding has been defined
3345     */
3346    private boolean mRightPaddingDefined = false;
3347
3348    /**
3349     * @hide
3350     */
3351    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3352    /**
3353     * @hide
3354     */
3355    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3356
3357    private LongSparseLongArray mMeasureCache;
3358
3359    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3360    private Drawable mBackground;
3361    private TintInfo mBackgroundTint;
3362
3363    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3364    private ForegroundInfo mForegroundInfo;
3365
3366    private Drawable mScrollIndicatorDrawable;
3367
3368    /**
3369     * RenderNode used for backgrounds.
3370     * <p>
3371     * When non-null and valid, this is expected to contain an up-to-date copy
3372     * of the background drawable. It is cleared on temporary detach, and reset
3373     * on cleanup.
3374     */
3375    private RenderNode mBackgroundRenderNode;
3376
3377    private int mBackgroundResource;
3378    private boolean mBackgroundSizeChanged;
3379
3380    private String mTransitionName;
3381
3382    static class TintInfo {
3383        ColorStateList mTintList;
3384        PorterDuff.Mode mTintMode;
3385        boolean mHasTintMode;
3386        boolean mHasTintList;
3387    }
3388
3389    private static class ForegroundInfo {
3390        private Drawable mDrawable;
3391        private TintInfo mTintInfo;
3392        private int mGravity = Gravity.FILL;
3393        private boolean mInsidePadding = true;
3394        private boolean mBoundsChanged = true;
3395        private final Rect mSelfBounds = new Rect();
3396        private final Rect mOverlayBounds = new Rect();
3397    }
3398
3399    static class ListenerInfo {
3400        /**
3401         * Listener used to dispatch focus change events.
3402         * This field should be made private, so it is hidden from the SDK.
3403         * {@hide}
3404         */
3405        protected OnFocusChangeListener mOnFocusChangeListener;
3406
3407        /**
3408         * Listeners for layout change events.
3409         */
3410        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3411
3412        protected OnScrollChangeListener mOnScrollChangeListener;
3413
3414        /**
3415         * Listeners for attach events.
3416         */
3417        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3418
3419        /**
3420         * Listener used to dispatch click events.
3421         * This field should be made private, so it is hidden from the SDK.
3422         * {@hide}
3423         */
3424        public OnClickListener mOnClickListener;
3425
3426        /**
3427         * Listener used to dispatch long click events.
3428         * This field should be made private, so it is hidden from the SDK.
3429         * {@hide}
3430         */
3431        protected OnLongClickListener mOnLongClickListener;
3432
3433        /**
3434         * Listener used to dispatch context click events. This field should be made private, so it
3435         * is hidden from the SDK.
3436         * {@hide}
3437         */
3438        protected OnContextClickListener mOnContextClickListener;
3439
3440        /**
3441         * Listener used to build the context menu.
3442         * This field should be made private, so it is hidden from the SDK.
3443         * {@hide}
3444         */
3445        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3446
3447        private OnKeyListener mOnKeyListener;
3448
3449        private OnTouchListener mOnTouchListener;
3450
3451        private OnHoverListener mOnHoverListener;
3452
3453        private OnGenericMotionListener mOnGenericMotionListener;
3454
3455        private OnDragListener mOnDragListener;
3456
3457        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3458
3459        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3460    }
3461
3462    ListenerInfo mListenerInfo;
3463
3464    /**
3465     * The application environment this view lives in.
3466     * This field should be made private, so it is hidden from the SDK.
3467     * {@hide}
3468     */
3469    @ViewDebug.ExportedProperty(deepExport = true)
3470    protected Context mContext;
3471
3472    private final Resources mResources;
3473
3474    private ScrollabilityCache mScrollCache;
3475
3476    private int[] mDrawableState = null;
3477
3478    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3479
3480    /**
3481     * Animator that automatically runs based on state changes.
3482     */
3483    private StateListAnimator mStateListAnimator;
3484
3485    /**
3486     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3487     * the user may specify which view to go to next.
3488     */
3489    private int mNextFocusLeftId = View.NO_ID;
3490
3491    /**
3492     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3493     * the user may specify which view to go to next.
3494     */
3495    private int mNextFocusRightId = View.NO_ID;
3496
3497    /**
3498     * When this view has focus and the next focus is {@link #FOCUS_UP},
3499     * the user may specify which view to go to next.
3500     */
3501    private int mNextFocusUpId = View.NO_ID;
3502
3503    /**
3504     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3505     * the user may specify which view to go to next.
3506     */
3507    private int mNextFocusDownId = View.NO_ID;
3508
3509    /**
3510     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3511     * the user may specify which view to go to next.
3512     */
3513    int mNextFocusForwardId = View.NO_ID;
3514
3515    private CheckForLongPress mPendingCheckForLongPress;
3516    private CheckForTap mPendingCheckForTap = null;
3517    private PerformClick mPerformClick;
3518    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3519
3520    private UnsetPressedState mUnsetPressedState;
3521
3522    /**
3523     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3524     * up event while a long press is invoked as soon as the long press duration is reached, so
3525     * a long press could be performed before the tap is checked, in which case the tap's action
3526     * should not be invoked.
3527     */
3528    private boolean mHasPerformedLongPress;
3529
3530    /**
3531     * Whether a context click button is currently pressed down. This is true when the stylus is
3532     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3533     * pressed. This is false once the button is released or if the stylus has been lifted.
3534     */
3535    private boolean mInContextButtonPress;
3536
3537    /**
3538     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3539     * true after a stylus button press has occured, when the next up event should not be recognized
3540     * as a tap.
3541     */
3542    private boolean mIgnoreNextUpEvent;
3543
3544    /**
3545     * The minimum height of the view. We'll try our best to have the height
3546     * of this view to at least this amount.
3547     */
3548    @ViewDebug.ExportedProperty(category = "measurement")
3549    private int mMinHeight;
3550
3551    /**
3552     * The minimum width of the view. We'll try our best to have the width
3553     * of this view to at least this amount.
3554     */
3555    @ViewDebug.ExportedProperty(category = "measurement")
3556    private int mMinWidth;
3557
3558    /**
3559     * The delegate to handle touch events that are physically in this view
3560     * but should be handled by another view.
3561     */
3562    private TouchDelegate mTouchDelegate = null;
3563
3564    /**
3565     * Solid color to use as a background when creating the drawing cache. Enables
3566     * the cache to use 16 bit bitmaps instead of 32 bit.
3567     */
3568    private int mDrawingCacheBackgroundColor = 0;
3569
3570    /**
3571     * Special tree observer used when mAttachInfo is null.
3572     */
3573    private ViewTreeObserver mFloatingTreeObserver;
3574
3575    /**
3576     * Cache the touch slop from the context that created the view.
3577     */
3578    private int mTouchSlop;
3579
3580    /**
3581     * Object that handles automatic animation of view properties.
3582     */
3583    private ViewPropertyAnimator mAnimator = null;
3584
3585    /**
3586     * Flag indicating that a drag can cross window boundaries.  When
3587     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3588     * with this flag set, all visible applications will be able to participate
3589     * in the drag operation and receive the dragged content.
3590     *
3591     * @hide
3592     */
3593    public static final int DRAG_FLAG_GLOBAL = 1;
3594
3595    /**
3596     * Flag indicating that the drag shadow will be opaque.  When
3597     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3598     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3599     */
3600    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3601
3602    /**
3603     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3604     */
3605    private float mVerticalScrollFactor;
3606
3607    /**
3608     * Position of the vertical scroll bar.
3609     */
3610    private int mVerticalScrollbarPosition;
3611
3612    /**
3613     * Position the scroll bar at the default position as determined by the system.
3614     */
3615    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3616
3617    /**
3618     * Position the scroll bar along the left edge.
3619     */
3620    public static final int SCROLLBAR_POSITION_LEFT = 1;
3621
3622    /**
3623     * Position the scroll bar along the right edge.
3624     */
3625    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3626
3627    /**
3628     * Indicates that the view does not have a layer.
3629     *
3630     * @see #getLayerType()
3631     * @see #setLayerType(int, android.graphics.Paint)
3632     * @see #LAYER_TYPE_SOFTWARE
3633     * @see #LAYER_TYPE_HARDWARE
3634     */
3635    public static final int LAYER_TYPE_NONE = 0;
3636
3637    /**
3638     * <p>Indicates that the view has a software layer. A software layer is backed
3639     * by a bitmap and causes the view to be rendered using Android's software
3640     * rendering pipeline, even if hardware acceleration is enabled.</p>
3641     *
3642     * <p>Software layers have various usages:</p>
3643     * <p>When the application is not using hardware acceleration, a software layer
3644     * is useful to apply a specific color filter and/or blending mode and/or
3645     * translucency to a view and all its children.</p>
3646     * <p>When the application is using hardware acceleration, a software layer
3647     * is useful to render drawing primitives not supported by the hardware
3648     * accelerated pipeline. It can also be used to cache a complex view tree
3649     * into a texture and reduce the complexity of drawing operations. For instance,
3650     * when animating a complex view tree with a translation, a software layer can
3651     * be used to render the view tree only once.</p>
3652     * <p>Software layers should be avoided when the affected view tree updates
3653     * often. Every update will require to re-render the software layer, which can
3654     * potentially be slow (particularly when hardware acceleration is turned on
3655     * since the layer will have to be uploaded into a hardware texture after every
3656     * update.)</p>
3657     *
3658     * @see #getLayerType()
3659     * @see #setLayerType(int, android.graphics.Paint)
3660     * @see #LAYER_TYPE_NONE
3661     * @see #LAYER_TYPE_HARDWARE
3662     */
3663    public static final int LAYER_TYPE_SOFTWARE = 1;
3664
3665    /**
3666     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3667     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3668     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3669     * rendering pipeline, but only if hardware acceleration is turned on for the
3670     * view hierarchy. When hardware acceleration is turned off, hardware layers
3671     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3672     *
3673     * <p>A hardware layer is useful to apply a specific color filter and/or
3674     * blending mode and/or translucency to a view and all its children.</p>
3675     * <p>A hardware layer can be used to cache a complex view tree into a
3676     * texture and reduce the complexity of drawing operations. For instance,
3677     * when animating a complex view tree with a translation, a hardware layer can
3678     * be used to render the view tree only once.</p>
3679     * <p>A hardware layer can also be used to increase the rendering quality when
3680     * rotation transformations are applied on a view. It can also be used to
3681     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3682     *
3683     * @see #getLayerType()
3684     * @see #setLayerType(int, android.graphics.Paint)
3685     * @see #LAYER_TYPE_NONE
3686     * @see #LAYER_TYPE_SOFTWARE
3687     */
3688    public static final int LAYER_TYPE_HARDWARE = 2;
3689
3690    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3691            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3692            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3693            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3694    })
3695    int mLayerType = LAYER_TYPE_NONE;
3696    Paint mLayerPaint;
3697
3698    /**
3699     * Set to true when drawing cache is enabled and cannot be created.
3700     *
3701     * @hide
3702     */
3703    public boolean mCachingFailed;
3704    private Bitmap mDrawingCache;
3705    private Bitmap mUnscaledDrawingCache;
3706
3707    /**
3708     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3709     * <p>
3710     * When non-null and valid, this is expected to contain an up-to-date copy
3711     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3712     * cleanup.
3713     */
3714    final RenderNode mRenderNode;
3715
3716    /**
3717     * Set to true when the view is sending hover accessibility events because it
3718     * is the innermost hovered view.
3719     */
3720    private boolean mSendingHoverAccessibilityEvents;
3721
3722    /**
3723     * Delegate for injecting accessibility functionality.
3724     */
3725    AccessibilityDelegate mAccessibilityDelegate;
3726
3727    /**
3728     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3729     * and add/remove objects to/from the overlay directly through the Overlay methods.
3730     */
3731    ViewOverlay mOverlay;
3732
3733    /**
3734     * The currently active parent view for receiving delegated nested scrolling events.
3735     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3736     * by {@link #stopNestedScroll()} at the same point where we clear
3737     * requestDisallowInterceptTouchEvent.
3738     */
3739    private ViewParent mNestedScrollingParent;
3740
3741    /**
3742     * Consistency verifier for debugging purposes.
3743     * @hide
3744     */
3745    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3746            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3747                    new InputEventConsistencyVerifier(this, 0) : null;
3748
3749    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3750
3751    private int[] mTempNestedScrollConsumed;
3752
3753    /**
3754     * An overlay is going to draw this View instead of being drawn as part of this
3755     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3756     * when this view is invalidated.
3757     */
3758    GhostView mGhostView;
3759
3760    /**
3761     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3762     * @hide
3763     */
3764    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3765    public String[] mAttributes;
3766
3767    /**
3768     * Maps a Resource id to its name.
3769     */
3770    private static SparseArray<String> mAttributeMap;
3771
3772    /**
3773     * @hide
3774     */
3775    String mStartActivityRequestWho;
3776
3777    /**
3778     * Simple constructor to use when creating a view from code.
3779     *
3780     * @param context The Context the view is running in, through which it can
3781     *        access the current theme, resources, etc.
3782     */
3783    public View(Context context) {
3784        mContext = context;
3785        mResources = context != null ? context.getResources() : null;
3786        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3787        // Set some flags defaults
3788        mPrivateFlags2 =
3789                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3790                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3791                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3792                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3793                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3794                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3795        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3796        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3797        mUserPaddingStart = UNDEFINED_PADDING;
3798        mUserPaddingEnd = UNDEFINED_PADDING;
3799        mRenderNode = RenderNode.create(getClass().getName(), this);
3800
3801        if (!sCompatibilityDone && context != null) {
3802            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3803
3804            // Older apps may need this compatibility hack for measurement.
3805            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3806
3807            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3808            // of whether a layout was requested on that View.
3809            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3810
3811            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3812
3813            // In M and newer, our widgets can pass a "hint" value in the size
3814            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3815            // know what the expected parent size is going to be, so e.g. list items can size
3816            // themselves at 1/3 the size of their container. It breaks older apps though,
3817            // specifically apps that use some popular open source libraries.
3818            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3819
3820            sCompatibilityDone = true;
3821        }
3822    }
3823
3824    /**
3825     * Constructor that is called when inflating a view from XML. This is called
3826     * when a view is being constructed from an XML file, supplying attributes
3827     * that were specified in the XML file. This version uses a default style of
3828     * 0, so the only attribute values applied are those in the Context's Theme
3829     * and the given AttributeSet.
3830     *
3831     * <p>
3832     * The method onFinishInflate() will be called after all children have been
3833     * added.
3834     *
3835     * @param context The Context the view is running in, through which it can
3836     *        access the current theme, resources, etc.
3837     * @param attrs The attributes of the XML tag that is inflating the view.
3838     * @see #View(Context, AttributeSet, int)
3839     */
3840    public View(Context context, @Nullable AttributeSet attrs) {
3841        this(context, attrs, 0);
3842    }
3843
3844    /**
3845     * Perform inflation from XML and apply a class-specific base style from a
3846     * theme attribute. This constructor of View allows subclasses to use their
3847     * own base style when they are inflating. For example, a Button class's
3848     * constructor would call this version of the super class constructor and
3849     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3850     * allows the theme's button style to modify all of the base view attributes
3851     * (in particular its background) as well as the Button class's attributes.
3852     *
3853     * @param context The Context the view is running in, through which it can
3854     *        access the current theme, resources, etc.
3855     * @param attrs The attributes of the XML tag that is inflating the view.
3856     * @param defStyleAttr An attribute in the current theme that contains a
3857     *        reference to a style resource that supplies default values for
3858     *        the view. Can be 0 to not look for defaults.
3859     * @see #View(Context, AttributeSet)
3860     */
3861    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3862        this(context, attrs, defStyleAttr, 0);
3863    }
3864
3865    /**
3866     * Perform inflation from XML and apply a class-specific base style from a
3867     * theme attribute or style resource. This constructor of View allows
3868     * subclasses to use their own base style when they are inflating.
3869     * <p>
3870     * When determining the final value of a particular attribute, there are
3871     * four inputs that come into play:
3872     * <ol>
3873     * <li>Any attribute values in the given AttributeSet.
3874     * <li>The style resource specified in the AttributeSet (named "style").
3875     * <li>The default style specified by <var>defStyleAttr</var>.
3876     * <li>The default style specified by <var>defStyleRes</var>.
3877     * <li>The base values in this theme.
3878     * </ol>
3879     * <p>
3880     * Each of these inputs is considered in-order, with the first listed taking
3881     * precedence over the following ones. In other words, if in the
3882     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3883     * , then the button's text will <em>always</em> be black, regardless of
3884     * what is specified in any of the styles.
3885     *
3886     * @param context The Context the view is running in, through which it can
3887     *        access the current theme, resources, etc.
3888     * @param attrs The attributes of the XML tag that is inflating the view.
3889     * @param defStyleAttr An attribute in the current theme that contains a
3890     *        reference to a style resource that supplies default values for
3891     *        the view. Can be 0 to not look for defaults.
3892     * @param defStyleRes A resource identifier of a style resource that
3893     *        supplies default values for the view, used only if
3894     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3895     *        to not look for defaults.
3896     * @see #View(Context, AttributeSet, int)
3897     */
3898    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3899        this(context);
3900
3901        final TypedArray a = context.obtainStyledAttributes(
3902                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3903
3904        if (mDebugViewAttributes) {
3905            saveAttributeData(attrs, a);
3906        }
3907
3908        Drawable background = null;
3909
3910        int leftPadding = -1;
3911        int topPadding = -1;
3912        int rightPadding = -1;
3913        int bottomPadding = -1;
3914        int startPadding = UNDEFINED_PADDING;
3915        int endPadding = UNDEFINED_PADDING;
3916
3917        int padding = -1;
3918
3919        int viewFlagValues = 0;
3920        int viewFlagMasks = 0;
3921
3922        boolean setScrollContainer = false;
3923
3924        int x = 0;
3925        int y = 0;
3926
3927        float tx = 0;
3928        float ty = 0;
3929        float tz = 0;
3930        float elevation = 0;
3931        float rotation = 0;
3932        float rotationX = 0;
3933        float rotationY = 0;
3934        float sx = 1f;
3935        float sy = 1f;
3936        boolean transformSet = false;
3937
3938        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3939        int overScrollMode = mOverScrollMode;
3940        boolean initializeScrollbars = false;
3941        boolean initializeScrollIndicators = false;
3942
3943        boolean startPaddingDefined = false;
3944        boolean endPaddingDefined = false;
3945        boolean leftPaddingDefined = false;
3946        boolean rightPaddingDefined = false;
3947
3948        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3949
3950        final int N = a.getIndexCount();
3951        for (int i = 0; i < N; i++) {
3952            int attr = a.getIndex(i);
3953            switch (attr) {
3954                case com.android.internal.R.styleable.View_background:
3955                    background = a.getDrawable(attr);
3956                    break;
3957                case com.android.internal.R.styleable.View_padding:
3958                    padding = a.getDimensionPixelSize(attr, -1);
3959                    mUserPaddingLeftInitial = padding;
3960                    mUserPaddingRightInitial = padding;
3961                    leftPaddingDefined = true;
3962                    rightPaddingDefined = true;
3963                    break;
3964                 case com.android.internal.R.styleable.View_paddingLeft:
3965                    leftPadding = a.getDimensionPixelSize(attr, -1);
3966                    mUserPaddingLeftInitial = leftPadding;
3967                    leftPaddingDefined = true;
3968                    break;
3969                case com.android.internal.R.styleable.View_paddingTop:
3970                    topPadding = a.getDimensionPixelSize(attr, -1);
3971                    break;
3972                case com.android.internal.R.styleable.View_paddingRight:
3973                    rightPadding = a.getDimensionPixelSize(attr, -1);
3974                    mUserPaddingRightInitial = rightPadding;
3975                    rightPaddingDefined = true;
3976                    break;
3977                case com.android.internal.R.styleable.View_paddingBottom:
3978                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3979                    break;
3980                case com.android.internal.R.styleable.View_paddingStart:
3981                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3982                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3983                    break;
3984                case com.android.internal.R.styleable.View_paddingEnd:
3985                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3986                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3987                    break;
3988                case com.android.internal.R.styleable.View_scrollX:
3989                    x = a.getDimensionPixelOffset(attr, 0);
3990                    break;
3991                case com.android.internal.R.styleable.View_scrollY:
3992                    y = a.getDimensionPixelOffset(attr, 0);
3993                    break;
3994                case com.android.internal.R.styleable.View_alpha:
3995                    setAlpha(a.getFloat(attr, 1f));
3996                    break;
3997                case com.android.internal.R.styleable.View_transformPivotX:
3998                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3999                    break;
4000                case com.android.internal.R.styleable.View_transformPivotY:
4001                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4002                    break;
4003                case com.android.internal.R.styleable.View_translationX:
4004                    tx = a.getDimensionPixelOffset(attr, 0);
4005                    transformSet = true;
4006                    break;
4007                case com.android.internal.R.styleable.View_translationY:
4008                    ty = a.getDimensionPixelOffset(attr, 0);
4009                    transformSet = true;
4010                    break;
4011                case com.android.internal.R.styleable.View_translationZ:
4012                    tz = a.getDimensionPixelOffset(attr, 0);
4013                    transformSet = true;
4014                    break;
4015                case com.android.internal.R.styleable.View_elevation:
4016                    elevation = a.getDimensionPixelOffset(attr, 0);
4017                    transformSet = true;
4018                    break;
4019                case com.android.internal.R.styleable.View_rotation:
4020                    rotation = a.getFloat(attr, 0);
4021                    transformSet = true;
4022                    break;
4023                case com.android.internal.R.styleable.View_rotationX:
4024                    rotationX = a.getFloat(attr, 0);
4025                    transformSet = true;
4026                    break;
4027                case com.android.internal.R.styleable.View_rotationY:
4028                    rotationY = a.getFloat(attr, 0);
4029                    transformSet = true;
4030                    break;
4031                case com.android.internal.R.styleable.View_scaleX:
4032                    sx = a.getFloat(attr, 1f);
4033                    transformSet = true;
4034                    break;
4035                case com.android.internal.R.styleable.View_scaleY:
4036                    sy = a.getFloat(attr, 1f);
4037                    transformSet = true;
4038                    break;
4039                case com.android.internal.R.styleable.View_id:
4040                    mID = a.getResourceId(attr, NO_ID);
4041                    break;
4042                case com.android.internal.R.styleable.View_tag:
4043                    mTag = a.getText(attr);
4044                    break;
4045                case com.android.internal.R.styleable.View_fitsSystemWindows:
4046                    if (a.getBoolean(attr, false)) {
4047                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4048                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4049                    }
4050                    break;
4051                case com.android.internal.R.styleable.View_focusable:
4052                    if (a.getBoolean(attr, false)) {
4053                        viewFlagValues |= FOCUSABLE;
4054                        viewFlagMasks |= FOCUSABLE_MASK;
4055                    }
4056                    break;
4057                case com.android.internal.R.styleable.View_focusableInTouchMode:
4058                    if (a.getBoolean(attr, false)) {
4059                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4060                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4061                    }
4062                    break;
4063                case com.android.internal.R.styleable.View_clickable:
4064                    if (a.getBoolean(attr, false)) {
4065                        viewFlagValues |= CLICKABLE;
4066                        viewFlagMasks |= CLICKABLE;
4067                    }
4068                    break;
4069                case com.android.internal.R.styleable.View_longClickable:
4070                    if (a.getBoolean(attr, false)) {
4071                        viewFlagValues |= LONG_CLICKABLE;
4072                        viewFlagMasks |= LONG_CLICKABLE;
4073                    }
4074                    break;
4075                case com.android.internal.R.styleable.View_contextClickable:
4076                    if (a.getBoolean(attr, false)) {
4077                        viewFlagValues |= CONTEXT_CLICKABLE;
4078                        viewFlagMasks |= CONTEXT_CLICKABLE;
4079                    }
4080                    break;
4081                case com.android.internal.R.styleable.View_saveEnabled:
4082                    if (!a.getBoolean(attr, true)) {
4083                        viewFlagValues |= SAVE_DISABLED;
4084                        viewFlagMasks |= SAVE_DISABLED_MASK;
4085                    }
4086                    break;
4087                case com.android.internal.R.styleable.View_duplicateParentState:
4088                    if (a.getBoolean(attr, false)) {
4089                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4090                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4091                    }
4092                    break;
4093                case com.android.internal.R.styleable.View_visibility:
4094                    final int visibility = a.getInt(attr, 0);
4095                    if (visibility != 0) {
4096                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4097                        viewFlagMasks |= VISIBILITY_MASK;
4098                    }
4099                    break;
4100                case com.android.internal.R.styleable.View_layoutDirection:
4101                    // Clear any layout direction flags (included resolved bits) already set
4102                    mPrivateFlags2 &=
4103                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4104                    // Set the layout direction flags depending on the value of the attribute
4105                    final int layoutDirection = a.getInt(attr, -1);
4106                    final int value = (layoutDirection != -1) ?
4107                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4108                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4109                    break;
4110                case com.android.internal.R.styleable.View_drawingCacheQuality:
4111                    final int cacheQuality = a.getInt(attr, 0);
4112                    if (cacheQuality != 0) {
4113                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4114                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4115                    }
4116                    break;
4117                case com.android.internal.R.styleable.View_contentDescription:
4118                    setContentDescription(a.getString(attr));
4119                    break;
4120                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4121                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4122                    break;
4123                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4124                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4125                    break;
4126                case com.android.internal.R.styleable.View_labelFor:
4127                    setLabelFor(a.getResourceId(attr, NO_ID));
4128                    break;
4129                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4130                    if (!a.getBoolean(attr, true)) {
4131                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4132                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4133                    }
4134                    break;
4135                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4136                    if (!a.getBoolean(attr, true)) {
4137                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4138                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4139                    }
4140                    break;
4141                case R.styleable.View_scrollbars:
4142                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4143                    if (scrollbars != SCROLLBARS_NONE) {
4144                        viewFlagValues |= scrollbars;
4145                        viewFlagMasks |= SCROLLBARS_MASK;
4146                        initializeScrollbars = true;
4147                    }
4148                    break;
4149                //noinspection deprecation
4150                case R.styleable.View_fadingEdge:
4151                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4152                        // Ignore the attribute starting with ICS
4153                        break;
4154                    }
4155                    // With builds < ICS, fall through and apply fading edges
4156                case R.styleable.View_requiresFadingEdge:
4157                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4158                    if (fadingEdge != FADING_EDGE_NONE) {
4159                        viewFlagValues |= fadingEdge;
4160                        viewFlagMasks |= FADING_EDGE_MASK;
4161                        initializeFadingEdgeInternal(a);
4162                    }
4163                    break;
4164                case R.styleable.View_scrollbarStyle:
4165                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4166                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4167                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4168                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4169                    }
4170                    break;
4171                case R.styleable.View_isScrollContainer:
4172                    setScrollContainer = true;
4173                    if (a.getBoolean(attr, false)) {
4174                        setScrollContainer(true);
4175                    }
4176                    break;
4177                case com.android.internal.R.styleable.View_keepScreenOn:
4178                    if (a.getBoolean(attr, false)) {
4179                        viewFlagValues |= KEEP_SCREEN_ON;
4180                        viewFlagMasks |= KEEP_SCREEN_ON;
4181                    }
4182                    break;
4183                case R.styleable.View_filterTouchesWhenObscured:
4184                    if (a.getBoolean(attr, false)) {
4185                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4186                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4187                    }
4188                    break;
4189                case R.styleable.View_nextFocusLeft:
4190                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4191                    break;
4192                case R.styleable.View_nextFocusRight:
4193                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4194                    break;
4195                case R.styleable.View_nextFocusUp:
4196                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4197                    break;
4198                case R.styleable.View_nextFocusDown:
4199                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4200                    break;
4201                case R.styleable.View_nextFocusForward:
4202                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4203                    break;
4204                case R.styleable.View_minWidth:
4205                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4206                    break;
4207                case R.styleable.View_minHeight:
4208                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4209                    break;
4210                case R.styleable.View_onClick:
4211                    if (context.isRestricted()) {
4212                        throw new IllegalStateException("The android:onClick attribute cannot "
4213                                + "be used within a restricted context");
4214                    }
4215
4216                    final String handlerName = a.getString(attr);
4217                    if (handlerName != null) {
4218                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4219                    }
4220                    break;
4221                case R.styleable.View_overScrollMode:
4222                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4223                    break;
4224                case R.styleable.View_verticalScrollbarPosition:
4225                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4226                    break;
4227                case R.styleable.View_layerType:
4228                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4229                    break;
4230                case R.styleable.View_textDirection:
4231                    // Clear any text direction flag already set
4232                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4233                    // Set the text direction flags depending on the value of the attribute
4234                    final int textDirection = a.getInt(attr, -1);
4235                    if (textDirection != -1) {
4236                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4237                    }
4238                    break;
4239                case R.styleable.View_textAlignment:
4240                    // Clear any text alignment flag already set
4241                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4242                    // Set the text alignment flag depending on the value of the attribute
4243                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4244                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4245                    break;
4246                case R.styleable.View_importantForAccessibility:
4247                    setImportantForAccessibility(a.getInt(attr,
4248                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4249                    break;
4250                case R.styleable.View_accessibilityLiveRegion:
4251                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4252                    break;
4253                case R.styleable.View_transitionName:
4254                    setTransitionName(a.getString(attr));
4255                    break;
4256                case R.styleable.View_nestedScrollingEnabled:
4257                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4258                    break;
4259                case R.styleable.View_stateListAnimator:
4260                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4261                            a.getResourceId(attr, 0)));
4262                    break;
4263                case R.styleable.View_backgroundTint:
4264                    // This will get applied later during setBackground().
4265                    if (mBackgroundTint == null) {
4266                        mBackgroundTint = new TintInfo();
4267                    }
4268                    mBackgroundTint.mTintList = a.getColorStateList(
4269                            R.styleable.View_backgroundTint);
4270                    mBackgroundTint.mHasTintList = true;
4271                    break;
4272                case R.styleable.View_backgroundTintMode:
4273                    // This will get applied later during setBackground().
4274                    if (mBackgroundTint == null) {
4275                        mBackgroundTint = new TintInfo();
4276                    }
4277                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4278                            R.styleable.View_backgroundTintMode, -1), null);
4279                    mBackgroundTint.mHasTintMode = true;
4280                    break;
4281                case R.styleable.View_outlineProvider:
4282                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4283                            PROVIDER_BACKGROUND));
4284                    break;
4285                case R.styleable.View_foreground:
4286                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4287                        setForeground(a.getDrawable(attr));
4288                    }
4289                    break;
4290                case R.styleable.View_foregroundGravity:
4291                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4292                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4293                    }
4294                    break;
4295                case R.styleable.View_foregroundTintMode:
4296                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4297                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4298                    }
4299                    break;
4300                case R.styleable.View_foregroundTint:
4301                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4302                        setForegroundTintList(a.getColorStateList(attr));
4303                    }
4304                    break;
4305                case R.styleable.View_foregroundInsidePadding:
4306                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4307                        if (mForegroundInfo == null) {
4308                            mForegroundInfo = new ForegroundInfo();
4309                        }
4310                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4311                                mForegroundInfo.mInsidePadding);
4312                    }
4313                    break;
4314                case R.styleable.View_scrollIndicators:
4315                    final int scrollIndicators =
4316                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4317                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4318                    if (scrollIndicators != 0) {
4319                        mPrivateFlags3 |= scrollIndicators;
4320                        initializeScrollIndicators = true;
4321                    }
4322                    break;
4323            }
4324        }
4325
4326        setOverScrollMode(overScrollMode);
4327
4328        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4329        // the resolved layout direction). Those cached values will be used later during padding
4330        // resolution.
4331        mUserPaddingStart = startPadding;
4332        mUserPaddingEnd = endPadding;
4333
4334        if (background != null) {
4335            setBackground(background);
4336        }
4337
4338        // setBackground above will record that padding is currently provided by the background.
4339        // If we have padding specified via xml, record that here instead and use it.
4340        mLeftPaddingDefined = leftPaddingDefined;
4341        mRightPaddingDefined = rightPaddingDefined;
4342
4343        if (padding >= 0) {
4344            leftPadding = padding;
4345            topPadding = padding;
4346            rightPadding = padding;
4347            bottomPadding = padding;
4348            mUserPaddingLeftInitial = padding;
4349            mUserPaddingRightInitial = padding;
4350        }
4351
4352        if (isRtlCompatibilityMode()) {
4353            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4354            // left / right padding are used if defined (meaning here nothing to do). If they are not
4355            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4356            // start / end and resolve them as left / right (layout direction is not taken into account).
4357            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4358            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4359            // defined.
4360            if (!mLeftPaddingDefined && startPaddingDefined) {
4361                leftPadding = startPadding;
4362            }
4363            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4364            if (!mRightPaddingDefined && endPaddingDefined) {
4365                rightPadding = endPadding;
4366            }
4367            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4368        } else {
4369            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4370            // values defined. Otherwise, left /right values are used.
4371            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4372            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4373            // defined.
4374            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4375
4376            if (mLeftPaddingDefined && !hasRelativePadding) {
4377                mUserPaddingLeftInitial = leftPadding;
4378            }
4379            if (mRightPaddingDefined && !hasRelativePadding) {
4380                mUserPaddingRightInitial = rightPadding;
4381            }
4382        }
4383
4384        internalSetPadding(
4385                mUserPaddingLeftInitial,
4386                topPadding >= 0 ? topPadding : mPaddingTop,
4387                mUserPaddingRightInitial,
4388                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4389
4390        if (viewFlagMasks != 0) {
4391            setFlags(viewFlagValues, viewFlagMasks);
4392        }
4393
4394        if (initializeScrollbars) {
4395            initializeScrollbarsInternal(a);
4396        }
4397
4398        if (initializeScrollIndicators) {
4399            initializeScrollIndicatorsInternal();
4400        }
4401
4402        a.recycle();
4403
4404        // Needs to be called after mViewFlags is set
4405        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4406            recomputePadding();
4407        }
4408
4409        if (x != 0 || y != 0) {
4410            scrollTo(x, y);
4411        }
4412
4413        if (transformSet) {
4414            setTranslationX(tx);
4415            setTranslationY(ty);
4416            setTranslationZ(tz);
4417            setElevation(elevation);
4418            setRotation(rotation);
4419            setRotationX(rotationX);
4420            setRotationY(rotationY);
4421            setScaleX(sx);
4422            setScaleY(sy);
4423        }
4424
4425        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4426            setScrollContainer(true);
4427        }
4428
4429        computeOpaqueFlags();
4430    }
4431
4432    /**
4433     * An implementation of OnClickListener that attempts to lazily load a
4434     * named click handling method from a parent or ancestor context.
4435     */
4436    private static class DeclaredOnClickListener implements OnClickListener {
4437        private final View mHostView;
4438        private final String mMethodName;
4439
4440        private Method mResolvedMethod;
4441        private Context mResolvedContext;
4442
4443        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4444            mHostView = hostView;
4445            mMethodName = methodName;
4446        }
4447
4448        @Override
4449        public void onClick(@NonNull View v) {
4450            if (mResolvedMethod == null) {
4451                resolveMethod(mHostView.getContext(), mMethodName);
4452            }
4453
4454            try {
4455                mResolvedMethod.invoke(mResolvedContext, v);
4456            } catch (IllegalAccessException e) {
4457                throw new IllegalStateException(
4458                        "Could not execute non-public method for android:onClick", e);
4459            } catch (InvocationTargetException e) {
4460                throw new IllegalStateException(
4461                        "Could not execute method for android:onClick", e);
4462            }
4463        }
4464
4465        @NonNull
4466        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4467            while (context != null) {
4468                try {
4469                    if (!context.isRestricted()) {
4470                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4471                        if (method != null) {
4472                            mResolvedMethod = method;
4473                            mResolvedContext = context;
4474                            return;
4475                        }
4476                    }
4477                } catch (NoSuchMethodException e) {
4478                    // Failed to find method, keep searching up the hierarchy.
4479                }
4480
4481                if (context instanceof ContextWrapper) {
4482                    context = ((ContextWrapper) context).getBaseContext();
4483                } else {
4484                    // Can't search up the hierarchy, null out and fail.
4485                    context = null;
4486                }
4487            }
4488
4489            final int id = mHostView.getId();
4490            final String idText = id == NO_ID ? "" : " with id '"
4491                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4492            throw new IllegalStateException("Could not find method " + mMethodName
4493                    + "(View) in a parent or ancestor Context for android:onClick "
4494                    + "attribute defined on view " + mHostView.getClass() + idText);
4495        }
4496    }
4497
4498    /**
4499     * Non-public constructor for use in testing
4500     */
4501    View() {
4502        mResources = null;
4503        mRenderNode = RenderNode.create(getClass().getName(), this);
4504    }
4505
4506    private static SparseArray<String> getAttributeMap() {
4507        if (mAttributeMap == null) {
4508            mAttributeMap = new SparseArray<>();
4509        }
4510        return mAttributeMap;
4511    }
4512
4513    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4514        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4515        final int indexCount = t.getIndexCount();
4516        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4517
4518        int i = 0;
4519
4520        // Store raw XML attributes.
4521        for (int j = 0; j < attrsCount; ++j) {
4522            attributes[i] = attrs.getAttributeName(j);
4523            attributes[i + 1] = attrs.getAttributeValue(j);
4524            i += 2;
4525        }
4526
4527        // Store resolved styleable attributes.
4528        final Resources res = t.getResources();
4529        final SparseArray<String> attributeMap = getAttributeMap();
4530        for (int j = 0; j < indexCount; ++j) {
4531            final int index = t.getIndex(j);
4532            if (!t.hasValueOrEmpty(index)) {
4533                // Value is undefined. Skip it.
4534                continue;
4535            }
4536
4537            final int resourceId = t.getResourceId(index, 0);
4538            if (resourceId == 0) {
4539                // Value is not a reference. Skip it.
4540                continue;
4541            }
4542
4543            String resourceName = attributeMap.get(resourceId);
4544            if (resourceName == null) {
4545                try {
4546                    resourceName = res.getResourceName(resourceId);
4547                } catch (Resources.NotFoundException e) {
4548                    resourceName = "0x" + Integer.toHexString(resourceId);
4549                }
4550                attributeMap.put(resourceId, resourceName);
4551            }
4552
4553            attributes[i] = resourceName;
4554            attributes[i + 1] = t.getString(index);
4555            i += 2;
4556        }
4557
4558        // Trim to fit contents.
4559        final String[] trimmed = new String[i];
4560        System.arraycopy(attributes, 0, trimmed, 0, i);
4561        mAttributes = trimmed;
4562    }
4563
4564    public String toString() {
4565        StringBuilder out = new StringBuilder(128);
4566        out.append(getClass().getName());
4567        out.append('{');
4568        out.append(Integer.toHexString(System.identityHashCode(this)));
4569        out.append(' ');
4570        switch (mViewFlags&VISIBILITY_MASK) {
4571            case VISIBLE: out.append('V'); break;
4572            case INVISIBLE: out.append('I'); break;
4573            case GONE: out.append('G'); break;
4574            default: out.append('.'); break;
4575        }
4576        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4577        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4578        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4579        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4580        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4581        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4582        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4583        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4584        out.append(' ');
4585        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4586        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4587        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4588        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4589            out.append('p');
4590        } else {
4591            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4592        }
4593        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4594        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4595        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4596        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4597        out.append(' ');
4598        out.append(mLeft);
4599        out.append(',');
4600        out.append(mTop);
4601        out.append('-');
4602        out.append(mRight);
4603        out.append(',');
4604        out.append(mBottom);
4605        final int id = getId();
4606        if (id != NO_ID) {
4607            out.append(" #");
4608            out.append(Integer.toHexString(id));
4609            final Resources r = mResources;
4610            if (Resources.resourceHasPackage(id) && r != null) {
4611                try {
4612                    String pkgname;
4613                    switch (id&0xff000000) {
4614                        case 0x7f000000:
4615                            pkgname="app";
4616                            break;
4617                        case 0x01000000:
4618                            pkgname="android";
4619                            break;
4620                        default:
4621                            pkgname = r.getResourcePackageName(id);
4622                            break;
4623                    }
4624                    String typename = r.getResourceTypeName(id);
4625                    String entryname = r.getResourceEntryName(id);
4626                    out.append(" ");
4627                    out.append(pkgname);
4628                    out.append(":");
4629                    out.append(typename);
4630                    out.append("/");
4631                    out.append(entryname);
4632                } catch (Resources.NotFoundException e) {
4633                }
4634            }
4635        }
4636        out.append("}");
4637        return out.toString();
4638    }
4639
4640    /**
4641     * <p>
4642     * Initializes the fading edges from a given set of styled attributes. This
4643     * method should be called by subclasses that need fading edges and when an
4644     * instance of these subclasses is created programmatically rather than
4645     * being inflated from XML. This method is automatically called when the XML
4646     * is inflated.
4647     * </p>
4648     *
4649     * @param a the styled attributes set to initialize the fading edges from
4650     *
4651     * @removed
4652     */
4653    protected void initializeFadingEdge(TypedArray a) {
4654        // This method probably shouldn't have been included in the SDK to begin with.
4655        // It relies on 'a' having been initialized using an attribute filter array that is
4656        // not publicly available to the SDK. The old method has been renamed
4657        // to initializeFadingEdgeInternal and hidden for framework use only;
4658        // this one initializes using defaults to make it safe to call for apps.
4659
4660        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4661
4662        initializeFadingEdgeInternal(arr);
4663
4664        arr.recycle();
4665    }
4666
4667    /**
4668     * <p>
4669     * Initializes the fading edges from a given set of styled attributes. This
4670     * method should be called by subclasses that need fading edges and when an
4671     * instance of these subclasses is created programmatically rather than
4672     * being inflated from XML. This method is automatically called when the XML
4673     * is inflated.
4674     * </p>
4675     *
4676     * @param a the styled attributes set to initialize the fading edges from
4677     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4678     */
4679    protected void initializeFadingEdgeInternal(TypedArray a) {
4680        initScrollCache();
4681
4682        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4683                R.styleable.View_fadingEdgeLength,
4684                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4685    }
4686
4687    /**
4688     * Returns the size of the vertical faded edges used to indicate that more
4689     * content in this view is visible.
4690     *
4691     * @return The size in pixels of the vertical faded edge or 0 if vertical
4692     *         faded edges are not enabled for this view.
4693     * @attr ref android.R.styleable#View_fadingEdgeLength
4694     */
4695    public int getVerticalFadingEdgeLength() {
4696        if (isVerticalFadingEdgeEnabled()) {
4697            ScrollabilityCache cache = mScrollCache;
4698            if (cache != null) {
4699                return cache.fadingEdgeLength;
4700            }
4701        }
4702        return 0;
4703    }
4704
4705    /**
4706     * Set the size of the faded edge used to indicate that more content in this
4707     * view is available.  Will not change whether the fading edge is enabled; use
4708     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4709     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4710     * for the vertical or horizontal fading edges.
4711     *
4712     * @param length The size in pixels of the faded edge used to indicate that more
4713     *        content in this view is visible.
4714     */
4715    public void setFadingEdgeLength(int length) {
4716        initScrollCache();
4717        mScrollCache.fadingEdgeLength = length;
4718    }
4719
4720    /**
4721     * Returns the size of the horizontal faded edges used to indicate that more
4722     * content in this view is visible.
4723     *
4724     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4725     *         faded edges are not enabled for this view.
4726     * @attr ref android.R.styleable#View_fadingEdgeLength
4727     */
4728    public int getHorizontalFadingEdgeLength() {
4729        if (isHorizontalFadingEdgeEnabled()) {
4730            ScrollabilityCache cache = mScrollCache;
4731            if (cache != null) {
4732                return cache.fadingEdgeLength;
4733            }
4734        }
4735        return 0;
4736    }
4737
4738    /**
4739     * Returns the width of the vertical scrollbar.
4740     *
4741     * @return The width in pixels of the vertical scrollbar or 0 if there
4742     *         is no vertical scrollbar.
4743     */
4744    public int getVerticalScrollbarWidth() {
4745        ScrollabilityCache cache = mScrollCache;
4746        if (cache != null) {
4747            ScrollBarDrawable scrollBar = cache.scrollBar;
4748            if (scrollBar != null) {
4749                int size = scrollBar.getSize(true);
4750                if (size <= 0) {
4751                    size = cache.scrollBarSize;
4752                }
4753                return size;
4754            }
4755            return 0;
4756        }
4757        return 0;
4758    }
4759
4760    /**
4761     * Returns the height of the horizontal scrollbar.
4762     *
4763     * @return The height in pixels of the horizontal scrollbar or 0 if
4764     *         there is no horizontal scrollbar.
4765     */
4766    protected int getHorizontalScrollbarHeight() {
4767        ScrollabilityCache cache = mScrollCache;
4768        if (cache != null) {
4769            ScrollBarDrawable scrollBar = cache.scrollBar;
4770            if (scrollBar != null) {
4771                int size = scrollBar.getSize(false);
4772                if (size <= 0) {
4773                    size = cache.scrollBarSize;
4774                }
4775                return size;
4776            }
4777            return 0;
4778        }
4779        return 0;
4780    }
4781
4782    /**
4783     * <p>
4784     * Initializes the scrollbars from a given set of styled attributes. This
4785     * method should be called by subclasses that need scrollbars and when an
4786     * instance of these subclasses is created programmatically rather than
4787     * being inflated from XML. This method is automatically called when the XML
4788     * is inflated.
4789     * </p>
4790     *
4791     * @param a the styled attributes set to initialize the scrollbars from
4792     *
4793     * @removed
4794     */
4795    protected void initializeScrollbars(TypedArray a) {
4796        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4797        // using the View filter array which is not available to the SDK. As such, internal
4798        // framework usage now uses initializeScrollbarsInternal and we grab a default
4799        // TypedArray with the right filter instead here.
4800        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4801
4802        initializeScrollbarsInternal(arr);
4803
4804        // We ignored the method parameter. Recycle the one we actually did use.
4805        arr.recycle();
4806    }
4807
4808    /**
4809     * <p>
4810     * Initializes the scrollbars from a given set of styled attributes. This
4811     * method should be called by subclasses that need scrollbars and when an
4812     * instance of these subclasses is created programmatically rather than
4813     * being inflated from XML. This method is automatically called when the XML
4814     * is inflated.
4815     * </p>
4816     *
4817     * @param a the styled attributes set to initialize the scrollbars from
4818     * @hide
4819     */
4820    protected void initializeScrollbarsInternal(TypedArray a) {
4821        initScrollCache();
4822
4823        final ScrollabilityCache scrollabilityCache = mScrollCache;
4824
4825        if (scrollabilityCache.scrollBar == null) {
4826            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4827            scrollabilityCache.scrollBar.setCallback(this);
4828            scrollabilityCache.scrollBar.setState(getDrawableState());
4829        }
4830
4831        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4832
4833        if (!fadeScrollbars) {
4834            scrollabilityCache.state = ScrollabilityCache.ON;
4835        }
4836        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4837
4838
4839        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4840                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4841                        .getScrollBarFadeDuration());
4842        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4843                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4844                ViewConfiguration.getScrollDefaultDelay());
4845
4846
4847        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4848                com.android.internal.R.styleable.View_scrollbarSize,
4849                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4850
4851        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4852        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4853
4854        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4855        if (thumb != null) {
4856            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4857        }
4858
4859        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4860                false);
4861        if (alwaysDraw) {
4862            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4863        }
4864
4865        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4866        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4867
4868        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4869        if (thumb != null) {
4870            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4871        }
4872
4873        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4874                false);
4875        if (alwaysDraw) {
4876            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4877        }
4878
4879        // Apply layout direction to the new Drawables if needed
4880        final int layoutDirection = getLayoutDirection();
4881        if (track != null) {
4882            track.setLayoutDirection(layoutDirection);
4883        }
4884        if (thumb != null) {
4885            thumb.setLayoutDirection(layoutDirection);
4886        }
4887
4888        // Re-apply user/background padding so that scrollbar(s) get added
4889        resolvePadding();
4890    }
4891
4892    private void initializeScrollIndicatorsInternal() {
4893        // Some day maybe we'll break this into top/left/start/etc. and let the
4894        // client control it. Until then, you can have any scroll indicator you
4895        // want as long as it's a 1dp foreground-colored rectangle.
4896        if (mScrollIndicatorDrawable == null) {
4897            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4898        }
4899    }
4900
4901    /**
4902     * <p>
4903     * Initalizes the scrollability cache if necessary.
4904     * </p>
4905     */
4906    private void initScrollCache() {
4907        if (mScrollCache == null) {
4908            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4909        }
4910    }
4911
4912    private ScrollabilityCache getScrollCache() {
4913        initScrollCache();
4914        return mScrollCache;
4915    }
4916
4917    /**
4918     * Set the position of the vertical scroll bar. Should be one of
4919     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4920     * {@link #SCROLLBAR_POSITION_RIGHT}.
4921     *
4922     * @param position Where the vertical scroll bar should be positioned.
4923     */
4924    public void setVerticalScrollbarPosition(int position) {
4925        if (mVerticalScrollbarPosition != position) {
4926            mVerticalScrollbarPosition = position;
4927            computeOpaqueFlags();
4928            resolvePadding();
4929        }
4930    }
4931
4932    /**
4933     * @return The position where the vertical scroll bar will show, if applicable.
4934     * @see #setVerticalScrollbarPosition(int)
4935     */
4936    public int getVerticalScrollbarPosition() {
4937        return mVerticalScrollbarPosition;
4938    }
4939
4940    /**
4941     * Sets the state of all scroll indicators.
4942     * <p>
4943     * See {@link #setScrollIndicators(int, int)} for usage information.
4944     *
4945     * @param indicators a bitmask of indicators that should be enabled, or
4946     *                   {@code 0} to disable all indicators
4947     * @see #setScrollIndicators(int, int)
4948     * @see #getScrollIndicators()
4949     * @attr ref android.R.styleable#View_scrollIndicators
4950     */
4951    public void setScrollIndicators(@ScrollIndicators int indicators) {
4952        setScrollIndicators(indicators,
4953                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
4954    }
4955
4956    /**
4957     * Sets the state of the scroll indicators specified by the mask. To change
4958     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
4959     * <p>
4960     * When a scroll indicator is enabled, it will be displayed if the view
4961     * can scroll in the direction of the indicator.
4962     * <p>
4963     * Multiple indicator types may be enabled or disabled by passing the
4964     * logical OR of the desired types. If multiple types are specified, they
4965     * will all be set to the same enabled state.
4966     * <p>
4967     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
4968     *
4969     * @param indicators the indicator direction, or the logical OR of multiple
4970     *             indicator directions. One or more of:
4971     *             <ul>
4972     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
4973     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
4974     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
4975     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
4976     *               <li>{@link #SCROLL_INDICATOR_START}</li>
4977     *               <li>{@link #SCROLL_INDICATOR_END}</li>
4978     *             </ul>
4979     * @see #setScrollIndicators(int)
4980     * @see #getScrollIndicators()
4981     * @attr ref android.R.styleable#View_scrollIndicators
4982     */
4983    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
4984        // Shift and sanitize mask.
4985        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4986        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
4987
4988        // Shift and mask indicators.
4989        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4990        indicators &= mask;
4991
4992        // Merge with non-masked flags.
4993        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
4994
4995        if (mPrivateFlags3 != updatedFlags) {
4996            mPrivateFlags3 = updatedFlags;
4997
4998            if (indicators != 0) {
4999                initializeScrollIndicatorsInternal();
5000            }
5001            invalidate();
5002        }
5003    }
5004
5005    /**
5006     * Returns a bitmask representing the enabled scroll indicators.
5007     * <p>
5008     * For example, if the top and left scroll indicators are enabled and all
5009     * other indicators are disabled, the return value will be
5010     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5011     * <p>
5012     * To check whether the bottom scroll indicator is enabled, use the value
5013     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5014     *
5015     * @return a bitmask representing the enabled scroll indicators
5016     */
5017    @ScrollIndicators
5018    public int getScrollIndicators() {
5019        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5020                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5021    }
5022
5023    ListenerInfo getListenerInfo() {
5024        if (mListenerInfo != null) {
5025            return mListenerInfo;
5026        }
5027        mListenerInfo = new ListenerInfo();
5028        return mListenerInfo;
5029    }
5030
5031    /**
5032     * Register a callback to be invoked when the scroll X or Y positions of
5033     * this view change.
5034     * <p>
5035     * <b>Note:</b> Some views handle scrolling independently from View and may
5036     * have their own separate listeners for scroll-type events. For example,
5037     * {@link android.widget.ListView ListView} allows clients to register an
5038     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5039     * to listen for changes in list scroll position.
5040     *
5041     * @param l The listener to notify when the scroll X or Y position changes.
5042     * @see android.view.View#getScrollX()
5043     * @see android.view.View#getScrollY()
5044     */
5045    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5046        getListenerInfo().mOnScrollChangeListener = l;
5047    }
5048
5049    /**
5050     * Register a callback to be invoked when focus of this view changed.
5051     *
5052     * @param l The callback that will run.
5053     */
5054    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5055        getListenerInfo().mOnFocusChangeListener = l;
5056    }
5057
5058    /**
5059     * Add a listener that will be called when the bounds of the view change due to
5060     * layout processing.
5061     *
5062     * @param listener The listener that will be called when layout bounds change.
5063     */
5064    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5065        ListenerInfo li = getListenerInfo();
5066        if (li.mOnLayoutChangeListeners == null) {
5067            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5068        }
5069        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5070            li.mOnLayoutChangeListeners.add(listener);
5071        }
5072    }
5073
5074    /**
5075     * Remove a listener for layout changes.
5076     *
5077     * @param listener The listener for layout bounds change.
5078     */
5079    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5080        ListenerInfo li = mListenerInfo;
5081        if (li == null || li.mOnLayoutChangeListeners == null) {
5082            return;
5083        }
5084        li.mOnLayoutChangeListeners.remove(listener);
5085    }
5086
5087    /**
5088     * Add a listener for attach state changes.
5089     *
5090     * This listener will be called whenever this view is attached or detached
5091     * from a window. Remove the listener using
5092     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5093     *
5094     * @param listener Listener to attach
5095     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5096     */
5097    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5098        ListenerInfo li = getListenerInfo();
5099        if (li.mOnAttachStateChangeListeners == null) {
5100            li.mOnAttachStateChangeListeners
5101                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5102        }
5103        li.mOnAttachStateChangeListeners.add(listener);
5104    }
5105
5106    /**
5107     * Remove a listener for attach state changes. The listener will receive no further
5108     * notification of window attach/detach events.
5109     *
5110     * @param listener Listener to remove
5111     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5112     */
5113    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5114        ListenerInfo li = mListenerInfo;
5115        if (li == null || li.mOnAttachStateChangeListeners == null) {
5116            return;
5117        }
5118        li.mOnAttachStateChangeListeners.remove(listener);
5119    }
5120
5121    /**
5122     * Returns the focus-change callback registered for this view.
5123     *
5124     * @return The callback, or null if one is not registered.
5125     */
5126    public OnFocusChangeListener getOnFocusChangeListener() {
5127        ListenerInfo li = mListenerInfo;
5128        return li != null ? li.mOnFocusChangeListener : null;
5129    }
5130
5131    /**
5132     * Register a callback to be invoked when this view is clicked. If this view is not
5133     * clickable, it becomes clickable.
5134     *
5135     * @param l The callback that will run
5136     *
5137     * @see #setClickable(boolean)
5138     */
5139    public void setOnClickListener(@Nullable OnClickListener l) {
5140        if (!isClickable()) {
5141            setClickable(true);
5142        }
5143        getListenerInfo().mOnClickListener = l;
5144    }
5145
5146    /**
5147     * Return whether this view has an attached OnClickListener.  Returns
5148     * true if there is a listener, false if there is none.
5149     */
5150    public boolean hasOnClickListeners() {
5151        ListenerInfo li = mListenerInfo;
5152        return (li != null && li.mOnClickListener != null);
5153    }
5154
5155    /**
5156     * Register a callback to be invoked when this view is clicked and held. If this view is not
5157     * long clickable, it becomes long clickable.
5158     *
5159     * @param l The callback that will run
5160     *
5161     * @see #setLongClickable(boolean)
5162     */
5163    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5164        if (!isLongClickable()) {
5165            setLongClickable(true);
5166        }
5167        getListenerInfo().mOnLongClickListener = l;
5168    }
5169
5170    /**
5171     * Register a callback to be invoked when this view is context clicked. If the view is not
5172     * context clickable, it becomes context clickable.
5173     *
5174     * @param l The callback that will run
5175     * @see #setContextClickable(boolean)
5176     */
5177    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5178        if (!isContextClickable()) {
5179            setContextClickable(true);
5180        }
5181        getListenerInfo().mOnContextClickListener = l;
5182    }
5183
5184    /**
5185     * Register a callback to be invoked when the context menu for this view is
5186     * being built. If this view is not long clickable, it becomes long clickable.
5187     *
5188     * @param l The callback that will run
5189     *
5190     */
5191    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5192        if (!isLongClickable()) {
5193            setLongClickable(true);
5194        }
5195        getListenerInfo().mOnCreateContextMenuListener = l;
5196    }
5197
5198    /**
5199     * Call this view's OnClickListener, if it is defined.  Performs all normal
5200     * actions associated with clicking: reporting accessibility event, playing
5201     * a sound, etc.
5202     *
5203     * @return True there was an assigned OnClickListener that was called, false
5204     *         otherwise is returned.
5205     */
5206    public boolean performClick() {
5207        final boolean result;
5208        final ListenerInfo li = mListenerInfo;
5209        if (li != null && li.mOnClickListener != null) {
5210            playSoundEffect(SoundEffectConstants.CLICK);
5211            li.mOnClickListener.onClick(this);
5212            result = true;
5213        } else {
5214            result = false;
5215        }
5216
5217        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5218        return result;
5219    }
5220
5221    /**
5222     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5223     * this only calls the listener, and does not do any associated clicking
5224     * actions like reporting an accessibility event.
5225     *
5226     * @return True there was an assigned OnClickListener that was called, false
5227     *         otherwise is returned.
5228     */
5229    public boolean callOnClick() {
5230        ListenerInfo li = mListenerInfo;
5231        if (li != null && li.mOnClickListener != null) {
5232            li.mOnClickListener.onClick(this);
5233            return true;
5234        }
5235        return false;
5236    }
5237
5238    /**
5239     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5240     * OnLongClickListener did not consume the event.
5241     *
5242     * @return True if one of the above receivers consumed the event, false otherwise.
5243     */
5244    public boolean performLongClick() {
5245        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5246
5247        boolean handled = false;
5248        ListenerInfo li = mListenerInfo;
5249        if (li != null && li.mOnLongClickListener != null) {
5250            handled = li.mOnLongClickListener.onLongClick(View.this);
5251        }
5252        if (!handled) {
5253            handled = showContextMenu();
5254        }
5255        if (handled) {
5256            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5257        }
5258        return handled;
5259    }
5260
5261    /**
5262     * Call this view's OnContextClickListener, if it is defined.
5263     *
5264     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5265     *         otherwise.
5266     */
5267    public boolean performContextClick() {
5268        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5269
5270        boolean handled = false;
5271        ListenerInfo li = mListenerInfo;
5272        if (li != null && li.mOnContextClickListener != null) {
5273            handled = li.mOnContextClickListener.onContextClick(View.this);
5274        }
5275        if (handled) {
5276            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5277        }
5278        return handled;
5279    }
5280
5281    /**
5282     * Performs button-related actions during a touch down event.
5283     *
5284     * @param event The event.
5285     * @return True if the down was consumed.
5286     *
5287     * @hide
5288     */
5289    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5290        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5291            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5292            showContextMenu(event.getX(), event.getY(), event.getMetaState());
5293            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5294            return true;
5295        }
5296        return false;
5297    }
5298
5299    /**
5300     * Bring up the context menu for this view.
5301     *
5302     * @return Whether a context menu was displayed.
5303     */
5304    public boolean showContextMenu() {
5305        return getParent().showContextMenuForChild(this);
5306    }
5307
5308    /**
5309     * Bring up the context menu for this view, referring to the item under the specified point.
5310     *
5311     * @param x The referenced x coordinate.
5312     * @param y The referenced y coordinate.
5313     * @param metaState The keyboard modifiers that were pressed.
5314     * @return Whether a context menu was displayed.
5315     *
5316     * @hide
5317     */
5318    public boolean showContextMenu(float x, float y, int metaState) {
5319        return showContextMenu();
5320    }
5321
5322    /**
5323     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5324     *
5325     * @param callback Callback that will control the lifecycle of the action mode
5326     * @return The new action mode if it is started, null otherwise
5327     *
5328     * @see ActionMode
5329     * @see #startActionMode(android.view.ActionMode.Callback, int)
5330     */
5331    public ActionMode startActionMode(ActionMode.Callback callback) {
5332        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5333    }
5334
5335    /**
5336     * Start an action mode with the given type.
5337     *
5338     * @param callback Callback that will control the lifecycle of the action mode
5339     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5340     * @return The new action mode if it is started, null otherwise
5341     *
5342     * @see ActionMode
5343     */
5344    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5345        ViewParent parent = getParent();
5346        if (parent == null) return null;
5347        try {
5348            return parent.startActionModeForChild(this, callback, type);
5349        } catch (AbstractMethodError ame) {
5350            // Older implementations of custom views might not implement this.
5351            return parent.startActionModeForChild(this, callback);
5352        }
5353    }
5354
5355    /**
5356     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5357     * Context, creating a unique View identifier to retrieve the result.
5358     *
5359     * @param intent The Intent to be started.
5360     * @param requestCode The request code to use.
5361     * @hide
5362     */
5363    public void startActivityForResult(Intent intent, int requestCode) {
5364        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5365        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5366    }
5367
5368    /**
5369     * If this View corresponds to the calling who, dispatches the activity result.
5370     * @param who The identifier for the targeted View to receive the result.
5371     * @param requestCode The integer request code originally supplied to
5372     *                    startActivityForResult(), allowing you to identify who this
5373     *                    result came from.
5374     * @param resultCode The integer result code returned by the child activity
5375     *                   through its setResult().
5376     * @param data An Intent, which can return result data to the caller
5377     *               (various data can be attached to Intent "extras").
5378     * @return {@code true} if the activity result was dispatched.
5379     * @hide
5380     */
5381    public boolean dispatchActivityResult(
5382            String who, int requestCode, int resultCode, Intent data) {
5383        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5384            onActivityResult(requestCode, resultCode, data);
5385            mStartActivityRequestWho = null;
5386            return true;
5387        }
5388        return false;
5389    }
5390
5391    /**
5392     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5393     *
5394     * @param requestCode The integer request code originally supplied to
5395     *                    startActivityForResult(), allowing you to identify who this
5396     *                    result came from.
5397     * @param resultCode The integer result code returned by the child activity
5398     *                   through its setResult().
5399     * @param data An Intent, which can return result data to the caller
5400     *               (various data can be attached to Intent "extras").
5401     * @hide
5402     */
5403    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5404        // Do nothing.
5405    }
5406
5407    /**
5408     * Register a callback to be invoked when a hardware key is pressed in this view.
5409     * Key presses in software input methods will generally not trigger the methods of
5410     * this listener.
5411     * @param l the key listener to attach to this view
5412     */
5413    public void setOnKeyListener(OnKeyListener l) {
5414        getListenerInfo().mOnKeyListener = l;
5415    }
5416
5417    /**
5418     * Register a callback to be invoked when a touch event is sent to this view.
5419     * @param l the touch listener to attach to this view
5420     */
5421    public void setOnTouchListener(OnTouchListener l) {
5422        getListenerInfo().mOnTouchListener = l;
5423    }
5424
5425    /**
5426     * Register a callback to be invoked when a generic motion event is sent to this view.
5427     * @param l the generic motion listener to attach to this view
5428     */
5429    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5430        getListenerInfo().mOnGenericMotionListener = l;
5431    }
5432
5433    /**
5434     * Register a callback to be invoked when a hover event is sent to this view.
5435     * @param l the hover listener to attach to this view
5436     */
5437    public void setOnHoverListener(OnHoverListener l) {
5438        getListenerInfo().mOnHoverListener = l;
5439    }
5440
5441    /**
5442     * Register a drag event listener callback object for this View. The parameter is
5443     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5444     * View, the system calls the
5445     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5446     * @param l An implementation of {@link android.view.View.OnDragListener}.
5447     */
5448    public void setOnDragListener(OnDragListener l) {
5449        getListenerInfo().mOnDragListener = l;
5450    }
5451
5452    /**
5453     * Give this view focus. This will cause
5454     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5455     *
5456     * Note: this does not check whether this {@link View} should get focus, it just
5457     * gives it focus no matter what.  It should only be called internally by framework
5458     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5459     *
5460     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5461     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5462     *        focus moved when requestFocus() is called. It may not always
5463     *        apply, in which case use the default View.FOCUS_DOWN.
5464     * @param previouslyFocusedRect The rectangle of the view that had focus
5465     *        prior in this View's coordinate system.
5466     */
5467    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5468        if (DBG) {
5469            System.out.println(this + " requestFocus()");
5470        }
5471
5472        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5473            mPrivateFlags |= PFLAG_FOCUSED;
5474
5475            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5476
5477            if (mParent != null) {
5478                mParent.requestChildFocus(this, this);
5479            }
5480
5481            if (mAttachInfo != null) {
5482                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5483            }
5484
5485            onFocusChanged(true, direction, previouslyFocusedRect);
5486            refreshDrawableState();
5487        }
5488    }
5489
5490    /**
5491     * Populates <code>outRect</code> with the hotspot bounds. By default,
5492     * the hotspot bounds are identical to the screen bounds.
5493     *
5494     * @param outRect rect to populate with hotspot bounds
5495     * @hide Only for internal use by views and widgets.
5496     */
5497    public void getHotspotBounds(Rect outRect) {
5498        final Drawable background = getBackground();
5499        if (background != null) {
5500            background.getHotspotBounds(outRect);
5501        } else {
5502            getBoundsOnScreen(outRect);
5503        }
5504    }
5505
5506    /**
5507     * Request that a rectangle of this view be visible on the screen,
5508     * scrolling if necessary just enough.
5509     *
5510     * <p>A View should call this if it maintains some notion of which part
5511     * of its content is interesting.  For example, a text editing view
5512     * should call this when its cursor moves.
5513     *
5514     * @param rectangle The rectangle.
5515     * @return Whether any parent scrolled.
5516     */
5517    public boolean requestRectangleOnScreen(Rect rectangle) {
5518        return requestRectangleOnScreen(rectangle, false);
5519    }
5520
5521    /**
5522     * Request that a rectangle of this view be visible on the screen,
5523     * scrolling if necessary just enough.
5524     *
5525     * <p>A View should call this if it maintains some notion of which part
5526     * of its content is interesting.  For example, a text editing view
5527     * should call this when its cursor moves.
5528     *
5529     * <p>When <code>immediate</code> is set to true, scrolling will not be
5530     * animated.
5531     *
5532     * @param rectangle The rectangle.
5533     * @param immediate True to forbid animated scrolling, false otherwise
5534     * @return Whether any parent scrolled.
5535     */
5536    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5537        if (mParent == null) {
5538            return false;
5539        }
5540
5541        View child = this;
5542
5543        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5544        position.set(rectangle);
5545
5546        ViewParent parent = mParent;
5547        boolean scrolled = false;
5548        while (parent != null) {
5549            rectangle.set((int) position.left, (int) position.top,
5550                    (int) position.right, (int) position.bottom);
5551
5552            scrolled |= parent.requestChildRectangleOnScreen(child,
5553                    rectangle, immediate);
5554
5555            if (!child.hasIdentityMatrix()) {
5556                child.getMatrix().mapRect(position);
5557            }
5558
5559            position.offset(child.mLeft, child.mTop);
5560
5561            if (!(parent instanceof View)) {
5562                break;
5563            }
5564
5565            View parentView = (View) parent;
5566
5567            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5568
5569            child = parentView;
5570            parent = child.getParent();
5571        }
5572
5573        return scrolled;
5574    }
5575
5576    /**
5577     * Called when this view wants to give up focus. If focus is cleared
5578     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5579     * <p>
5580     * <strong>Note:</strong> When a View clears focus the framework is trying
5581     * to give focus to the first focusable View from the top. Hence, if this
5582     * View is the first from the top that can take focus, then all callbacks
5583     * related to clearing focus will be invoked after which the framework will
5584     * give focus to this view.
5585     * </p>
5586     */
5587    public void clearFocus() {
5588        if (DBG) {
5589            System.out.println(this + " clearFocus()");
5590        }
5591
5592        clearFocusInternal(null, true, true);
5593    }
5594
5595    /**
5596     * Clears focus from the view, optionally propagating the change up through
5597     * the parent hierarchy and requesting that the root view place new focus.
5598     *
5599     * @param propagate whether to propagate the change up through the parent
5600     *            hierarchy
5601     * @param refocus when propagate is true, specifies whether to request the
5602     *            root view place new focus
5603     */
5604    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5605        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5606            mPrivateFlags &= ~PFLAG_FOCUSED;
5607
5608            if (propagate && mParent != null) {
5609                mParent.clearChildFocus(this);
5610            }
5611
5612            onFocusChanged(false, 0, null);
5613            refreshDrawableState();
5614
5615            if (propagate && (!refocus || !rootViewRequestFocus())) {
5616                notifyGlobalFocusCleared(this);
5617            }
5618        }
5619    }
5620
5621    void notifyGlobalFocusCleared(View oldFocus) {
5622        if (oldFocus != null && mAttachInfo != null) {
5623            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5624        }
5625    }
5626
5627    boolean rootViewRequestFocus() {
5628        final View root = getRootView();
5629        return root != null && root.requestFocus();
5630    }
5631
5632    /**
5633     * Called internally by the view system when a new view is getting focus.
5634     * This is what clears the old focus.
5635     * <p>
5636     * <b>NOTE:</b> The parent view's focused child must be updated manually
5637     * after calling this method. Otherwise, the view hierarchy may be left in
5638     * an inconstent state.
5639     */
5640    void unFocus(View focused) {
5641        if (DBG) {
5642            System.out.println(this + " unFocus()");
5643        }
5644
5645        clearFocusInternal(focused, false, false);
5646    }
5647
5648    /**
5649     * Returns true if this view has focus itself, or is the ancestor of the
5650     * view that has focus.
5651     *
5652     * @return True if this view has or contains focus, false otherwise.
5653     */
5654    @ViewDebug.ExportedProperty(category = "focus")
5655    public boolean hasFocus() {
5656        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5657    }
5658
5659    /**
5660     * Returns true if this view is focusable or if it contains a reachable View
5661     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5662     * is a View whose parents do not block descendants focus.
5663     *
5664     * Only {@link #VISIBLE} views are considered focusable.
5665     *
5666     * @return True if the view is focusable or if the view contains a focusable
5667     *         View, false otherwise.
5668     *
5669     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5670     * @see ViewGroup#getTouchscreenBlocksFocus()
5671     */
5672    public boolean hasFocusable() {
5673        if (!isFocusableInTouchMode()) {
5674            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5675                final ViewGroup g = (ViewGroup) p;
5676                if (g.shouldBlockFocusForTouchscreen()) {
5677                    return false;
5678                }
5679            }
5680        }
5681        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5682    }
5683
5684    /**
5685     * Called by the view system when the focus state of this view changes.
5686     * When the focus change event is caused by directional navigation, direction
5687     * and previouslyFocusedRect provide insight into where the focus is coming from.
5688     * When overriding, be sure to call up through to the super class so that
5689     * the standard focus handling will occur.
5690     *
5691     * @param gainFocus True if the View has focus; false otherwise.
5692     * @param direction The direction focus has moved when requestFocus()
5693     *                  is called to give this view focus. Values are
5694     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5695     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5696     *                  It may not always apply, in which case use the default.
5697     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5698     *        system, of the previously focused view.  If applicable, this will be
5699     *        passed in as finer grained information about where the focus is coming
5700     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5701     */
5702    @CallSuper
5703    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5704            @Nullable Rect previouslyFocusedRect) {
5705        if (gainFocus) {
5706            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5707        } else {
5708            notifyViewAccessibilityStateChangedIfNeeded(
5709                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5710        }
5711
5712        InputMethodManager imm = InputMethodManager.peekInstance();
5713        if (!gainFocus) {
5714            if (isPressed()) {
5715                setPressed(false);
5716            }
5717            if (imm != null && mAttachInfo != null
5718                    && mAttachInfo.mHasWindowFocus) {
5719                imm.focusOut(this);
5720            }
5721            onFocusLost();
5722        } else if (imm != null && mAttachInfo != null
5723                && mAttachInfo.mHasWindowFocus) {
5724            imm.focusIn(this);
5725        }
5726
5727        invalidate(true);
5728        ListenerInfo li = mListenerInfo;
5729        if (li != null && li.mOnFocusChangeListener != null) {
5730            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5731        }
5732
5733        if (mAttachInfo != null) {
5734            mAttachInfo.mKeyDispatchState.reset(this);
5735        }
5736    }
5737
5738    /**
5739     * Sends an accessibility event of the given type. If accessibility is
5740     * not enabled this method has no effect. The default implementation calls
5741     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5742     * to populate information about the event source (this View), then calls
5743     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5744     * populate the text content of the event source including its descendants,
5745     * and last calls
5746     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5747     * on its parent to request sending of the event to interested parties.
5748     * <p>
5749     * If an {@link AccessibilityDelegate} has been specified via calling
5750     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5751     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5752     * responsible for handling this call.
5753     * </p>
5754     *
5755     * @param eventType The type of the event to send, as defined by several types from
5756     * {@link android.view.accessibility.AccessibilityEvent}, such as
5757     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5758     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5759     *
5760     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5761     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5762     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5763     * @see AccessibilityDelegate
5764     */
5765    public void sendAccessibilityEvent(int eventType) {
5766        if (mAccessibilityDelegate != null) {
5767            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5768        } else {
5769            sendAccessibilityEventInternal(eventType);
5770        }
5771    }
5772
5773    /**
5774     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5775     * {@link AccessibilityEvent} to make an announcement which is related to some
5776     * sort of a context change for which none of the events representing UI transitions
5777     * is a good fit. For example, announcing a new page in a book. If accessibility
5778     * is not enabled this method does nothing.
5779     *
5780     * @param text The announcement text.
5781     */
5782    public void announceForAccessibility(CharSequence text) {
5783        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5784            AccessibilityEvent event = AccessibilityEvent.obtain(
5785                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5786            onInitializeAccessibilityEvent(event);
5787            event.getText().add(text);
5788            event.setContentDescription(null);
5789            mParent.requestSendAccessibilityEvent(this, event);
5790        }
5791    }
5792
5793    /**
5794     * @see #sendAccessibilityEvent(int)
5795     *
5796     * Note: Called from the default {@link AccessibilityDelegate}.
5797     *
5798     * @hide
5799     */
5800    public void sendAccessibilityEventInternal(int eventType) {
5801        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5802            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5803        }
5804    }
5805
5806    /**
5807     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5808     * takes as an argument an empty {@link AccessibilityEvent} and does not
5809     * perform a check whether accessibility is enabled.
5810     * <p>
5811     * If an {@link AccessibilityDelegate} has been specified via calling
5812     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5813     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5814     * is responsible for handling this call.
5815     * </p>
5816     *
5817     * @param event The event to send.
5818     *
5819     * @see #sendAccessibilityEvent(int)
5820     */
5821    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5822        if (mAccessibilityDelegate != null) {
5823            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5824        } else {
5825            sendAccessibilityEventUncheckedInternal(event);
5826        }
5827    }
5828
5829    /**
5830     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5831     *
5832     * Note: Called from the default {@link AccessibilityDelegate}.
5833     *
5834     * @hide
5835     */
5836    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5837        if (!isShown()) {
5838            return;
5839        }
5840        onInitializeAccessibilityEvent(event);
5841        // Only a subset of accessibility events populates text content.
5842        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5843            dispatchPopulateAccessibilityEvent(event);
5844        }
5845        // In the beginning we called #isShown(), so we know that getParent() is not null.
5846        getParent().requestSendAccessibilityEvent(this, event);
5847    }
5848
5849    /**
5850     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5851     * to its children for adding their text content to the event. Note that the
5852     * event text is populated in a separate dispatch path since we add to the
5853     * event not only the text of the source but also the text of all its descendants.
5854     * A typical implementation will call
5855     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5856     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5857     * on each child. Override this method if custom population of the event text
5858     * content is required.
5859     * <p>
5860     * If an {@link AccessibilityDelegate} has been specified via calling
5861     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5862     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5863     * is responsible for handling this call.
5864     * </p>
5865     * <p>
5866     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5867     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5868     * </p>
5869     *
5870     * @param event The event.
5871     *
5872     * @return True if the event population was completed.
5873     */
5874    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5875        if (mAccessibilityDelegate != null) {
5876            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5877        } else {
5878            return dispatchPopulateAccessibilityEventInternal(event);
5879        }
5880    }
5881
5882    /**
5883     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5884     *
5885     * Note: Called from the default {@link AccessibilityDelegate}.
5886     *
5887     * @hide
5888     */
5889    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5890        onPopulateAccessibilityEvent(event);
5891        return false;
5892    }
5893
5894    /**
5895     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5896     * giving a chance to this View to populate the accessibility event with its
5897     * text content. While this method is free to modify event
5898     * attributes other than text content, doing so should normally be performed in
5899     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5900     * <p>
5901     * Example: Adding formatted date string to an accessibility event in addition
5902     *          to the text added by the super implementation:
5903     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5904     *     super.onPopulateAccessibilityEvent(event);
5905     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5906     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5907     *         mCurrentDate.getTimeInMillis(), flags);
5908     *     event.getText().add(selectedDateUtterance);
5909     * }</pre>
5910     * <p>
5911     * If an {@link AccessibilityDelegate} has been specified via calling
5912     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5913     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5914     * is responsible for handling this call.
5915     * </p>
5916     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5917     * information to the event, in case the default implementation has basic information to add.
5918     * </p>
5919     *
5920     * @param event The accessibility event which to populate.
5921     *
5922     * @see #sendAccessibilityEvent(int)
5923     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5924     */
5925    @CallSuper
5926    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5927        if (mAccessibilityDelegate != null) {
5928            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5929        } else {
5930            onPopulateAccessibilityEventInternal(event);
5931        }
5932    }
5933
5934    /**
5935     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5936     *
5937     * Note: Called from the default {@link AccessibilityDelegate}.
5938     *
5939     * @hide
5940     */
5941    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5942    }
5943
5944    /**
5945     * Initializes an {@link AccessibilityEvent} with information about
5946     * this View which is the event source. In other words, the source of
5947     * an accessibility event is the view whose state change triggered firing
5948     * the event.
5949     * <p>
5950     * Example: Setting the password property of an event in addition
5951     *          to properties set by the super implementation:
5952     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5953     *     super.onInitializeAccessibilityEvent(event);
5954     *     event.setPassword(true);
5955     * }</pre>
5956     * <p>
5957     * If an {@link AccessibilityDelegate} has been specified via calling
5958     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5959     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5960     * is responsible for handling this call.
5961     * </p>
5962     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5963     * information to the event, in case the default implementation has basic information to add.
5964     * </p>
5965     * @param event The event to initialize.
5966     *
5967     * @see #sendAccessibilityEvent(int)
5968     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5969     */
5970    @CallSuper
5971    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5972        if (mAccessibilityDelegate != null) {
5973            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5974        } else {
5975            onInitializeAccessibilityEventInternal(event);
5976        }
5977    }
5978
5979    /**
5980     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5981     *
5982     * Note: Called from the default {@link AccessibilityDelegate}.
5983     *
5984     * @hide
5985     */
5986    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5987        event.setSource(this);
5988        event.setClassName(getAccessibilityClassName());
5989        event.setPackageName(getContext().getPackageName());
5990        event.setEnabled(isEnabled());
5991        event.setContentDescription(mContentDescription);
5992
5993        switch (event.getEventType()) {
5994            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5995                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5996                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5997                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5998                event.setItemCount(focusablesTempList.size());
5999                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6000                if (mAttachInfo != null) {
6001                    focusablesTempList.clear();
6002                }
6003            } break;
6004            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6005                CharSequence text = getIterableTextForAccessibility();
6006                if (text != null && text.length() > 0) {
6007                    event.setFromIndex(getAccessibilitySelectionStart());
6008                    event.setToIndex(getAccessibilitySelectionEnd());
6009                    event.setItemCount(text.length());
6010                }
6011            } break;
6012        }
6013    }
6014
6015    /**
6016     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6017     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6018     * This method is responsible for obtaining an accessibility node info from a
6019     * pool of reusable instances and calling
6020     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6021     * initialize the former.
6022     * <p>
6023     * Note: The client is responsible for recycling the obtained instance by calling
6024     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6025     * </p>
6026     *
6027     * @return A populated {@link AccessibilityNodeInfo}.
6028     *
6029     * @see AccessibilityNodeInfo
6030     */
6031    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6032        if (mAccessibilityDelegate != null) {
6033            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6034        } else {
6035            return createAccessibilityNodeInfoInternal();
6036        }
6037    }
6038
6039    /**
6040     * @see #createAccessibilityNodeInfo()
6041     *
6042     * @hide
6043     */
6044    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6045        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6046        if (provider != null) {
6047            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6048        } else {
6049            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6050            onInitializeAccessibilityNodeInfo(info);
6051            return info;
6052        }
6053    }
6054
6055    /**
6056     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6057     * The base implementation sets:
6058     * <ul>
6059     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6060     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6061     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6062     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6063     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6064     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6065     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6066     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6067     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6068     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6069     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6070     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6071     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6072     * </ul>
6073     * <p>
6074     * Subclasses should override this method, call the super implementation,
6075     * and set additional attributes.
6076     * </p>
6077     * <p>
6078     * If an {@link AccessibilityDelegate} has been specified via calling
6079     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6080     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6081     * is responsible for handling this call.
6082     * </p>
6083     *
6084     * @param info The instance to initialize.
6085     */
6086    @CallSuper
6087    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6088        if (mAccessibilityDelegate != null) {
6089            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6090        } else {
6091            onInitializeAccessibilityNodeInfoInternal(info);
6092        }
6093    }
6094
6095    /**
6096     * Gets the location of this view in screen coordinates.
6097     *
6098     * @param outRect The output location
6099     * @hide
6100     */
6101    public void getBoundsOnScreen(Rect outRect) {
6102        getBoundsOnScreen(outRect, false);
6103    }
6104
6105    /**
6106     * Gets the location of this view in screen coordinates.
6107     *
6108     * @param outRect The output location
6109     * @param clipToParent Whether to clip child bounds to the parent ones.
6110     * @hide
6111     */
6112    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6113        if (mAttachInfo == null) {
6114            return;
6115        }
6116
6117        RectF position = mAttachInfo.mTmpTransformRect;
6118        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6119
6120        if (!hasIdentityMatrix()) {
6121            getMatrix().mapRect(position);
6122        }
6123
6124        position.offset(mLeft, mTop);
6125
6126        ViewParent parent = mParent;
6127        while (parent instanceof View) {
6128            View parentView = (View) parent;
6129
6130            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6131
6132            if (clipToParent) {
6133                position.left = Math.max(position.left, 0);
6134                position.top = Math.max(position.top, 0);
6135                position.right = Math.min(position.right, parentView.getWidth());
6136                position.bottom = Math.min(position.bottom, parentView.getHeight());
6137            }
6138
6139            if (!parentView.hasIdentityMatrix()) {
6140                parentView.getMatrix().mapRect(position);
6141            }
6142
6143            position.offset(parentView.mLeft, parentView.mTop);
6144
6145            parent = parentView.mParent;
6146        }
6147
6148        if (parent instanceof ViewRootImpl) {
6149            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6150            position.offset(0, -viewRootImpl.mCurScrollY);
6151        }
6152
6153        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6154
6155        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6156                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6157    }
6158
6159    /**
6160     * Return the class name of this object to be used for accessibility purposes.
6161     * Subclasses should only override this if they are implementing something that
6162     * should be seen as a completely new class of view when used by accessibility,
6163     * unrelated to the class it is deriving from.  This is used to fill in
6164     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6165     */
6166    public CharSequence getAccessibilityClassName() {
6167        return View.class.getName();
6168    }
6169
6170    /**
6171     * Called when assist structure is being retrieved from a view as part of
6172     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6173     * @param structure Fill in with structured view data.  The default implementation
6174     * fills in all data that can be inferred from the view itself.
6175     */
6176    public void onProvideStructure(ViewStructure structure) {
6177        final int id = mID;
6178        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6179                && (id&0x0000ffff) != 0) {
6180            String pkg, type, entry;
6181            try {
6182                final Resources res = getResources();
6183                entry = res.getResourceEntryName(id);
6184                type = res.getResourceTypeName(id);
6185                pkg = res.getResourcePackageName(id);
6186            } catch (Resources.NotFoundException e) {
6187                entry = type = pkg = null;
6188            }
6189            structure.setId(id, pkg, type, entry);
6190        } else {
6191            structure.setId(id, null, null, null);
6192        }
6193        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6194        if (!hasIdentityMatrix()) {
6195            structure.setTransformation(getMatrix());
6196        }
6197        structure.setElevation(getZ());
6198        structure.setVisibility(getVisibility());
6199        structure.setEnabled(isEnabled());
6200        if (isClickable()) {
6201            structure.setClickable(true);
6202        }
6203        if (isFocusable()) {
6204            structure.setFocusable(true);
6205        }
6206        if (isFocused()) {
6207            structure.setFocused(true);
6208        }
6209        if (isAccessibilityFocused()) {
6210            structure.setAccessibilityFocused(true);
6211        }
6212        if (isSelected()) {
6213            structure.setSelected(true);
6214        }
6215        if (isActivated()) {
6216            structure.setActivated(true);
6217        }
6218        if (isLongClickable()) {
6219            structure.setLongClickable(true);
6220        }
6221        if (this instanceof Checkable) {
6222            structure.setCheckable(true);
6223            if (((Checkable)this).isChecked()) {
6224                structure.setChecked(true);
6225            }
6226        }
6227        if (isContextClickable()) {
6228            structure.setContextClickable(true);
6229        }
6230        structure.setClassName(getAccessibilityClassName().toString());
6231        structure.setContentDescription(getContentDescription());
6232    }
6233
6234    /**
6235     * Called when assist structure is being retrieved from a view as part of
6236     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6237     * generate additional virtual structure under this view.  The defaullt implementation
6238     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6239     * view's virtual accessibility nodes, if any.  You can override this for a more
6240     * optimal implementation providing this data.
6241     */
6242    public void onProvideVirtualStructure(ViewStructure structure) {
6243        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6244        if (provider != null) {
6245            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6246            structure.setChildCount(1);
6247            ViewStructure root = structure.newChild(0);
6248            populateVirtualStructure(root, provider, info);
6249            info.recycle();
6250        }
6251    }
6252
6253    private void populateVirtualStructure(ViewStructure structure,
6254            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6255        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6256                null, null, null);
6257        Rect rect = structure.getTempRect();
6258        info.getBoundsInParent(rect);
6259        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6260        structure.setVisibility(VISIBLE);
6261        structure.setEnabled(info.isEnabled());
6262        if (info.isClickable()) {
6263            structure.setClickable(true);
6264        }
6265        if (info.isFocusable()) {
6266            structure.setFocusable(true);
6267        }
6268        if (info.isFocused()) {
6269            structure.setFocused(true);
6270        }
6271        if (info.isAccessibilityFocused()) {
6272            structure.setAccessibilityFocused(true);
6273        }
6274        if (info.isSelected()) {
6275            structure.setSelected(true);
6276        }
6277        if (info.isLongClickable()) {
6278            structure.setLongClickable(true);
6279        }
6280        if (info.isCheckable()) {
6281            structure.setCheckable(true);
6282            if (info.isChecked()) {
6283                structure.setChecked(true);
6284            }
6285        }
6286        if (info.isContextClickable()) {
6287            structure.setContextClickable(true);
6288        }
6289        CharSequence cname = info.getClassName();
6290        structure.setClassName(cname != null ? cname.toString() : null);
6291        structure.setContentDescription(info.getContentDescription());
6292        if (info.getText() != null || info.getError() != null) {
6293            structure.setText(info.getText(), info.getTextSelectionStart(),
6294                    info.getTextSelectionEnd());
6295        }
6296        final int NCHILDREN = info.getChildCount();
6297        if (NCHILDREN > 0) {
6298            structure.setChildCount(NCHILDREN);
6299            for (int i=0; i<NCHILDREN; i++) {
6300                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6301                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6302                ViewStructure child = structure.newChild(i);
6303                populateVirtualStructure(child, provider, cinfo);
6304                cinfo.recycle();
6305            }
6306        }
6307    }
6308
6309    /**
6310     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6311     * implementation calls {@link #onProvideStructure} and
6312     * {@link #onProvideVirtualStructure}.
6313     */
6314    public void dispatchProvideStructure(ViewStructure structure) {
6315        if (!isAssistBlocked()) {
6316            onProvideStructure(structure);
6317            onProvideVirtualStructure(structure);
6318        } else {
6319            structure.setClassName(getAccessibilityClassName().toString());
6320            structure.setAssistBlocked(true);
6321        }
6322    }
6323
6324    /**
6325     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6326     *
6327     * Note: Called from the default {@link AccessibilityDelegate}.
6328     *
6329     * @hide
6330     */
6331    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6332        if (mAttachInfo == null) {
6333            return;
6334        }
6335
6336        Rect bounds = mAttachInfo.mTmpInvalRect;
6337
6338        getDrawingRect(bounds);
6339        info.setBoundsInParent(bounds);
6340
6341        getBoundsOnScreen(bounds, true);
6342        info.setBoundsInScreen(bounds);
6343
6344        ViewParent parent = getParentForAccessibility();
6345        if (parent instanceof View) {
6346            info.setParent((View) parent);
6347        }
6348
6349        if (mID != View.NO_ID) {
6350            View rootView = getRootView();
6351            if (rootView == null) {
6352                rootView = this;
6353            }
6354
6355            View label = rootView.findLabelForView(this, mID);
6356            if (label != null) {
6357                info.setLabeledBy(label);
6358            }
6359
6360            if ((mAttachInfo.mAccessibilityFetchFlags
6361                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6362                    && Resources.resourceHasPackage(mID)) {
6363                try {
6364                    String viewId = getResources().getResourceName(mID);
6365                    info.setViewIdResourceName(viewId);
6366                } catch (Resources.NotFoundException nfe) {
6367                    /* ignore */
6368                }
6369            }
6370        }
6371
6372        if (mLabelForId != View.NO_ID) {
6373            View rootView = getRootView();
6374            if (rootView == null) {
6375                rootView = this;
6376            }
6377            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6378            if (labeled != null) {
6379                info.setLabelFor(labeled);
6380            }
6381        }
6382
6383        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6384            View rootView = getRootView();
6385            if (rootView == null) {
6386                rootView = this;
6387            }
6388            View next = rootView.findViewInsideOutShouldExist(this,
6389                    mAccessibilityTraversalBeforeId);
6390            if (next != null && next.includeForAccessibility()) {
6391                info.setTraversalBefore(next);
6392            }
6393        }
6394
6395        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6396            View rootView = getRootView();
6397            if (rootView == null) {
6398                rootView = this;
6399            }
6400            View next = rootView.findViewInsideOutShouldExist(this,
6401                    mAccessibilityTraversalAfterId);
6402            if (next != null && next.includeForAccessibility()) {
6403                info.setTraversalAfter(next);
6404            }
6405        }
6406
6407        info.setVisibleToUser(isVisibleToUser());
6408
6409        info.setPackageName(mContext.getPackageName());
6410        info.setClassName(getAccessibilityClassName());
6411        info.setContentDescription(getContentDescription());
6412
6413        info.setEnabled(isEnabled());
6414        info.setClickable(isClickable());
6415        info.setFocusable(isFocusable());
6416        info.setFocused(isFocused());
6417        info.setAccessibilityFocused(isAccessibilityFocused());
6418        info.setSelected(isSelected());
6419        info.setLongClickable(isLongClickable());
6420        info.setContextClickable(isContextClickable());
6421        info.setLiveRegion(getAccessibilityLiveRegion());
6422
6423        // TODO: These make sense only if we are in an AdapterView but all
6424        // views can be selected. Maybe from accessibility perspective
6425        // we should report as selectable view in an AdapterView.
6426        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6427        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6428
6429        if (isFocusable()) {
6430            if (isFocused()) {
6431                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6432            } else {
6433                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6434            }
6435        }
6436
6437        if (!isAccessibilityFocused()) {
6438            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6439        } else {
6440            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6441        }
6442
6443        if (isClickable() && isEnabled()) {
6444            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6445        }
6446
6447        if (isLongClickable() && isEnabled()) {
6448            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6449        }
6450
6451        if (isContextClickable() && isEnabled()) {
6452            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6453        }
6454
6455        CharSequence text = getIterableTextForAccessibility();
6456        if (text != null && text.length() > 0) {
6457            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6458
6459            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6460            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6461            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6462            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6463                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6464                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6465        }
6466
6467        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6468    }
6469
6470    private View findLabelForView(View view, int labeledId) {
6471        if (mMatchLabelForPredicate == null) {
6472            mMatchLabelForPredicate = new MatchLabelForPredicate();
6473        }
6474        mMatchLabelForPredicate.mLabeledId = labeledId;
6475        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6476    }
6477
6478    /**
6479     * Computes whether this view is visible to the user. Such a view is
6480     * attached, visible, all its predecessors are visible, it is not clipped
6481     * entirely by its predecessors, and has an alpha greater than zero.
6482     *
6483     * @return Whether the view is visible on the screen.
6484     *
6485     * @hide
6486     */
6487    protected boolean isVisibleToUser() {
6488        return isVisibleToUser(null);
6489    }
6490
6491    /**
6492     * Computes whether the given portion of this view is visible to the user.
6493     * Such a view is attached, visible, all its predecessors are visible,
6494     * has an alpha greater than zero, and the specified portion is not
6495     * clipped entirely by its predecessors.
6496     *
6497     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6498     *                    <code>null</code>, and the entire view will be tested in this case.
6499     *                    When <code>true</code> is returned by the function, the actual visible
6500     *                    region will be stored in this parameter; that is, if boundInView is fully
6501     *                    contained within the view, no modification will be made, otherwise regions
6502     *                    outside of the visible area of the view will be clipped.
6503     *
6504     * @return Whether the specified portion of the view is visible on the screen.
6505     *
6506     * @hide
6507     */
6508    protected boolean isVisibleToUser(Rect boundInView) {
6509        if (mAttachInfo != null) {
6510            // Attached to invisible window means this view is not visible.
6511            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6512                return false;
6513            }
6514            // An invisible predecessor or one with alpha zero means
6515            // that this view is not visible to the user.
6516            Object current = this;
6517            while (current instanceof View) {
6518                View view = (View) current;
6519                // We have attach info so this view is attached and there is no
6520                // need to check whether we reach to ViewRootImpl on the way up.
6521                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6522                        view.getVisibility() != VISIBLE) {
6523                    return false;
6524                }
6525                current = view.mParent;
6526            }
6527            // Check if the view is entirely covered by its predecessors.
6528            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6529            Point offset = mAttachInfo.mPoint;
6530            if (!getGlobalVisibleRect(visibleRect, offset)) {
6531                return false;
6532            }
6533            // Check if the visible portion intersects the rectangle of interest.
6534            if (boundInView != null) {
6535                visibleRect.offset(-offset.x, -offset.y);
6536                return boundInView.intersect(visibleRect);
6537            }
6538            return true;
6539        }
6540        return false;
6541    }
6542
6543    /**
6544     * Returns the delegate for implementing accessibility support via
6545     * composition. For more details see {@link AccessibilityDelegate}.
6546     *
6547     * @return The delegate, or null if none set.
6548     *
6549     * @hide
6550     */
6551    public AccessibilityDelegate getAccessibilityDelegate() {
6552        return mAccessibilityDelegate;
6553    }
6554
6555    /**
6556     * Sets a delegate for implementing accessibility support via composition as
6557     * opposed to inheritance. The delegate's primary use is for implementing
6558     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6559     *
6560     * @param delegate The delegate instance.
6561     *
6562     * @see AccessibilityDelegate
6563     */
6564    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6565        mAccessibilityDelegate = delegate;
6566    }
6567
6568    /**
6569     * Gets the provider for managing a virtual view hierarchy rooted at this View
6570     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6571     * that explore the window content.
6572     * <p>
6573     * If this method returns an instance, this instance is responsible for managing
6574     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6575     * View including the one representing the View itself. Similarly the returned
6576     * instance is responsible for performing accessibility actions on any virtual
6577     * view or the root view itself.
6578     * </p>
6579     * <p>
6580     * If an {@link AccessibilityDelegate} has been specified via calling
6581     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6582     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6583     * is responsible for handling this call.
6584     * </p>
6585     *
6586     * @return The provider.
6587     *
6588     * @see AccessibilityNodeProvider
6589     */
6590    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6591        if (mAccessibilityDelegate != null) {
6592            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6593        } else {
6594            return null;
6595        }
6596    }
6597
6598    /**
6599     * Gets the unique identifier of this view on the screen for accessibility purposes.
6600     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6601     *
6602     * @return The view accessibility id.
6603     *
6604     * @hide
6605     */
6606    public int getAccessibilityViewId() {
6607        if (mAccessibilityViewId == NO_ID) {
6608            mAccessibilityViewId = sNextAccessibilityViewId++;
6609        }
6610        return mAccessibilityViewId;
6611    }
6612
6613    /**
6614     * Gets the unique identifier of the window in which this View reseides.
6615     *
6616     * @return The window accessibility id.
6617     *
6618     * @hide
6619     */
6620    public int getAccessibilityWindowId() {
6621        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6622                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6623    }
6624
6625    /**
6626     * Gets the {@link View} description. It briefly describes the view and is
6627     * primarily used for accessibility support. Set this property to enable
6628     * better accessibility support for your application. This is especially
6629     * true for views that do not have textual representation (For example,
6630     * ImageButton).
6631     *
6632     * @return The content description.
6633     *
6634     * @attr ref android.R.styleable#View_contentDescription
6635     */
6636    @ViewDebug.ExportedProperty(category = "accessibility")
6637    public CharSequence getContentDescription() {
6638        return mContentDescription;
6639    }
6640
6641    /**
6642     * Sets the {@link View} description. It briefly describes the view and is
6643     * primarily used for accessibility support. Set this property to enable
6644     * better accessibility support for your application. This is especially
6645     * true for views that do not have textual representation (For example,
6646     * ImageButton).
6647     *
6648     * @param contentDescription The content description.
6649     *
6650     * @attr ref android.R.styleable#View_contentDescription
6651     */
6652    @RemotableViewMethod
6653    public void setContentDescription(CharSequence contentDescription) {
6654        if (mContentDescription == null) {
6655            if (contentDescription == null) {
6656                return;
6657            }
6658        } else if (mContentDescription.equals(contentDescription)) {
6659            return;
6660        }
6661        mContentDescription = contentDescription;
6662        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6663        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6664            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6665            notifySubtreeAccessibilityStateChangedIfNeeded();
6666        } else {
6667            notifyViewAccessibilityStateChangedIfNeeded(
6668                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6669        }
6670    }
6671
6672    /**
6673     * Sets the id of a view before which this one is visited in accessibility traversal.
6674     * A screen-reader must visit the content of this view before the content of the one
6675     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6676     * will traverse the entire content of B before traversing the entire content of A,
6677     * regardles of what traversal strategy it is using.
6678     * <p>
6679     * Views that do not have specified before/after relationships are traversed in order
6680     * determined by the screen-reader.
6681     * </p>
6682     * <p>
6683     * Setting that this view is before a view that is not important for accessibility
6684     * or if this view is not important for accessibility will have no effect as the
6685     * screen-reader is not aware of unimportant views.
6686     * </p>
6687     *
6688     * @param beforeId The id of a view this one precedes in accessibility traversal.
6689     *
6690     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6691     *
6692     * @see #setImportantForAccessibility(int)
6693     */
6694    @RemotableViewMethod
6695    public void setAccessibilityTraversalBefore(int beforeId) {
6696        if (mAccessibilityTraversalBeforeId == beforeId) {
6697            return;
6698        }
6699        mAccessibilityTraversalBeforeId = beforeId;
6700        notifyViewAccessibilityStateChangedIfNeeded(
6701                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6702    }
6703
6704    /**
6705     * Gets the id of a view before which this one is visited in accessibility traversal.
6706     *
6707     * @return The id of a view this one precedes in accessibility traversal if
6708     *         specified, otherwise {@link #NO_ID}.
6709     *
6710     * @see #setAccessibilityTraversalBefore(int)
6711     */
6712    public int getAccessibilityTraversalBefore() {
6713        return mAccessibilityTraversalBeforeId;
6714    }
6715
6716    /**
6717     * Sets the id of a view after which this one is visited in accessibility traversal.
6718     * A screen-reader must visit the content of the other view before the content of this
6719     * one. For example, if view B is set to be after view A, then a screen-reader
6720     * will traverse the entire content of A before traversing the entire content of B,
6721     * regardles of what traversal strategy it is using.
6722     * <p>
6723     * Views that do not have specified before/after relationships are traversed in order
6724     * determined by the screen-reader.
6725     * </p>
6726     * <p>
6727     * Setting that this view is after a view that is not important for accessibility
6728     * or if this view is not important for accessibility will have no effect as the
6729     * screen-reader is not aware of unimportant views.
6730     * </p>
6731     *
6732     * @param afterId The id of a view this one succedees in accessibility traversal.
6733     *
6734     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6735     *
6736     * @see #setImportantForAccessibility(int)
6737     */
6738    @RemotableViewMethod
6739    public void setAccessibilityTraversalAfter(int afterId) {
6740        if (mAccessibilityTraversalAfterId == afterId) {
6741            return;
6742        }
6743        mAccessibilityTraversalAfterId = afterId;
6744        notifyViewAccessibilityStateChangedIfNeeded(
6745                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6746    }
6747
6748    /**
6749     * Gets the id of a view after which this one is visited in accessibility traversal.
6750     *
6751     * @return The id of a view this one succeedes in accessibility traversal if
6752     *         specified, otherwise {@link #NO_ID}.
6753     *
6754     * @see #setAccessibilityTraversalAfter(int)
6755     */
6756    public int getAccessibilityTraversalAfter() {
6757        return mAccessibilityTraversalAfterId;
6758    }
6759
6760    /**
6761     * Gets the id of a view for which this view serves as a label for
6762     * accessibility purposes.
6763     *
6764     * @return The labeled view id.
6765     */
6766    @ViewDebug.ExportedProperty(category = "accessibility")
6767    public int getLabelFor() {
6768        return mLabelForId;
6769    }
6770
6771    /**
6772     * Sets the id of a view for which this view serves as a label for
6773     * accessibility purposes.
6774     *
6775     * @param id The labeled view id.
6776     */
6777    @RemotableViewMethod
6778    public void setLabelFor(@IdRes int id) {
6779        if (mLabelForId == id) {
6780            return;
6781        }
6782        mLabelForId = id;
6783        if (mLabelForId != View.NO_ID
6784                && mID == View.NO_ID) {
6785            mID = generateViewId();
6786        }
6787        notifyViewAccessibilityStateChangedIfNeeded(
6788                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6789    }
6790
6791    /**
6792     * Invoked whenever this view loses focus, either by losing window focus or by losing
6793     * focus within its window. This method can be used to clear any state tied to the
6794     * focus. For instance, if a button is held pressed with the trackball and the window
6795     * loses focus, this method can be used to cancel the press.
6796     *
6797     * Subclasses of View overriding this method should always call super.onFocusLost().
6798     *
6799     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6800     * @see #onWindowFocusChanged(boolean)
6801     *
6802     * @hide pending API council approval
6803     */
6804    @CallSuper
6805    protected void onFocusLost() {
6806        resetPressedState();
6807    }
6808
6809    private void resetPressedState() {
6810        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6811            return;
6812        }
6813
6814        if (isPressed()) {
6815            setPressed(false);
6816
6817            if (!mHasPerformedLongPress) {
6818                removeLongPressCallback();
6819            }
6820        }
6821    }
6822
6823    /**
6824     * Returns true if this view has focus
6825     *
6826     * @return True if this view has focus, false otherwise.
6827     */
6828    @ViewDebug.ExportedProperty(category = "focus")
6829    public boolean isFocused() {
6830        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6831    }
6832
6833    /**
6834     * Find the view in the hierarchy rooted at this view that currently has
6835     * focus.
6836     *
6837     * @return The view that currently has focus, or null if no focused view can
6838     *         be found.
6839     */
6840    public View findFocus() {
6841        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6842    }
6843
6844    /**
6845     * Indicates whether this view is one of the set of scrollable containers in
6846     * its window.
6847     *
6848     * @return whether this view is one of the set of scrollable containers in
6849     * its window
6850     *
6851     * @attr ref android.R.styleable#View_isScrollContainer
6852     */
6853    public boolean isScrollContainer() {
6854        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6855    }
6856
6857    /**
6858     * Change whether this view is one of the set of scrollable containers in
6859     * its window.  This will be used to determine whether the window can
6860     * resize or must pan when a soft input area is open -- scrollable
6861     * containers allow the window to use resize mode since the container
6862     * will appropriately shrink.
6863     *
6864     * @attr ref android.R.styleable#View_isScrollContainer
6865     */
6866    public void setScrollContainer(boolean isScrollContainer) {
6867        if (isScrollContainer) {
6868            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6869                mAttachInfo.mScrollContainers.add(this);
6870                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6871            }
6872            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6873        } else {
6874            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6875                mAttachInfo.mScrollContainers.remove(this);
6876            }
6877            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6878        }
6879    }
6880
6881    /**
6882     * Returns the quality of the drawing cache.
6883     *
6884     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6885     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6886     *
6887     * @see #setDrawingCacheQuality(int)
6888     * @see #setDrawingCacheEnabled(boolean)
6889     * @see #isDrawingCacheEnabled()
6890     *
6891     * @attr ref android.R.styleable#View_drawingCacheQuality
6892     */
6893    @DrawingCacheQuality
6894    public int getDrawingCacheQuality() {
6895        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6896    }
6897
6898    /**
6899     * Set the drawing cache quality of this view. This value is used only when the
6900     * drawing cache is enabled
6901     *
6902     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6903     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6904     *
6905     * @see #getDrawingCacheQuality()
6906     * @see #setDrawingCacheEnabled(boolean)
6907     * @see #isDrawingCacheEnabled()
6908     *
6909     * @attr ref android.R.styleable#View_drawingCacheQuality
6910     */
6911    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6912        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6913    }
6914
6915    /**
6916     * Returns whether the screen should remain on, corresponding to the current
6917     * value of {@link #KEEP_SCREEN_ON}.
6918     *
6919     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6920     *
6921     * @see #setKeepScreenOn(boolean)
6922     *
6923     * @attr ref android.R.styleable#View_keepScreenOn
6924     */
6925    public boolean getKeepScreenOn() {
6926        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6927    }
6928
6929    /**
6930     * Controls whether the screen should remain on, modifying the
6931     * value of {@link #KEEP_SCREEN_ON}.
6932     *
6933     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6934     *
6935     * @see #getKeepScreenOn()
6936     *
6937     * @attr ref android.R.styleable#View_keepScreenOn
6938     */
6939    public void setKeepScreenOn(boolean keepScreenOn) {
6940        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6941    }
6942
6943    /**
6944     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6945     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6946     *
6947     * @attr ref android.R.styleable#View_nextFocusLeft
6948     */
6949    public int getNextFocusLeftId() {
6950        return mNextFocusLeftId;
6951    }
6952
6953    /**
6954     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6955     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6956     * decide automatically.
6957     *
6958     * @attr ref android.R.styleable#View_nextFocusLeft
6959     */
6960    public void setNextFocusLeftId(int nextFocusLeftId) {
6961        mNextFocusLeftId = nextFocusLeftId;
6962    }
6963
6964    /**
6965     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6966     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6967     *
6968     * @attr ref android.R.styleable#View_nextFocusRight
6969     */
6970    public int getNextFocusRightId() {
6971        return mNextFocusRightId;
6972    }
6973
6974    /**
6975     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6976     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6977     * decide automatically.
6978     *
6979     * @attr ref android.R.styleable#View_nextFocusRight
6980     */
6981    public void setNextFocusRightId(int nextFocusRightId) {
6982        mNextFocusRightId = nextFocusRightId;
6983    }
6984
6985    /**
6986     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6987     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6988     *
6989     * @attr ref android.R.styleable#View_nextFocusUp
6990     */
6991    public int getNextFocusUpId() {
6992        return mNextFocusUpId;
6993    }
6994
6995    /**
6996     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6997     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6998     * decide automatically.
6999     *
7000     * @attr ref android.R.styleable#View_nextFocusUp
7001     */
7002    public void setNextFocusUpId(int nextFocusUpId) {
7003        mNextFocusUpId = nextFocusUpId;
7004    }
7005
7006    /**
7007     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7008     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7009     *
7010     * @attr ref android.R.styleable#View_nextFocusDown
7011     */
7012    public int getNextFocusDownId() {
7013        return mNextFocusDownId;
7014    }
7015
7016    /**
7017     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7018     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7019     * decide automatically.
7020     *
7021     * @attr ref android.R.styleable#View_nextFocusDown
7022     */
7023    public void setNextFocusDownId(int nextFocusDownId) {
7024        mNextFocusDownId = nextFocusDownId;
7025    }
7026
7027    /**
7028     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7029     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7030     *
7031     * @attr ref android.R.styleable#View_nextFocusForward
7032     */
7033    public int getNextFocusForwardId() {
7034        return mNextFocusForwardId;
7035    }
7036
7037    /**
7038     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7039     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7040     * decide automatically.
7041     *
7042     * @attr ref android.R.styleable#View_nextFocusForward
7043     */
7044    public void setNextFocusForwardId(int nextFocusForwardId) {
7045        mNextFocusForwardId = nextFocusForwardId;
7046    }
7047
7048    /**
7049     * Returns the visibility of this view and all of its ancestors
7050     *
7051     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7052     */
7053    public boolean isShown() {
7054        View current = this;
7055        //noinspection ConstantConditions
7056        do {
7057            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7058                return false;
7059            }
7060            ViewParent parent = current.mParent;
7061            if (parent == null) {
7062                return false; // We are not attached to the view root
7063            }
7064            if (!(parent instanceof View)) {
7065                return true;
7066            }
7067            current = (View) parent;
7068        } while (current != null);
7069
7070        return false;
7071    }
7072
7073    /**
7074     * Called by the view hierarchy when the content insets for a window have
7075     * changed, to allow it to adjust its content to fit within those windows.
7076     * The content insets tell you the space that the status bar, input method,
7077     * and other system windows infringe on the application's window.
7078     *
7079     * <p>You do not normally need to deal with this function, since the default
7080     * window decoration given to applications takes care of applying it to the
7081     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7082     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7083     * and your content can be placed under those system elements.  You can then
7084     * use this method within your view hierarchy if you have parts of your UI
7085     * which you would like to ensure are not being covered.
7086     *
7087     * <p>The default implementation of this method simply applies the content
7088     * insets to the view's padding, consuming that content (modifying the
7089     * insets to be 0), and returning true.  This behavior is off by default, but can
7090     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7091     *
7092     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7093     * insets object is propagated down the hierarchy, so any changes made to it will
7094     * be seen by all following views (including potentially ones above in
7095     * the hierarchy since this is a depth-first traversal).  The first view
7096     * that returns true will abort the entire traversal.
7097     *
7098     * <p>The default implementation works well for a situation where it is
7099     * used with a container that covers the entire window, allowing it to
7100     * apply the appropriate insets to its content on all edges.  If you need
7101     * a more complicated layout (such as two different views fitting system
7102     * windows, one on the top of the window, and one on the bottom),
7103     * you can override the method and handle the insets however you would like.
7104     * Note that the insets provided by the framework are always relative to the
7105     * far edges of the window, not accounting for the location of the called view
7106     * within that window.  (In fact when this method is called you do not yet know
7107     * where the layout will place the view, as it is done before layout happens.)
7108     *
7109     * <p>Note: unlike many View methods, there is no dispatch phase to this
7110     * call.  If you are overriding it in a ViewGroup and want to allow the
7111     * call to continue to your children, you must be sure to call the super
7112     * implementation.
7113     *
7114     * <p>Here is a sample layout that makes use of fitting system windows
7115     * to have controls for a video view placed inside of the window decorations
7116     * that it hides and shows.  This can be used with code like the second
7117     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7118     *
7119     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7120     *
7121     * @param insets Current content insets of the window.  Prior to
7122     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7123     * the insets or else you and Android will be unhappy.
7124     *
7125     * @return {@code true} if this view applied the insets and it should not
7126     * continue propagating further down the hierarchy, {@code false} otherwise.
7127     * @see #getFitsSystemWindows()
7128     * @see #setFitsSystemWindows(boolean)
7129     * @see #setSystemUiVisibility(int)
7130     *
7131     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7132     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7133     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7134     * to implement handling their own insets.
7135     */
7136    protected boolean fitSystemWindows(Rect insets) {
7137        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7138            if (insets == null) {
7139                // Null insets by definition have already been consumed.
7140                // This call cannot apply insets since there are none to apply,
7141                // so return false.
7142                return false;
7143            }
7144            // If we're not in the process of dispatching the newer apply insets call,
7145            // that means we're not in the compatibility path. Dispatch into the newer
7146            // apply insets path and take things from there.
7147            try {
7148                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7149                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7150            } finally {
7151                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7152            }
7153        } else {
7154            // We're being called from the newer apply insets path.
7155            // Perform the standard fallback behavior.
7156            return fitSystemWindowsInt(insets);
7157        }
7158    }
7159
7160    private boolean fitSystemWindowsInt(Rect insets) {
7161        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7162            mUserPaddingStart = UNDEFINED_PADDING;
7163            mUserPaddingEnd = UNDEFINED_PADDING;
7164            Rect localInsets = sThreadLocal.get();
7165            if (localInsets == null) {
7166                localInsets = new Rect();
7167                sThreadLocal.set(localInsets);
7168            }
7169            boolean res = computeFitSystemWindows(insets, localInsets);
7170            mUserPaddingLeftInitial = localInsets.left;
7171            mUserPaddingRightInitial = localInsets.right;
7172            internalSetPadding(localInsets.left, localInsets.top,
7173                    localInsets.right, localInsets.bottom);
7174            return res;
7175        }
7176        return false;
7177    }
7178
7179    /**
7180     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7181     *
7182     * <p>This method should be overridden by views that wish to apply a policy different from or
7183     * in addition to the default behavior. Clients that wish to force a view subtree
7184     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7185     *
7186     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7187     * it will be called during dispatch instead of this method. The listener may optionally
7188     * call this method from its own implementation if it wishes to apply the view's default
7189     * insets policy in addition to its own.</p>
7190     *
7191     * <p>Implementations of this method should either return the insets parameter unchanged
7192     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7193     * that this view applied itself. This allows new inset types added in future platform
7194     * versions to pass through existing implementations unchanged without being erroneously
7195     * consumed.</p>
7196     *
7197     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7198     * property is set then the view will consume the system window insets and apply them
7199     * as padding for the view.</p>
7200     *
7201     * @param insets Insets to apply
7202     * @return The supplied insets with any applied insets consumed
7203     */
7204    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7205        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7206            // We weren't called from within a direct call to fitSystemWindows,
7207            // call into it as a fallback in case we're in a class that overrides it
7208            // and has logic to perform.
7209            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7210                return insets.consumeSystemWindowInsets();
7211            }
7212        } else {
7213            // We were called from within a direct call to fitSystemWindows.
7214            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7215                return insets.consumeSystemWindowInsets();
7216            }
7217        }
7218        return insets;
7219    }
7220
7221    /**
7222     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7223     * window insets to this view. The listener's
7224     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7225     * method will be called instead of the view's
7226     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7227     *
7228     * @param listener Listener to set
7229     *
7230     * @see #onApplyWindowInsets(WindowInsets)
7231     */
7232    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7233        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7234    }
7235
7236    /**
7237     * Request to apply the given window insets to this view or another view in its subtree.
7238     *
7239     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7240     * obscured by window decorations or overlays. This can include the status and navigation bars,
7241     * action bars, input methods and more. New inset categories may be added in the future.
7242     * The method returns the insets provided minus any that were applied by this view or its
7243     * children.</p>
7244     *
7245     * <p>Clients wishing to provide custom behavior should override the
7246     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7247     * {@link OnApplyWindowInsetsListener} via the
7248     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7249     * method.</p>
7250     *
7251     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7252     * </p>
7253     *
7254     * @param insets Insets to apply
7255     * @return The provided insets minus the insets that were consumed
7256     */
7257    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7258        try {
7259            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7260            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7261                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7262            } else {
7263                return onApplyWindowInsets(insets);
7264            }
7265        } finally {
7266            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7267        }
7268    }
7269
7270    /**
7271     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7272     * only available if the view is attached.
7273     *
7274     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7275     */
7276    public WindowInsets getRootWindowInsets() {
7277        if (mAttachInfo != null) {
7278            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7279        }
7280        return null;
7281    }
7282
7283    /**
7284     * @hide Compute the insets that should be consumed by this view and the ones
7285     * that should propagate to those under it.
7286     */
7287    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7288        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7289                || mAttachInfo == null
7290                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7291                        && !mAttachInfo.mOverscanRequested)) {
7292            outLocalInsets.set(inoutInsets);
7293            inoutInsets.set(0, 0, 0, 0);
7294            return true;
7295        } else {
7296            // The application wants to take care of fitting system window for
7297            // the content...  however we still need to take care of any overscan here.
7298            final Rect overscan = mAttachInfo.mOverscanInsets;
7299            outLocalInsets.set(overscan);
7300            inoutInsets.left -= overscan.left;
7301            inoutInsets.top -= overscan.top;
7302            inoutInsets.right -= overscan.right;
7303            inoutInsets.bottom -= overscan.bottom;
7304            return false;
7305        }
7306    }
7307
7308    /**
7309     * Compute insets that should be consumed by this view and the ones that should propagate
7310     * to those under it.
7311     *
7312     * @param in Insets currently being processed by this View, likely received as a parameter
7313     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7314     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7315     *                       by this view
7316     * @return Insets that should be passed along to views under this one
7317     */
7318    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7319        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7320                || mAttachInfo == null
7321                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7322            outLocalInsets.set(in.getSystemWindowInsets());
7323            return in.consumeSystemWindowInsets();
7324        } else {
7325            outLocalInsets.set(0, 0, 0, 0);
7326            return in;
7327        }
7328    }
7329
7330    /**
7331     * Sets whether or not this view should account for system screen decorations
7332     * such as the status bar and inset its content; that is, controlling whether
7333     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7334     * executed.  See that method for more details.
7335     *
7336     * <p>Note that if you are providing your own implementation of
7337     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7338     * flag to true -- your implementation will be overriding the default
7339     * implementation that checks this flag.
7340     *
7341     * @param fitSystemWindows If true, then the default implementation of
7342     * {@link #fitSystemWindows(Rect)} will be executed.
7343     *
7344     * @attr ref android.R.styleable#View_fitsSystemWindows
7345     * @see #getFitsSystemWindows()
7346     * @see #fitSystemWindows(Rect)
7347     * @see #setSystemUiVisibility(int)
7348     */
7349    public void setFitsSystemWindows(boolean fitSystemWindows) {
7350        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7351    }
7352
7353    /**
7354     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7355     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7356     * will be executed.
7357     *
7358     * @return {@code true} if the default implementation of
7359     * {@link #fitSystemWindows(Rect)} will be executed.
7360     *
7361     * @attr ref android.R.styleable#View_fitsSystemWindows
7362     * @see #setFitsSystemWindows(boolean)
7363     * @see #fitSystemWindows(Rect)
7364     * @see #setSystemUiVisibility(int)
7365     */
7366    @ViewDebug.ExportedProperty
7367    public boolean getFitsSystemWindows() {
7368        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7369    }
7370
7371    /** @hide */
7372    public boolean fitsSystemWindows() {
7373        return getFitsSystemWindows();
7374    }
7375
7376    /**
7377     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7378     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7379     */
7380    public void requestFitSystemWindows() {
7381        if (mParent != null) {
7382            mParent.requestFitSystemWindows();
7383        }
7384    }
7385
7386    /**
7387     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7388     */
7389    public void requestApplyInsets() {
7390        requestFitSystemWindows();
7391    }
7392
7393    /**
7394     * For use by PhoneWindow to make its own system window fitting optional.
7395     * @hide
7396     */
7397    public void makeOptionalFitsSystemWindows() {
7398        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7399    }
7400
7401    /**
7402     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7403     * treat them as such.
7404     * @hide
7405     */
7406    public void getOutsets(Rect outOutsetRect) {
7407        if (mAttachInfo != null) {
7408            outOutsetRect.set(mAttachInfo.mOutsets);
7409        } else {
7410            outOutsetRect.setEmpty();
7411        }
7412    }
7413
7414    /**
7415     * Returns the visibility status for this view.
7416     *
7417     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7418     * @attr ref android.R.styleable#View_visibility
7419     */
7420    @ViewDebug.ExportedProperty(mapping = {
7421        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7422        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7423        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7424    })
7425    @Visibility
7426    public int getVisibility() {
7427        return mViewFlags & VISIBILITY_MASK;
7428    }
7429
7430    /**
7431     * Set the enabled state of this view.
7432     *
7433     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7434     * @attr ref android.R.styleable#View_visibility
7435     */
7436    @RemotableViewMethod
7437    public void setVisibility(@Visibility int visibility) {
7438        setFlags(visibility, VISIBILITY_MASK);
7439    }
7440
7441    /**
7442     * Returns the enabled status for this view. The interpretation of the
7443     * enabled state varies by subclass.
7444     *
7445     * @return True if this view is enabled, false otherwise.
7446     */
7447    @ViewDebug.ExportedProperty
7448    public boolean isEnabled() {
7449        return (mViewFlags & ENABLED_MASK) == ENABLED;
7450    }
7451
7452    /**
7453     * Set the enabled state of this view. The interpretation of the enabled
7454     * state varies by subclass.
7455     *
7456     * @param enabled True if this view is enabled, false otherwise.
7457     */
7458    @RemotableViewMethod
7459    public void setEnabled(boolean enabled) {
7460        if (enabled == isEnabled()) return;
7461
7462        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7463
7464        /*
7465         * The View most likely has to change its appearance, so refresh
7466         * the drawable state.
7467         */
7468        refreshDrawableState();
7469
7470        // Invalidate too, since the default behavior for views is to be
7471        // be drawn at 50% alpha rather than to change the drawable.
7472        invalidate(true);
7473
7474        if (!enabled) {
7475            cancelPendingInputEvents();
7476        }
7477    }
7478
7479    /**
7480     * Set whether this view can receive the focus.
7481     *
7482     * Setting this to false will also ensure that this view is not focusable
7483     * in touch mode.
7484     *
7485     * @param focusable If true, this view can receive the focus.
7486     *
7487     * @see #setFocusableInTouchMode(boolean)
7488     * @attr ref android.R.styleable#View_focusable
7489     */
7490    public void setFocusable(boolean focusable) {
7491        if (!focusable) {
7492            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7493        }
7494        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7495    }
7496
7497    /**
7498     * Set whether this view can receive focus while in touch mode.
7499     *
7500     * Setting this to true will also ensure that this view is focusable.
7501     *
7502     * @param focusableInTouchMode If true, this view can receive the focus while
7503     *   in touch mode.
7504     *
7505     * @see #setFocusable(boolean)
7506     * @attr ref android.R.styleable#View_focusableInTouchMode
7507     */
7508    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7509        // Focusable in touch mode should always be set before the focusable flag
7510        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7511        // which, in touch mode, will not successfully request focus on this view
7512        // because the focusable in touch mode flag is not set
7513        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7514        if (focusableInTouchMode) {
7515            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7516        }
7517    }
7518
7519    /**
7520     * Set whether this view should have sound effects enabled for events such as
7521     * clicking and touching.
7522     *
7523     * <p>You may wish to disable sound effects for a view if you already play sounds,
7524     * for instance, a dial key that plays dtmf tones.
7525     *
7526     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7527     * @see #isSoundEffectsEnabled()
7528     * @see #playSoundEffect(int)
7529     * @attr ref android.R.styleable#View_soundEffectsEnabled
7530     */
7531    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7532        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7533    }
7534
7535    /**
7536     * @return whether this view should have sound effects enabled for events such as
7537     *     clicking and touching.
7538     *
7539     * @see #setSoundEffectsEnabled(boolean)
7540     * @see #playSoundEffect(int)
7541     * @attr ref android.R.styleable#View_soundEffectsEnabled
7542     */
7543    @ViewDebug.ExportedProperty
7544    public boolean isSoundEffectsEnabled() {
7545        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7546    }
7547
7548    /**
7549     * Set whether this view should have haptic feedback for events such as
7550     * long presses.
7551     *
7552     * <p>You may wish to disable haptic feedback if your view already controls
7553     * its own haptic feedback.
7554     *
7555     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7556     * @see #isHapticFeedbackEnabled()
7557     * @see #performHapticFeedback(int)
7558     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7559     */
7560    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7561        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7562    }
7563
7564    /**
7565     * @return whether this view should have haptic feedback enabled for events
7566     * long presses.
7567     *
7568     * @see #setHapticFeedbackEnabled(boolean)
7569     * @see #performHapticFeedback(int)
7570     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7571     */
7572    @ViewDebug.ExportedProperty
7573    public boolean isHapticFeedbackEnabled() {
7574        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7575    }
7576
7577    /**
7578     * Returns the layout direction for this view.
7579     *
7580     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7581     *   {@link #LAYOUT_DIRECTION_RTL},
7582     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7583     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7584     *
7585     * @attr ref android.R.styleable#View_layoutDirection
7586     *
7587     * @hide
7588     */
7589    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7590        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7591        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7592        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7593        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7594    })
7595    @LayoutDir
7596    public int getRawLayoutDirection() {
7597        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7598    }
7599
7600    /**
7601     * Set the layout direction for this view. This will propagate a reset of layout direction
7602     * resolution to the view's children and resolve layout direction for this view.
7603     *
7604     * @param layoutDirection the layout direction to set. Should be one of:
7605     *
7606     * {@link #LAYOUT_DIRECTION_LTR},
7607     * {@link #LAYOUT_DIRECTION_RTL},
7608     * {@link #LAYOUT_DIRECTION_INHERIT},
7609     * {@link #LAYOUT_DIRECTION_LOCALE}.
7610     *
7611     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7612     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7613     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7614     *
7615     * @attr ref android.R.styleable#View_layoutDirection
7616     */
7617    @RemotableViewMethod
7618    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7619        if (getRawLayoutDirection() != layoutDirection) {
7620            // Reset the current layout direction and the resolved one
7621            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7622            resetRtlProperties();
7623            // Set the new layout direction (filtered)
7624            mPrivateFlags2 |=
7625                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7626            // We need to resolve all RTL properties as they all depend on layout direction
7627            resolveRtlPropertiesIfNeeded();
7628            requestLayout();
7629            invalidate(true);
7630        }
7631    }
7632
7633    /**
7634     * Returns the resolved layout direction for this view.
7635     *
7636     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7637     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7638     *
7639     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7640     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7641     *
7642     * @attr ref android.R.styleable#View_layoutDirection
7643     */
7644    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7645        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7646        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7647    })
7648    @ResolvedLayoutDir
7649    public int getLayoutDirection() {
7650        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7651        if (targetSdkVersion < JELLY_BEAN_MR1) {
7652            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7653            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7654        }
7655        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7656                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7657    }
7658
7659    /**
7660     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7661     * layout attribute and/or the inherited value from the parent
7662     *
7663     * @return true if the layout is right-to-left.
7664     *
7665     * @hide
7666     */
7667    @ViewDebug.ExportedProperty(category = "layout")
7668    public boolean isLayoutRtl() {
7669        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7670    }
7671
7672    /**
7673     * Indicates whether the view is currently tracking transient state that the
7674     * app should not need to concern itself with saving and restoring, but that
7675     * the framework should take special note to preserve when possible.
7676     *
7677     * <p>A view with transient state cannot be trivially rebound from an external
7678     * data source, such as an adapter binding item views in a list. This may be
7679     * because the view is performing an animation, tracking user selection
7680     * of content, or similar.</p>
7681     *
7682     * @return true if the view has transient state
7683     */
7684    @ViewDebug.ExportedProperty(category = "layout")
7685    public boolean hasTransientState() {
7686        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7687    }
7688
7689    /**
7690     * Set whether this view is currently tracking transient state that the
7691     * framework should attempt to preserve when possible. This flag is reference counted,
7692     * so every call to setHasTransientState(true) should be paired with a later call
7693     * to setHasTransientState(false).
7694     *
7695     * <p>A view with transient state cannot be trivially rebound from an external
7696     * data source, such as an adapter binding item views in a list. This may be
7697     * because the view is performing an animation, tracking user selection
7698     * of content, or similar.</p>
7699     *
7700     * @param hasTransientState true if this view has transient state
7701     */
7702    public void setHasTransientState(boolean hasTransientState) {
7703        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7704                mTransientStateCount - 1;
7705        if (mTransientStateCount < 0) {
7706            mTransientStateCount = 0;
7707            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7708                    "unmatched pair of setHasTransientState calls");
7709        } else if ((hasTransientState && mTransientStateCount == 1) ||
7710                (!hasTransientState && mTransientStateCount == 0)) {
7711            // update flag if we've just incremented up from 0 or decremented down to 0
7712            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7713                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7714            if (mParent != null) {
7715                try {
7716                    mParent.childHasTransientStateChanged(this, hasTransientState);
7717                } catch (AbstractMethodError e) {
7718                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7719                            " does not fully implement ViewParent", e);
7720                }
7721            }
7722        }
7723    }
7724
7725    /**
7726     * Returns true if this view is currently attached to a window.
7727     */
7728    public boolean isAttachedToWindow() {
7729        return mAttachInfo != null;
7730    }
7731
7732    /**
7733     * Returns true if this view has been through at least one layout since it
7734     * was last attached to or detached from a window.
7735     */
7736    public boolean isLaidOut() {
7737        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7738    }
7739
7740    /**
7741     * If this view doesn't do any drawing on its own, set this flag to
7742     * allow further optimizations. By default, this flag is not set on
7743     * View, but could be set on some View subclasses such as ViewGroup.
7744     *
7745     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7746     * you should clear this flag.
7747     *
7748     * @param willNotDraw whether or not this View draw on its own
7749     */
7750    public void setWillNotDraw(boolean willNotDraw) {
7751        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7752    }
7753
7754    /**
7755     * Returns whether or not this View draws on its own.
7756     *
7757     * @return true if this view has nothing to draw, false otherwise
7758     */
7759    @ViewDebug.ExportedProperty(category = "drawing")
7760    public boolean willNotDraw() {
7761        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7762    }
7763
7764    /**
7765     * When a View's drawing cache is enabled, drawing is redirected to an
7766     * offscreen bitmap. Some views, like an ImageView, must be able to
7767     * bypass this mechanism if they already draw a single bitmap, to avoid
7768     * unnecessary usage of the memory.
7769     *
7770     * @param willNotCacheDrawing true if this view does not cache its
7771     *        drawing, false otherwise
7772     */
7773    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7774        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7775    }
7776
7777    /**
7778     * Returns whether or not this View can cache its drawing or not.
7779     *
7780     * @return true if this view does not cache its drawing, false otherwise
7781     */
7782    @ViewDebug.ExportedProperty(category = "drawing")
7783    public boolean willNotCacheDrawing() {
7784        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7785    }
7786
7787    /**
7788     * Indicates whether this view reacts to click events or not.
7789     *
7790     * @return true if the view is clickable, false otherwise
7791     *
7792     * @see #setClickable(boolean)
7793     * @attr ref android.R.styleable#View_clickable
7794     */
7795    @ViewDebug.ExportedProperty
7796    public boolean isClickable() {
7797        return (mViewFlags & CLICKABLE) == CLICKABLE;
7798    }
7799
7800    /**
7801     * Enables or disables click events for this view. When a view
7802     * is clickable it will change its state to "pressed" on every click.
7803     * Subclasses should set the view clickable to visually react to
7804     * user's clicks.
7805     *
7806     * @param clickable true to make the view clickable, false otherwise
7807     *
7808     * @see #isClickable()
7809     * @attr ref android.R.styleable#View_clickable
7810     */
7811    public void setClickable(boolean clickable) {
7812        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7813    }
7814
7815    /**
7816     * Indicates whether this view reacts to long click events or not.
7817     *
7818     * @return true if the view is long clickable, false otherwise
7819     *
7820     * @see #setLongClickable(boolean)
7821     * @attr ref android.R.styleable#View_longClickable
7822     */
7823    public boolean isLongClickable() {
7824        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7825    }
7826
7827    /**
7828     * Enables or disables long click events for this view. When a view is long
7829     * clickable it reacts to the user holding down the button for a longer
7830     * duration than a tap. This event can either launch the listener or a
7831     * context menu.
7832     *
7833     * @param longClickable true to make the view long clickable, false otherwise
7834     * @see #isLongClickable()
7835     * @attr ref android.R.styleable#View_longClickable
7836     */
7837    public void setLongClickable(boolean longClickable) {
7838        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7839    }
7840
7841    /**
7842     * Indicates whether this view reacts to context clicks or not.
7843     *
7844     * @return true if the view is context clickable, false otherwise
7845     * @see #setContextClickable(boolean)
7846     * @attr ref android.R.styleable#View_contextClickable
7847     */
7848    public boolean isContextClickable() {
7849        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
7850    }
7851
7852    /**
7853     * Enables or disables context clicking for this view. This event can launch the listener.
7854     *
7855     * @param contextClickable true to make the view react to a context click, false otherwise
7856     * @see #isContextClickable()
7857     * @attr ref android.R.styleable#View_contextClickable
7858     */
7859    public void setContextClickable(boolean contextClickable) {
7860        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
7861    }
7862
7863    /**
7864     * Sets the pressed state for this view and provides a touch coordinate for
7865     * animation hinting.
7866     *
7867     * @param pressed Pass true to set the View's internal state to "pressed",
7868     *            or false to reverts the View's internal state from a
7869     *            previously set "pressed" state.
7870     * @param x The x coordinate of the touch that caused the press
7871     * @param y The y coordinate of the touch that caused the press
7872     */
7873    private void setPressed(boolean pressed, float x, float y) {
7874        if (pressed) {
7875            drawableHotspotChanged(x, y);
7876        }
7877
7878        setPressed(pressed);
7879    }
7880
7881    /**
7882     * Sets the pressed state for this view.
7883     *
7884     * @see #isClickable()
7885     * @see #setClickable(boolean)
7886     *
7887     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7888     *        the View's internal state from a previously set "pressed" state.
7889     */
7890    public void setPressed(boolean pressed) {
7891        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7892
7893        if (pressed) {
7894            mPrivateFlags |= PFLAG_PRESSED;
7895        } else {
7896            mPrivateFlags &= ~PFLAG_PRESSED;
7897        }
7898
7899        if (needsRefresh) {
7900            refreshDrawableState();
7901        }
7902        dispatchSetPressed(pressed);
7903    }
7904
7905    /**
7906     * Dispatch setPressed to all of this View's children.
7907     *
7908     * @see #setPressed(boolean)
7909     *
7910     * @param pressed The new pressed state
7911     */
7912    protected void dispatchSetPressed(boolean pressed) {
7913    }
7914
7915    /**
7916     * Indicates whether the view is currently in pressed state. Unless
7917     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7918     * the pressed state.
7919     *
7920     * @see #setPressed(boolean)
7921     * @see #isClickable()
7922     * @see #setClickable(boolean)
7923     *
7924     * @return true if the view is currently pressed, false otherwise
7925     */
7926    @ViewDebug.ExportedProperty
7927    public boolean isPressed() {
7928        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7929    }
7930
7931    /**
7932     * @hide
7933     * Indicates whether this view will participate in data collection through
7934     * {@link ViewStructure}.  If true, it will not provide any data
7935     * for itself or its children.  If false, the normal data collection will be allowed.
7936     *
7937     * @return Returns false if assist data collection is not blocked, else true.
7938     *
7939     * @see #setAssistBlocked(boolean)
7940     * @attr ref android.R.styleable#View_assistBlocked
7941     */
7942    public boolean isAssistBlocked() {
7943        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7944    }
7945
7946    /**
7947     * @hide
7948     * Controls whether assist data collection from this view and its children is enabled
7949     * (that is, whether {@link #onProvideStructure} and
7950     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
7951     * allowing normal assist collection.  Setting this to false will disable assist collection.
7952     *
7953     * @param enabled Set to true to <em>disable</em> assist data collection, or false
7954     * (the default) to allow it.
7955     *
7956     * @see #isAssistBlocked()
7957     * @see #onProvideStructure
7958     * @see #onProvideVirtualStructure
7959     * @attr ref android.R.styleable#View_assistBlocked
7960     */
7961    public void setAssistBlocked(boolean enabled) {
7962        if (enabled) {
7963            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7964        } else {
7965            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7966        }
7967    }
7968
7969    /**
7970     * Indicates whether this view will save its state (that is,
7971     * whether its {@link #onSaveInstanceState} method will be called).
7972     *
7973     * @return Returns true if the view state saving is enabled, else false.
7974     *
7975     * @see #setSaveEnabled(boolean)
7976     * @attr ref android.R.styleable#View_saveEnabled
7977     */
7978    public boolean isSaveEnabled() {
7979        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7980    }
7981
7982    /**
7983     * Controls whether the saving of this view's state is
7984     * enabled (that is, whether its {@link #onSaveInstanceState} method
7985     * will be called).  Note that even if freezing is enabled, the
7986     * view still must have an id assigned to it (via {@link #setId(int)})
7987     * for its state to be saved.  This flag can only disable the
7988     * saving of this view; any child views may still have their state saved.
7989     *
7990     * @param enabled Set to false to <em>disable</em> state saving, or true
7991     * (the default) to allow it.
7992     *
7993     * @see #isSaveEnabled()
7994     * @see #setId(int)
7995     * @see #onSaveInstanceState()
7996     * @attr ref android.R.styleable#View_saveEnabled
7997     */
7998    public void setSaveEnabled(boolean enabled) {
7999        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8000    }
8001
8002    /**
8003     * Gets whether the framework should discard touches when the view's
8004     * window is obscured by another visible window.
8005     * Refer to the {@link View} security documentation for more details.
8006     *
8007     * @return True if touch filtering is enabled.
8008     *
8009     * @see #setFilterTouchesWhenObscured(boolean)
8010     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8011     */
8012    @ViewDebug.ExportedProperty
8013    public boolean getFilterTouchesWhenObscured() {
8014        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8015    }
8016
8017    /**
8018     * Sets whether the framework should discard touches when the view's
8019     * window is obscured by another visible window.
8020     * Refer to the {@link View} security documentation for more details.
8021     *
8022     * @param enabled True if touch filtering should be enabled.
8023     *
8024     * @see #getFilterTouchesWhenObscured
8025     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8026     */
8027    public void setFilterTouchesWhenObscured(boolean enabled) {
8028        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8029                FILTER_TOUCHES_WHEN_OBSCURED);
8030    }
8031
8032    /**
8033     * Indicates whether the entire hierarchy under this view will save its
8034     * state when a state saving traversal occurs from its parent.  The default
8035     * is true; if false, these views will not be saved unless
8036     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8037     *
8038     * @return Returns true if the view state saving from parent is enabled, else false.
8039     *
8040     * @see #setSaveFromParentEnabled(boolean)
8041     */
8042    public boolean isSaveFromParentEnabled() {
8043        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8044    }
8045
8046    /**
8047     * Controls whether the entire hierarchy under this view will save its
8048     * state when a state saving traversal occurs from its parent.  The default
8049     * is true; if false, these views will not be saved unless
8050     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8051     *
8052     * @param enabled Set to false to <em>disable</em> state saving, or true
8053     * (the default) to allow it.
8054     *
8055     * @see #isSaveFromParentEnabled()
8056     * @see #setId(int)
8057     * @see #onSaveInstanceState()
8058     */
8059    public void setSaveFromParentEnabled(boolean enabled) {
8060        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8061    }
8062
8063
8064    /**
8065     * Returns whether this View is able to take focus.
8066     *
8067     * @return True if this view can take focus, or false otherwise.
8068     * @attr ref android.R.styleable#View_focusable
8069     */
8070    @ViewDebug.ExportedProperty(category = "focus")
8071    public final boolean isFocusable() {
8072        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8073    }
8074
8075    /**
8076     * When a view is focusable, it may not want to take focus when in touch mode.
8077     * For example, a button would like focus when the user is navigating via a D-pad
8078     * so that the user can click on it, but once the user starts touching the screen,
8079     * the button shouldn't take focus
8080     * @return Whether the view is focusable in touch mode.
8081     * @attr ref android.R.styleable#View_focusableInTouchMode
8082     */
8083    @ViewDebug.ExportedProperty
8084    public final boolean isFocusableInTouchMode() {
8085        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8086    }
8087
8088    /**
8089     * Find the nearest view in the specified direction that can take focus.
8090     * This does not actually give focus to that view.
8091     *
8092     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8093     *
8094     * @return The nearest focusable in the specified direction, or null if none
8095     *         can be found.
8096     */
8097    public View focusSearch(@FocusRealDirection int direction) {
8098        if (mParent != null) {
8099            return mParent.focusSearch(this, direction);
8100        } else {
8101            return null;
8102        }
8103    }
8104
8105    /**
8106     * This method is the last chance for the focused view and its ancestors to
8107     * respond to an arrow key. This is called when the focused view did not
8108     * consume the key internally, nor could the view system find a new view in
8109     * the requested direction to give focus to.
8110     *
8111     * @param focused The currently focused view.
8112     * @param direction The direction focus wants to move. One of FOCUS_UP,
8113     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8114     * @return True if the this view consumed this unhandled move.
8115     */
8116    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8117        return false;
8118    }
8119
8120    /**
8121     * If a user manually specified the next view id for a particular direction,
8122     * use the root to look up the view.
8123     * @param root The root view of the hierarchy containing this view.
8124     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8125     * or FOCUS_BACKWARD.
8126     * @return The user specified next view, or null if there is none.
8127     */
8128    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8129        switch (direction) {
8130            case FOCUS_LEFT:
8131                if (mNextFocusLeftId == View.NO_ID) return null;
8132                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8133            case FOCUS_RIGHT:
8134                if (mNextFocusRightId == View.NO_ID) return null;
8135                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8136            case FOCUS_UP:
8137                if (mNextFocusUpId == View.NO_ID) return null;
8138                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8139            case FOCUS_DOWN:
8140                if (mNextFocusDownId == View.NO_ID) return null;
8141                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8142            case FOCUS_FORWARD:
8143                if (mNextFocusForwardId == View.NO_ID) return null;
8144                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8145            case FOCUS_BACKWARD: {
8146                if (mID == View.NO_ID) return null;
8147                final int id = mID;
8148                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8149                    @Override
8150                    public boolean apply(View t) {
8151                        return t.mNextFocusForwardId == id;
8152                    }
8153                });
8154            }
8155        }
8156        return null;
8157    }
8158
8159    private View findViewInsideOutShouldExist(View root, int id) {
8160        if (mMatchIdPredicate == null) {
8161            mMatchIdPredicate = new MatchIdPredicate();
8162        }
8163        mMatchIdPredicate.mId = id;
8164        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8165        if (result == null) {
8166            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8167        }
8168        return result;
8169    }
8170
8171    /**
8172     * Find and return all focusable views that are descendants of this view,
8173     * possibly including this view if it is focusable itself.
8174     *
8175     * @param direction The direction of the focus
8176     * @return A list of focusable views
8177     */
8178    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8179        ArrayList<View> result = new ArrayList<View>(24);
8180        addFocusables(result, direction);
8181        return result;
8182    }
8183
8184    /**
8185     * Add any focusable views that are descendants of this view (possibly
8186     * including this view if it is focusable itself) to views.  If we are in touch mode,
8187     * only add views that are also focusable in touch mode.
8188     *
8189     * @param views Focusable views found so far
8190     * @param direction The direction of the focus
8191     */
8192    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8193        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8194    }
8195
8196    /**
8197     * Adds any focusable views that are descendants of this view (possibly
8198     * including this view if it is focusable itself) to views. This method
8199     * adds all focusable views regardless if we are in touch mode or
8200     * only views focusable in touch mode if we are in touch mode or
8201     * only views that can take accessibility focus if accessibility is enabled
8202     * depending on the focusable mode parameter.
8203     *
8204     * @param views Focusable views found so far or null if all we are interested is
8205     *        the number of focusables.
8206     * @param direction The direction of the focus.
8207     * @param focusableMode The type of focusables to be added.
8208     *
8209     * @see #FOCUSABLES_ALL
8210     * @see #FOCUSABLES_TOUCH_MODE
8211     */
8212    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8213            @FocusableMode int focusableMode) {
8214        if (views == null) {
8215            return;
8216        }
8217        if (!isFocusable()) {
8218            return;
8219        }
8220        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8221                && isInTouchMode() && !isFocusableInTouchMode()) {
8222            return;
8223        }
8224        views.add(this);
8225    }
8226
8227    /**
8228     * Finds the Views that contain given text. The containment is case insensitive.
8229     * The search is performed by either the text that the View renders or the content
8230     * description that describes the view for accessibility purposes and the view does
8231     * not render or both. Clients can specify how the search is to be performed via
8232     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8233     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8234     *
8235     * @param outViews The output list of matching Views.
8236     * @param searched The text to match against.
8237     *
8238     * @see #FIND_VIEWS_WITH_TEXT
8239     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8240     * @see #setContentDescription(CharSequence)
8241     */
8242    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8243            @FindViewFlags int flags) {
8244        if (getAccessibilityNodeProvider() != null) {
8245            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8246                outViews.add(this);
8247            }
8248        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8249                && (searched != null && searched.length() > 0)
8250                && (mContentDescription != null && mContentDescription.length() > 0)) {
8251            String searchedLowerCase = searched.toString().toLowerCase();
8252            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8253            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8254                outViews.add(this);
8255            }
8256        }
8257    }
8258
8259    /**
8260     * Find and return all touchable views that are descendants of this view,
8261     * possibly including this view if it is touchable itself.
8262     *
8263     * @return A list of touchable views
8264     */
8265    public ArrayList<View> getTouchables() {
8266        ArrayList<View> result = new ArrayList<View>();
8267        addTouchables(result);
8268        return result;
8269    }
8270
8271    /**
8272     * Add any touchable views that are descendants of this view (possibly
8273     * including this view if it is touchable itself) to views.
8274     *
8275     * @param views Touchable views found so far
8276     */
8277    public void addTouchables(ArrayList<View> views) {
8278        final int viewFlags = mViewFlags;
8279
8280        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8281                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8282                && (viewFlags & ENABLED_MASK) == ENABLED) {
8283            views.add(this);
8284        }
8285    }
8286
8287    /**
8288     * Returns whether this View is accessibility focused.
8289     *
8290     * @return True if this View is accessibility focused.
8291     */
8292    public boolean isAccessibilityFocused() {
8293        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8294    }
8295
8296    /**
8297     * Call this to try to give accessibility focus to this view.
8298     *
8299     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8300     * returns false or the view is no visible or the view already has accessibility
8301     * focus.
8302     *
8303     * See also {@link #focusSearch(int)}, which is what you call to say that you
8304     * have focus, and you want your parent to look for the next one.
8305     *
8306     * @return Whether this view actually took accessibility focus.
8307     *
8308     * @hide
8309     */
8310    public boolean requestAccessibilityFocus() {
8311        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8312        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8313            return false;
8314        }
8315        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8316            return false;
8317        }
8318        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8319            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8320            ViewRootImpl viewRootImpl = getViewRootImpl();
8321            if (viewRootImpl != null) {
8322                viewRootImpl.setAccessibilityFocus(this, null);
8323            }
8324            invalidate();
8325            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8326            return true;
8327        }
8328        return false;
8329    }
8330
8331    /**
8332     * Call this to try to clear accessibility focus of this view.
8333     *
8334     * See also {@link #focusSearch(int)}, which is what you call to say that you
8335     * have focus, and you want your parent to look for the next one.
8336     *
8337     * @hide
8338     */
8339    public void clearAccessibilityFocus() {
8340        clearAccessibilityFocusNoCallbacks();
8341        // Clear the global reference of accessibility focus if this
8342        // view or any of its descendants had accessibility focus.
8343        ViewRootImpl viewRootImpl = getViewRootImpl();
8344        if (viewRootImpl != null) {
8345            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8346            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8347                viewRootImpl.setAccessibilityFocus(null, null);
8348            }
8349        }
8350    }
8351
8352    private void sendAccessibilityHoverEvent(int eventType) {
8353        // Since we are not delivering to a client accessibility events from not
8354        // important views (unless the clinet request that) we need to fire the
8355        // event from the deepest view exposed to the client. As a consequence if
8356        // the user crosses a not exposed view the client will see enter and exit
8357        // of the exposed predecessor followed by and enter and exit of that same
8358        // predecessor when entering and exiting the not exposed descendant. This
8359        // is fine since the client has a clear idea which view is hovered at the
8360        // price of a couple more events being sent. This is a simple and
8361        // working solution.
8362        View source = this;
8363        while (true) {
8364            if (source.includeForAccessibility()) {
8365                source.sendAccessibilityEvent(eventType);
8366                return;
8367            }
8368            ViewParent parent = source.getParent();
8369            if (parent instanceof View) {
8370                source = (View) parent;
8371            } else {
8372                return;
8373            }
8374        }
8375    }
8376
8377    /**
8378     * Clears accessibility focus without calling any callback methods
8379     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8380     * is used for clearing accessibility focus when giving this focus to
8381     * another view.
8382     */
8383    void clearAccessibilityFocusNoCallbacks() {
8384        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8385            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8386            invalidate();
8387            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8388        }
8389    }
8390
8391    /**
8392     * Call this to try to give focus to a specific view or to one of its
8393     * descendants.
8394     *
8395     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8396     * false), or if it is focusable and it is not focusable in touch mode
8397     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8398     *
8399     * See also {@link #focusSearch(int)}, which is what you call to say that you
8400     * have focus, and you want your parent to look for the next one.
8401     *
8402     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8403     * {@link #FOCUS_DOWN} and <code>null</code>.
8404     *
8405     * @return Whether this view or one of its descendants actually took focus.
8406     */
8407    public final boolean requestFocus() {
8408        return requestFocus(View.FOCUS_DOWN);
8409    }
8410
8411    /**
8412     * Call this to try to give focus to a specific view or to one of its
8413     * descendants and give it a hint about what direction focus is heading.
8414     *
8415     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8416     * false), or if it is focusable and it is not focusable in touch mode
8417     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8418     *
8419     * See also {@link #focusSearch(int)}, which is what you call to say that you
8420     * have focus, and you want your parent to look for the next one.
8421     *
8422     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8423     * <code>null</code> set for the previously focused rectangle.
8424     *
8425     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8426     * @return Whether this view or one of its descendants actually took focus.
8427     */
8428    public final boolean requestFocus(int direction) {
8429        return requestFocus(direction, null);
8430    }
8431
8432    /**
8433     * Call this to try to give focus to a specific view or to one of its descendants
8434     * and give it hints about the direction and a specific rectangle that the focus
8435     * is coming from.  The rectangle can help give larger views a finer grained hint
8436     * about where focus is coming from, and therefore, where to show selection, or
8437     * forward focus change internally.
8438     *
8439     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8440     * false), or if it is focusable and it is not focusable in touch mode
8441     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8442     *
8443     * A View will not take focus if it is not visible.
8444     *
8445     * A View will not take focus if one of its parents has
8446     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8447     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8448     *
8449     * See also {@link #focusSearch(int)}, which is what you call to say that you
8450     * have focus, and you want your parent to look for the next one.
8451     *
8452     * You may wish to override this method if your custom {@link View} has an internal
8453     * {@link View} that it wishes to forward the request to.
8454     *
8455     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8456     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8457     *        to give a finer grained hint about where focus is coming from.  May be null
8458     *        if there is no hint.
8459     * @return Whether this view or one of its descendants actually took focus.
8460     */
8461    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8462        return requestFocusNoSearch(direction, previouslyFocusedRect);
8463    }
8464
8465    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8466        // need to be focusable
8467        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8468                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8469            return false;
8470        }
8471
8472        // need to be focusable in touch mode if in touch mode
8473        if (isInTouchMode() &&
8474            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8475               return false;
8476        }
8477
8478        // need to not have any parents blocking us
8479        if (hasAncestorThatBlocksDescendantFocus()) {
8480            return false;
8481        }
8482
8483        handleFocusGainInternal(direction, previouslyFocusedRect);
8484        return true;
8485    }
8486
8487    /**
8488     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8489     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8490     * touch mode to request focus when they are touched.
8491     *
8492     * @return Whether this view or one of its descendants actually took focus.
8493     *
8494     * @see #isInTouchMode()
8495     *
8496     */
8497    public final boolean requestFocusFromTouch() {
8498        // Leave touch mode if we need to
8499        if (isInTouchMode()) {
8500            ViewRootImpl viewRoot = getViewRootImpl();
8501            if (viewRoot != null) {
8502                viewRoot.ensureTouchMode(false);
8503            }
8504        }
8505        return requestFocus(View.FOCUS_DOWN);
8506    }
8507
8508    /**
8509     * @return Whether any ancestor of this view blocks descendant focus.
8510     */
8511    private boolean hasAncestorThatBlocksDescendantFocus() {
8512        final boolean focusableInTouchMode = isFocusableInTouchMode();
8513        ViewParent ancestor = mParent;
8514        while (ancestor instanceof ViewGroup) {
8515            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8516            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8517                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8518                return true;
8519            } else {
8520                ancestor = vgAncestor.getParent();
8521            }
8522        }
8523        return false;
8524    }
8525
8526    /**
8527     * Gets the mode for determining whether this View is important for accessibility
8528     * which is if it fires accessibility events and if it is reported to
8529     * accessibility services that query the screen.
8530     *
8531     * @return The mode for determining whether a View is important for accessibility.
8532     *
8533     * @attr ref android.R.styleable#View_importantForAccessibility
8534     *
8535     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8536     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8537     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8538     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8539     */
8540    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8541            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8542            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8543            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8544            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8545                    to = "noHideDescendants")
8546        })
8547    public int getImportantForAccessibility() {
8548        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8549                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8550    }
8551
8552    /**
8553     * Sets the live region mode for this view. This indicates to accessibility
8554     * services whether they should automatically notify the user about changes
8555     * to the view's content description or text, or to the content descriptions
8556     * or text of the view's children (where applicable).
8557     * <p>
8558     * For example, in a login screen with a TextView that displays an "incorrect
8559     * password" notification, that view should be marked as a live region with
8560     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8561     * <p>
8562     * To disable change notifications for this view, use
8563     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8564     * mode for most views.
8565     * <p>
8566     * To indicate that the user should be notified of changes, use
8567     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8568     * <p>
8569     * If the view's changes should interrupt ongoing speech and notify the user
8570     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8571     *
8572     * @param mode The live region mode for this view, one of:
8573     *        <ul>
8574     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8575     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8576     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8577     *        </ul>
8578     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8579     */
8580    public void setAccessibilityLiveRegion(int mode) {
8581        if (mode != getAccessibilityLiveRegion()) {
8582            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8583            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8584                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8585            notifyViewAccessibilityStateChangedIfNeeded(
8586                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8587        }
8588    }
8589
8590    /**
8591     * Gets the live region mode for this View.
8592     *
8593     * @return The live region mode for the view.
8594     *
8595     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8596     *
8597     * @see #setAccessibilityLiveRegion(int)
8598     */
8599    public int getAccessibilityLiveRegion() {
8600        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8601                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8602    }
8603
8604    /**
8605     * Sets how to determine whether this view is important for accessibility
8606     * which is if it fires accessibility events and if it is reported to
8607     * accessibility services that query the screen.
8608     *
8609     * @param mode How to determine whether this view is important for accessibility.
8610     *
8611     * @attr ref android.R.styleable#View_importantForAccessibility
8612     *
8613     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8614     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8615     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8616     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8617     */
8618    public void setImportantForAccessibility(int mode) {
8619        final int oldMode = getImportantForAccessibility();
8620        if (mode != oldMode) {
8621            // If we're moving between AUTO and another state, we might not need
8622            // to send a subtree changed notification. We'll store the computed
8623            // importance, since we'll need to check it later to make sure.
8624            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8625                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8626            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8627            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8628            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8629                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8630            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8631                notifySubtreeAccessibilityStateChangedIfNeeded();
8632            } else {
8633                notifyViewAccessibilityStateChangedIfNeeded(
8634                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8635            }
8636        }
8637    }
8638
8639    /**
8640     * Computes whether this view should be exposed for accessibility. In
8641     * general, views that are interactive or provide information are exposed
8642     * while views that serve only as containers are hidden.
8643     * <p>
8644     * If an ancestor of this view has importance
8645     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8646     * returns <code>false</code>.
8647     * <p>
8648     * Otherwise, the value is computed according to the view's
8649     * {@link #getImportantForAccessibility()} value:
8650     * <ol>
8651     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8652     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8653     * </code>
8654     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8655     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8656     * view satisfies any of the following:
8657     * <ul>
8658     * <li>Is actionable, e.g. {@link #isClickable()},
8659     * {@link #isLongClickable()}, or {@link #isFocusable()}
8660     * <li>Has an {@link AccessibilityDelegate}
8661     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8662     * {@link OnKeyListener}, etc.
8663     * <li>Is an accessibility live region, e.g.
8664     * {@link #getAccessibilityLiveRegion()} is not
8665     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8666     * </ul>
8667     * </ol>
8668     *
8669     * @return Whether the view is exposed for accessibility.
8670     * @see #setImportantForAccessibility(int)
8671     * @see #getImportantForAccessibility()
8672     */
8673    public boolean isImportantForAccessibility() {
8674        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8675                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8676        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8677                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8678            return false;
8679        }
8680
8681        // Check parent mode to ensure we're not hidden.
8682        ViewParent parent = mParent;
8683        while (parent instanceof View) {
8684            if (((View) parent).getImportantForAccessibility()
8685                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8686                return false;
8687            }
8688            parent = parent.getParent();
8689        }
8690
8691        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8692                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8693                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8694    }
8695
8696    /**
8697     * Gets the parent for accessibility purposes. Note that the parent for
8698     * accessibility is not necessary the immediate parent. It is the first
8699     * predecessor that is important for accessibility.
8700     *
8701     * @return The parent for accessibility purposes.
8702     */
8703    public ViewParent getParentForAccessibility() {
8704        if (mParent instanceof View) {
8705            View parentView = (View) mParent;
8706            if (parentView.includeForAccessibility()) {
8707                return mParent;
8708            } else {
8709                return mParent.getParentForAccessibility();
8710            }
8711        }
8712        return null;
8713    }
8714
8715    /**
8716     * Adds the children of this View relevant for accessibility to the given list
8717     * as output. Since some Views are not important for accessibility the added
8718     * child views are not necessarily direct children of this view, rather they are
8719     * the first level of descendants important for accessibility.
8720     *
8721     * @param outChildren The output list that will receive children for accessibility.
8722     */
8723    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8724
8725    }
8726
8727    /**
8728     * Whether to regard this view for accessibility. A view is regarded for
8729     * accessibility if it is important for accessibility or the querying
8730     * accessibility service has explicitly requested that view not
8731     * important for accessibility are regarded.
8732     *
8733     * @return Whether to regard the view for accessibility.
8734     *
8735     * @hide
8736     */
8737    public boolean includeForAccessibility() {
8738        if (mAttachInfo != null) {
8739            return (mAttachInfo.mAccessibilityFetchFlags
8740                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8741                    || isImportantForAccessibility();
8742        }
8743        return false;
8744    }
8745
8746    /**
8747     * Returns whether the View is considered actionable from
8748     * accessibility perspective. Such view are important for
8749     * accessibility.
8750     *
8751     * @return True if the view is actionable for accessibility.
8752     *
8753     * @hide
8754     */
8755    public boolean isActionableForAccessibility() {
8756        return (isClickable() || isLongClickable() || isFocusable());
8757    }
8758
8759    /**
8760     * Returns whether the View has registered callbacks which makes it
8761     * important for accessibility.
8762     *
8763     * @return True if the view is actionable for accessibility.
8764     */
8765    private boolean hasListenersForAccessibility() {
8766        ListenerInfo info = getListenerInfo();
8767        return mTouchDelegate != null || info.mOnKeyListener != null
8768                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8769                || info.mOnHoverListener != null || info.mOnDragListener != null;
8770    }
8771
8772    /**
8773     * Notifies that the accessibility state of this view changed. The change
8774     * is local to this view and does not represent structural changes such
8775     * as children and parent. For example, the view became focusable. The
8776     * notification is at at most once every
8777     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8778     * to avoid unnecessary load to the system. Also once a view has a pending
8779     * notification this method is a NOP until the notification has been sent.
8780     *
8781     * @hide
8782     */
8783    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8784        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8785            return;
8786        }
8787        if (mSendViewStateChangedAccessibilityEvent == null) {
8788            mSendViewStateChangedAccessibilityEvent =
8789                    new SendViewStateChangedAccessibilityEvent();
8790        }
8791        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8792    }
8793
8794    /**
8795     * Notifies that the accessibility state of this view changed. The change
8796     * is *not* local to this view and does represent structural changes such
8797     * as children and parent. For example, the view size changed. The
8798     * notification is at at most once every
8799     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8800     * to avoid unnecessary load to the system. Also once a view has a pending
8801     * notification this method is a NOP until the notification has been sent.
8802     *
8803     * @hide
8804     */
8805    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8806        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8807            return;
8808        }
8809        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8810            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8811            if (mParent != null) {
8812                try {
8813                    mParent.notifySubtreeAccessibilityStateChanged(
8814                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8815                } catch (AbstractMethodError e) {
8816                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8817                            " does not fully implement ViewParent", e);
8818                }
8819            }
8820        }
8821    }
8822
8823    /**
8824     * Change the visibility of the View without triggering any other changes. This is
8825     * important for transitions, where visibility changes should not adjust focus or
8826     * trigger a new layout. This is only used when the visibility has already been changed
8827     * and we need a transient value during an animation. When the animation completes,
8828     * the original visibility value is always restored.
8829     *
8830     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8831     * @hide
8832     */
8833    public void setTransitionVisibility(@Visibility int visibility) {
8834        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
8835    }
8836
8837    /**
8838     * Reset the flag indicating the accessibility state of the subtree rooted
8839     * at this view changed.
8840     */
8841    void resetSubtreeAccessibilityStateChanged() {
8842        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8843    }
8844
8845    /**
8846     * Report an accessibility action to this view's parents for delegated processing.
8847     *
8848     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8849     * call this method to delegate an accessibility action to a supporting parent. If the parent
8850     * returns true from its
8851     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8852     * method this method will return true to signify that the action was consumed.</p>
8853     *
8854     * <p>This method is useful for implementing nested scrolling child views. If
8855     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8856     * a custom view implementation may invoke this method to allow a parent to consume the
8857     * scroll first. If this method returns true the custom view should skip its own scrolling
8858     * behavior.</p>
8859     *
8860     * @param action Accessibility action to delegate
8861     * @param arguments Optional action arguments
8862     * @return true if the action was consumed by a parent
8863     */
8864    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8865        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8866            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8867                return true;
8868            }
8869        }
8870        return false;
8871    }
8872
8873    /**
8874     * Performs the specified accessibility action on the view. For
8875     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8876     * <p>
8877     * If an {@link AccessibilityDelegate} has been specified via calling
8878     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8879     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8880     * is responsible for handling this call.
8881     * </p>
8882     *
8883     * <p>The default implementation will delegate
8884     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8885     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8886     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8887     *
8888     * @param action The action to perform.
8889     * @param arguments Optional action arguments.
8890     * @return Whether the action was performed.
8891     */
8892    public boolean performAccessibilityAction(int action, Bundle arguments) {
8893      if (mAccessibilityDelegate != null) {
8894          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8895      } else {
8896          return performAccessibilityActionInternal(action, arguments);
8897      }
8898    }
8899
8900   /**
8901    * @see #performAccessibilityAction(int, Bundle)
8902    *
8903    * Note: Called from the default {@link AccessibilityDelegate}.
8904    *
8905    * @hide
8906    */
8907    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8908        if (isNestedScrollingEnabled()
8909                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8910                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
8911                || action == R.id.accessibilityActionScrollUp
8912                || action == R.id.accessibilityActionScrollLeft
8913                || action == R.id.accessibilityActionScrollDown
8914                || action == R.id.accessibilityActionScrollRight)) {
8915            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8916                return true;
8917            }
8918        }
8919
8920        switch (action) {
8921            case AccessibilityNodeInfo.ACTION_CLICK: {
8922                if (isClickable()) {
8923                    performClick();
8924                    return true;
8925                }
8926            } break;
8927            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8928                if (isLongClickable()) {
8929                    performLongClick();
8930                    return true;
8931                }
8932            } break;
8933            case AccessibilityNodeInfo.ACTION_FOCUS: {
8934                if (!hasFocus()) {
8935                    // Get out of touch mode since accessibility
8936                    // wants to move focus around.
8937                    getViewRootImpl().ensureTouchMode(false);
8938                    return requestFocus();
8939                }
8940            } break;
8941            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8942                if (hasFocus()) {
8943                    clearFocus();
8944                    return !isFocused();
8945                }
8946            } break;
8947            case AccessibilityNodeInfo.ACTION_SELECT: {
8948                if (!isSelected()) {
8949                    setSelected(true);
8950                    return isSelected();
8951                }
8952            } break;
8953            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8954                if (isSelected()) {
8955                    setSelected(false);
8956                    return !isSelected();
8957                }
8958            } break;
8959            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8960                if (!isAccessibilityFocused()) {
8961                    return requestAccessibilityFocus();
8962                }
8963            } break;
8964            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8965                if (isAccessibilityFocused()) {
8966                    clearAccessibilityFocus();
8967                    return true;
8968                }
8969            } break;
8970            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8971                if (arguments != null) {
8972                    final int granularity = arguments.getInt(
8973                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8974                    final boolean extendSelection = arguments.getBoolean(
8975                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8976                    return traverseAtGranularity(granularity, true, extendSelection);
8977                }
8978            } break;
8979            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8980                if (arguments != null) {
8981                    final int granularity = arguments.getInt(
8982                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8983                    final boolean extendSelection = arguments.getBoolean(
8984                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8985                    return traverseAtGranularity(granularity, false, extendSelection);
8986                }
8987            } break;
8988            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8989                CharSequence text = getIterableTextForAccessibility();
8990                if (text == null) {
8991                    return false;
8992                }
8993                final int start = (arguments != null) ? arguments.getInt(
8994                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8995                final int end = (arguments != null) ? arguments.getInt(
8996                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8997                // Only cursor position can be specified (selection length == 0)
8998                if ((getAccessibilitySelectionStart() != start
8999                        || getAccessibilitySelectionEnd() != end)
9000                        && (start == end)) {
9001                    setAccessibilitySelection(start, end);
9002                    notifyViewAccessibilityStateChangedIfNeeded(
9003                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9004                    return true;
9005                }
9006            } break;
9007            case R.id.accessibilityActionShowOnScreen: {
9008                if (mAttachInfo != null) {
9009                    final Rect r = mAttachInfo.mTmpInvalRect;
9010                    getDrawingRect(r);
9011                    return requestRectangleOnScreen(r, true);
9012                }
9013            } break;
9014            case R.id.accessibilityActionContextClick: {
9015                if (isContextClickable()) {
9016                    performContextClick();
9017                    return true;
9018                }
9019            } break;
9020        }
9021        return false;
9022    }
9023
9024    private boolean traverseAtGranularity(int granularity, boolean forward,
9025            boolean extendSelection) {
9026        CharSequence text = getIterableTextForAccessibility();
9027        if (text == null || text.length() == 0) {
9028            return false;
9029        }
9030        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9031        if (iterator == null) {
9032            return false;
9033        }
9034        int current = getAccessibilitySelectionEnd();
9035        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9036            current = forward ? 0 : text.length();
9037        }
9038        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9039        if (range == null) {
9040            return false;
9041        }
9042        final int segmentStart = range[0];
9043        final int segmentEnd = range[1];
9044        int selectionStart;
9045        int selectionEnd;
9046        if (extendSelection && isAccessibilitySelectionExtendable()) {
9047            selectionStart = getAccessibilitySelectionStart();
9048            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9049                selectionStart = forward ? segmentStart : segmentEnd;
9050            }
9051            selectionEnd = forward ? segmentEnd : segmentStart;
9052        } else {
9053            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9054        }
9055        setAccessibilitySelection(selectionStart, selectionEnd);
9056        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9057                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9058        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9059        return true;
9060    }
9061
9062    /**
9063     * Gets the text reported for accessibility purposes.
9064     *
9065     * @return The accessibility text.
9066     *
9067     * @hide
9068     */
9069    public CharSequence getIterableTextForAccessibility() {
9070        return getContentDescription();
9071    }
9072
9073    /**
9074     * Gets whether accessibility selection can be extended.
9075     *
9076     * @return If selection is extensible.
9077     *
9078     * @hide
9079     */
9080    public boolean isAccessibilitySelectionExtendable() {
9081        return false;
9082    }
9083
9084    /**
9085     * @hide
9086     */
9087    public int getAccessibilitySelectionStart() {
9088        return mAccessibilityCursorPosition;
9089    }
9090
9091    /**
9092     * @hide
9093     */
9094    public int getAccessibilitySelectionEnd() {
9095        return getAccessibilitySelectionStart();
9096    }
9097
9098    /**
9099     * @hide
9100     */
9101    public void setAccessibilitySelection(int start, int end) {
9102        if (start ==  end && end == mAccessibilityCursorPosition) {
9103            return;
9104        }
9105        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9106            mAccessibilityCursorPosition = start;
9107        } else {
9108            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9109        }
9110        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9111    }
9112
9113    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9114            int fromIndex, int toIndex) {
9115        if (mParent == null) {
9116            return;
9117        }
9118        AccessibilityEvent event = AccessibilityEvent.obtain(
9119                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9120        onInitializeAccessibilityEvent(event);
9121        onPopulateAccessibilityEvent(event);
9122        event.setFromIndex(fromIndex);
9123        event.setToIndex(toIndex);
9124        event.setAction(action);
9125        event.setMovementGranularity(granularity);
9126        mParent.requestSendAccessibilityEvent(this, event);
9127    }
9128
9129    /**
9130     * @hide
9131     */
9132    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9133        switch (granularity) {
9134            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9135                CharSequence text = getIterableTextForAccessibility();
9136                if (text != null && text.length() > 0) {
9137                    CharacterTextSegmentIterator iterator =
9138                        CharacterTextSegmentIterator.getInstance(
9139                                mContext.getResources().getConfiguration().locale);
9140                    iterator.initialize(text.toString());
9141                    return iterator;
9142                }
9143            } break;
9144            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9145                CharSequence text = getIterableTextForAccessibility();
9146                if (text != null && text.length() > 0) {
9147                    WordTextSegmentIterator iterator =
9148                        WordTextSegmentIterator.getInstance(
9149                                mContext.getResources().getConfiguration().locale);
9150                    iterator.initialize(text.toString());
9151                    return iterator;
9152                }
9153            } break;
9154            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9155                CharSequence text = getIterableTextForAccessibility();
9156                if (text != null && text.length() > 0) {
9157                    ParagraphTextSegmentIterator iterator =
9158                        ParagraphTextSegmentIterator.getInstance();
9159                    iterator.initialize(text.toString());
9160                    return iterator;
9161                }
9162            } break;
9163        }
9164        return null;
9165    }
9166
9167    /**
9168     * @hide
9169     */
9170    public void dispatchStartTemporaryDetach() {
9171        onStartTemporaryDetach();
9172    }
9173
9174    /**
9175     * This is called when a container is going to temporarily detach a child, with
9176     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9177     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9178     * {@link #onDetachedFromWindow()} when the container is done.
9179     */
9180    public void onStartTemporaryDetach() {
9181        removeUnsetPressCallback();
9182        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9183    }
9184
9185    /**
9186     * @hide
9187     */
9188    public void dispatchFinishTemporaryDetach() {
9189        onFinishTemporaryDetach();
9190    }
9191
9192    /**
9193     * Called after {@link #onStartTemporaryDetach} when the container is done
9194     * changing the view.
9195     */
9196    public void onFinishTemporaryDetach() {
9197    }
9198
9199    /**
9200     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9201     * for this view's window.  Returns null if the view is not currently attached
9202     * to the window.  Normally you will not need to use this directly, but
9203     * just use the standard high-level event callbacks like
9204     * {@link #onKeyDown(int, KeyEvent)}.
9205     */
9206    public KeyEvent.DispatcherState getKeyDispatcherState() {
9207        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9208    }
9209
9210    /**
9211     * Dispatch a key event before it is processed by any input method
9212     * associated with the view hierarchy.  This can be used to intercept
9213     * key events in special situations before the IME consumes them; a
9214     * typical example would be handling the BACK key to update the application's
9215     * UI instead of allowing the IME to see it and close itself.
9216     *
9217     * @param event The key event to be dispatched.
9218     * @return True if the event was handled, false otherwise.
9219     */
9220    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9221        return onKeyPreIme(event.getKeyCode(), event);
9222    }
9223
9224    /**
9225     * Dispatch a key event to the next view on the focus path. This path runs
9226     * from the top of the view tree down to the currently focused view. If this
9227     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9228     * the next node down the focus path. This method also fires any key
9229     * listeners.
9230     *
9231     * @param event The key event to be dispatched.
9232     * @return True if the event was handled, false otherwise.
9233     */
9234    public boolean dispatchKeyEvent(KeyEvent event) {
9235        if (mInputEventConsistencyVerifier != null) {
9236            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9237        }
9238
9239        // Give any attached key listener a first crack at the event.
9240        //noinspection SimplifiableIfStatement
9241        ListenerInfo li = mListenerInfo;
9242        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9243                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9244            return true;
9245        }
9246
9247        if (event.dispatch(this, mAttachInfo != null
9248                ? mAttachInfo.mKeyDispatchState : null, this)) {
9249            return true;
9250        }
9251
9252        if (mInputEventConsistencyVerifier != null) {
9253            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9254        }
9255        return false;
9256    }
9257
9258    /**
9259     * Dispatches a key shortcut event.
9260     *
9261     * @param event The key event to be dispatched.
9262     * @return True if the event was handled by the view, false otherwise.
9263     */
9264    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9265        return onKeyShortcut(event.getKeyCode(), event);
9266    }
9267
9268    /**
9269     * Pass the touch screen motion event down to the target view, or this
9270     * view if it is the target.
9271     *
9272     * @param event The motion event to be dispatched.
9273     * @return True if the event was handled by the view, false otherwise.
9274     */
9275    public boolean dispatchTouchEvent(MotionEvent event) {
9276        // If the event should be handled by accessibility focus first.
9277        if (event.isTargetAccessibilityFocus()) {
9278            // We don't have focus or no virtual descendant has it, do not handle the event.
9279            if (!isAccessibilityFocusedViewOrHost()) {
9280                return false;
9281            }
9282            // We have focus and got the event, then use normal event dispatch.
9283            event.setTargetAccessibilityFocus(false);
9284        }
9285
9286        boolean result = false;
9287
9288        if (mInputEventConsistencyVerifier != null) {
9289            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9290        }
9291
9292        final int actionMasked = event.getActionMasked();
9293        if (actionMasked == MotionEvent.ACTION_DOWN) {
9294            // Defensive cleanup for new gesture
9295            stopNestedScroll();
9296        }
9297
9298        if (onFilterTouchEventForSecurity(event)) {
9299            //noinspection SimplifiableIfStatement
9300            ListenerInfo li = mListenerInfo;
9301            if (li != null && li.mOnTouchListener != null
9302                    && (mViewFlags & ENABLED_MASK) == ENABLED
9303                    && li.mOnTouchListener.onTouch(this, event)) {
9304                result = true;
9305            }
9306
9307            if (!result && onTouchEvent(event)) {
9308                result = true;
9309            }
9310        }
9311
9312        if (!result && mInputEventConsistencyVerifier != null) {
9313            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9314        }
9315
9316        // Clean up after nested scrolls if this is the end of a gesture;
9317        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9318        // of the gesture.
9319        if (actionMasked == MotionEvent.ACTION_UP ||
9320                actionMasked == MotionEvent.ACTION_CANCEL ||
9321                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9322            stopNestedScroll();
9323        }
9324
9325        return result;
9326    }
9327
9328    boolean isAccessibilityFocusedViewOrHost() {
9329        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9330                .getAccessibilityFocusedHost() == this);
9331    }
9332
9333    /**
9334     * Filter the touch event to apply security policies.
9335     *
9336     * @param event The motion event to be filtered.
9337     * @return True if the event should be dispatched, false if the event should be dropped.
9338     *
9339     * @see #getFilterTouchesWhenObscured
9340     */
9341    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9342        //noinspection RedundantIfStatement
9343        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9344                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9345            // Window is obscured, drop this touch.
9346            return false;
9347        }
9348        return true;
9349    }
9350
9351    /**
9352     * Pass a trackball motion event down to the focused view.
9353     *
9354     * @param event The motion event to be dispatched.
9355     * @return True if the event was handled by the view, false otherwise.
9356     */
9357    public boolean dispatchTrackballEvent(MotionEvent event) {
9358        if (mInputEventConsistencyVerifier != null) {
9359            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9360        }
9361
9362        return onTrackballEvent(event);
9363    }
9364
9365    /**
9366     * Dispatch a generic motion event.
9367     * <p>
9368     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9369     * are delivered to the view under the pointer.  All other generic motion events are
9370     * delivered to the focused view.  Hover events are handled specially and are delivered
9371     * to {@link #onHoverEvent(MotionEvent)}.
9372     * </p>
9373     *
9374     * @param event The motion event to be dispatched.
9375     * @return True if the event was handled by the view, false otherwise.
9376     */
9377    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9378        if (mInputEventConsistencyVerifier != null) {
9379            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9380        }
9381
9382        final int source = event.getSource();
9383        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9384            final int action = event.getAction();
9385            if (action == MotionEvent.ACTION_HOVER_ENTER
9386                    || action == MotionEvent.ACTION_HOVER_MOVE
9387                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9388                if (dispatchHoverEvent(event)) {
9389                    return true;
9390                }
9391            } else if (dispatchGenericPointerEvent(event)) {
9392                return true;
9393            }
9394        } else if (dispatchGenericFocusedEvent(event)) {
9395            return true;
9396        }
9397
9398        if (dispatchGenericMotionEventInternal(event)) {
9399            return true;
9400        }
9401
9402        if (mInputEventConsistencyVerifier != null) {
9403            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9404        }
9405        return false;
9406    }
9407
9408    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9409        //noinspection SimplifiableIfStatement
9410        ListenerInfo li = mListenerInfo;
9411        if (li != null && li.mOnGenericMotionListener != null
9412                && (mViewFlags & ENABLED_MASK) == ENABLED
9413                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9414            return true;
9415        }
9416
9417        if (onGenericMotionEvent(event)) {
9418            return true;
9419        }
9420
9421        final int actionButton = event.getActionButton();
9422        switch (event.getActionMasked()) {
9423            case MotionEvent.ACTION_BUTTON_PRESS:
9424                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9425                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9426                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9427                    if (performContextClick()) {
9428                        mInContextButtonPress = true;
9429                        setPressed(true, event.getX(), event.getY());
9430                        removeTapCallback();
9431                        removeLongPressCallback();
9432                        return true;
9433                    }
9434                }
9435                break;
9436
9437            case MotionEvent.ACTION_BUTTON_RELEASE:
9438                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9439                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9440                    mInContextButtonPress = false;
9441                    mIgnoreNextUpEvent = true;
9442                }
9443                break;
9444        }
9445
9446        if (mInputEventConsistencyVerifier != null) {
9447            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9448        }
9449        return false;
9450    }
9451
9452    /**
9453     * Dispatch a hover event.
9454     * <p>
9455     * Do not call this method directly.
9456     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9457     * </p>
9458     *
9459     * @param event The motion event to be dispatched.
9460     * @return True if the event was handled by the view, false otherwise.
9461     */
9462    protected boolean dispatchHoverEvent(MotionEvent event) {
9463        ListenerInfo li = mListenerInfo;
9464        //noinspection SimplifiableIfStatement
9465        if (li != null && li.mOnHoverListener != null
9466                && (mViewFlags & ENABLED_MASK) == ENABLED
9467                && li.mOnHoverListener.onHover(this, event)) {
9468            return true;
9469        }
9470
9471        return onHoverEvent(event);
9472    }
9473
9474    /**
9475     * Returns true if the view has a child to which it has recently sent
9476     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9477     * it does not have a hovered child, then it must be the innermost hovered view.
9478     * @hide
9479     */
9480    protected boolean hasHoveredChild() {
9481        return false;
9482    }
9483
9484    /**
9485     * Dispatch a generic motion event to the view under the first pointer.
9486     * <p>
9487     * Do not call this method directly.
9488     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9489     * </p>
9490     *
9491     * @param event The motion event to be dispatched.
9492     * @return True if the event was handled by the view, false otherwise.
9493     */
9494    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9495        return false;
9496    }
9497
9498    /**
9499     * Dispatch a generic motion event to the currently focused view.
9500     * <p>
9501     * Do not call this method directly.
9502     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9503     * </p>
9504     *
9505     * @param event The motion event to be dispatched.
9506     * @return True if the event was handled by the view, false otherwise.
9507     */
9508    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9509        return false;
9510    }
9511
9512    /**
9513     * Dispatch a pointer event.
9514     * <p>
9515     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9516     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9517     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9518     * and should not be expected to handle other pointing device features.
9519     * </p>
9520     *
9521     * @param event The motion event to be dispatched.
9522     * @return True if the event was handled by the view, false otherwise.
9523     * @hide
9524     */
9525    public final boolean dispatchPointerEvent(MotionEvent event) {
9526        if (event.isTouchEvent()) {
9527            return dispatchTouchEvent(event);
9528        } else {
9529            return dispatchGenericMotionEvent(event);
9530        }
9531    }
9532
9533    /**
9534     * Called when the window containing this view gains or loses window focus.
9535     * ViewGroups should override to route to their children.
9536     *
9537     * @param hasFocus True if the window containing this view now has focus,
9538     *        false otherwise.
9539     */
9540    public void dispatchWindowFocusChanged(boolean hasFocus) {
9541        onWindowFocusChanged(hasFocus);
9542    }
9543
9544    /**
9545     * Called when the window containing this view gains or loses focus.  Note
9546     * that this is separate from view focus: to receive key events, both
9547     * your view and its window must have focus.  If a window is displayed
9548     * on top of yours that takes input focus, then your own window will lose
9549     * focus but the view focus will remain unchanged.
9550     *
9551     * @param hasWindowFocus True if the window containing this view now has
9552     *        focus, false otherwise.
9553     */
9554    public void onWindowFocusChanged(boolean hasWindowFocus) {
9555        InputMethodManager imm = InputMethodManager.peekInstance();
9556        if (!hasWindowFocus) {
9557            if (isPressed()) {
9558                setPressed(false);
9559            }
9560            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9561                imm.focusOut(this);
9562            }
9563            removeLongPressCallback();
9564            removeTapCallback();
9565            onFocusLost();
9566        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9567            imm.focusIn(this);
9568        }
9569        refreshDrawableState();
9570    }
9571
9572    /**
9573     * Returns true if this view is in a window that currently has window focus.
9574     * Note that this is not the same as the view itself having focus.
9575     *
9576     * @return True if this view is in a window that currently has window focus.
9577     */
9578    public boolean hasWindowFocus() {
9579        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9580    }
9581
9582    /**
9583     * Dispatch a view visibility change down the view hierarchy.
9584     * ViewGroups should override to route to their children.
9585     * @param changedView The view whose visibility changed. Could be 'this' or
9586     * an ancestor view.
9587     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9588     * {@link #INVISIBLE} or {@link #GONE}.
9589     */
9590    protected void dispatchVisibilityChanged(@NonNull View changedView,
9591            @Visibility int visibility) {
9592        onVisibilityChanged(changedView, visibility);
9593    }
9594
9595    /**
9596     * Called when the visibility of the view or an ancestor of the view has
9597     * changed.
9598     *
9599     * @param changedView The view whose visibility changed. May be
9600     *                    {@code this} or an ancestor view.
9601     * @param visibility The new visibility, one of {@link #VISIBLE},
9602     *                   {@link #INVISIBLE} or {@link #GONE}.
9603     */
9604    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9605        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9606        if (visible && mAttachInfo != null) {
9607            initialAwakenScrollBars();
9608        }
9609
9610        final Drawable dr = mBackground;
9611        if (dr != null && visible != dr.isVisible()) {
9612            dr.setVisible(visible, false);
9613        }
9614        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9615        if (fg != null && visible != fg.isVisible()) {
9616            fg.setVisible(visible, false);
9617        }
9618    }
9619
9620    /**
9621     * Dispatch a hint about whether this view is displayed. For instance, when
9622     * a View moves out of the screen, it might receives a display hint indicating
9623     * the view is not displayed. Applications should not <em>rely</em> on this hint
9624     * as there is no guarantee that they will receive one.
9625     *
9626     * @param hint A hint about whether or not this view is displayed:
9627     * {@link #VISIBLE} or {@link #INVISIBLE}.
9628     */
9629    public void dispatchDisplayHint(@Visibility int hint) {
9630        onDisplayHint(hint);
9631    }
9632
9633    /**
9634     * Gives this view a hint about whether is displayed or not. For instance, when
9635     * a View moves out of the screen, it might receives a display hint indicating
9636     * the view is not displayed. Applications should not <em>rely</em> on this hint
9637     * as there is no guarantee that they will receive one.
9638     *
9639     * @param hint A hint about whether or not this view is displayed:
9640     * {@link #VISIBLE} or {@link #INVISIBLE}.
9641     */
9642    protected void onDisplayHint(@Visibility int hint) {
9643    }
9644
9645    /**
9646     * Dispatch a window visibility change down the view hierarchy.
9647     * ViewGroups should override to route to their children.
9648     *
9649     * @param visibility The new visibility of the window.
9650     *
9651     * @see #onWindowVisibilityChanged(int)
9652     */
9653    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9654        onWindowVisibilityChanged(visibility);
9655    }
9656
9657    /**
9658     * Called when the window containing has change its visibility
9659     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9660     * that this tells you whether or not your window is being made visible
9661     * to the window manager; this does <em>not</em> tell you whether or not
9662     * your window is obscured by other windows on the screen, even if it
9663     * is itself visible.
9664     *
9665     * @param visibility The new visibility of the window.
9666     */
9667    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9668        if (visibility == VISIBLE) {
9669            initialAwakenScrollBars();
9670        }
9671    }
9672
9673    /**
9674     * Returns the current visibility of the window this view is attached to
9675     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9676     *
9677     * @return Returns the current visibility of the view's window.
9678     */
9679    @Visibility
9680    public int getWindowVisibility() {
9681        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9682    }
9683
9684    /**
9685     * Retrieve the overall visible display size in which the window this view is
9686     * attached to has been positioned in.  This takes into account screen
9687     * decorations above the window, for both cases where the window itself
9688     * is being position inside of them or the window is being placed under
9689     * then and covered insets are used for the window to position its content
9690     * inside.  In effect, this tells you the available area where content can
9691     * be placed and remain visible to users.
9692     *
9693     * <p>This function requires an IPC back to the window manager to retrieve
9694     * the requested information, so should not be used in performance critical
9695     * code like drawing.
9696     *
9697     * @param outRect Filled in with the visible display frame.  If the view
9698     * is not attached to a window, this is simply the raw display size.
9699     */
9700    public void getWindowVisibleDisplayFrame(Rect outRect) {
9701        if (mAttachInfo != null) {
9702            try {
9703                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9704            } catch (RemoteException e) {
9705                return;
9706            }
9707            // XXX This is really broken, and probably all needs to be done
9708            // in the window manager, and we need to know more about whether
9709            // we want the area behind or in front of the IME.
9710            final Rect insets = mAttachInfo.mVisibleInsets;
9711            outRect.left += insets.left;
9712            outRect.top += insets.top;
9713            outRect.right -= insets.right;
9714            outRect.bottom -= insets.bottom;
9715            return;
9716        }
9717        // The view is not attached to a display so we don't have a context.
9718        // Make a best guess about the display size.
9719        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9720        d.getRectSize(outRect);
9721    }
9722
9723    /**
9724     * Dispatch a notification about a resource configuration change down
9725     * the view hierarchy.
9726     * ViewGroups should override to route to their children.
9727     *
9728     * @param newConfig The new resource configuration.
9729     *
9730     * @see #onConfigurationChanged(android.content.res.Configuration)
9731     */
9732    public void dispatchConfigurationChanged(Configuration newConfig) {
9733        onConfigurationChanged(newConfig);
9734    }
9735
9736    /**
9737     * Called when the current configuration of the resources being used
9738     * by the application have changed.  You can use this to decide when
9739     * to reload resources that can changed based on orientation and other
9740     * configuration characteristics.  You only need to use this if you are
9741     * not relying on the normal {@link android.app.Activity} mechanism of
9742     * recreating the activity instance upon a configuration change.
9743     *
9744     * @param newConfig The new resource configuration.
9745     */
9746    protected void onConfigurationChanged(Configuration newConfig) {
9747    }
9748
9749    /**
9750     * Private function to aggregate all per-view attributes in to the view
9751     * root.
9752     */
9753    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9754        performCollectViewAttributes(attachInfo, visibility);
9755    }
9756
9757    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9758        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9759            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9760                attachInfo.mKeepScreenOn = true;
9761            }
9762            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9763            ListenerInfo li = mListenerInfo;
9764            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9765                attachInfo.mHasSystemUiListeners = true;
9766            }
9767        }
9768    }
9769
9770    void needGlobalAttributesUpdate(boolean force) {
9771        final AttachInfo ai = mAttachInfo;
9772        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9773            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9774                    || ai.mHasSystemUiListeners) {
9775                ai.mRecomputeGlobalAttributes = true;
9776            }
9777        }
9778    }
9779
9780    /**
9781     * Returns whether the device is currently in touch mode.  Touch mode is entered
9782     * once the user begins interacting with the device by touch, and affects various
9783     * things like whether focus is always visible to the user.
9784     *
9785     * @return Whether the device is in touch mode.
9786     */
9787    @ViewDebug.ExportedProperty
9788    public boolean isInTouchMode() {
9789        if (mAttachInfo != null) {
9790            return mAttachInfo.mInTouchMode;
9791        } else {
9792            return ViewRootImpl.isInTouchMode();
9793        }
9794    }
9795
9796    /**
9797     * Returns the context the view is running in, through which it can
9798     * access the current theme, resources, etc.
9799     *
9800     * @return The view's Context.
9801     */
9802    @ViewDebug.CapturedViewProperty
9803    public final Context getContext() {
9804        return mContext;
9805    }
9806
9807    /**
9808     * Handle a key event before it is processed by any input method
9809     * associated with the view hierarchy.  This can be used to intercept
9810     * key events in special situations before the IME consumes them; a
9811     * typical example would be handling the BACK key to update the application's
9812     * UI instead of allowing the IME to see it and close itself.
9813     *
9814     * @param keyCode The value in event.getKeyCode().
9815     * @param event Description of the key event.
9816     * @return If you handled the event, return true. If you want to allow the
9817     *         event to be handled by the next receiver, return false.
9818     */
9819    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9820        return false;
9821    }
9822
9823    /**
9824     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9825     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9826     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9827     * is released, if the view is enabled and clickable.
9828     *
9829     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9830     * although some may elect to do so in some situations. Do not rely on this to
9831     * catch software key presses.
9832     *
9833     * @param keyCode A key code that represents the button pressed, from
9834     *                {@link android.view.KeyEvent}.
9835     * @param event   The KeyEvent object that defines the button action.
9836     */
9837    public boolean onKeyDown(int keyCode, KeyEvent event) {
9838        boolean result = false;
9839
9840        if (KeyEvent.isConfirmKey(keyCode)) {
9841            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9842                return true;
9843            }
9844            // Long clickable items don't necessarily have to be clickable
9845            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9846                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9847                    (event.getRepeatCount() == 0)) {
9848                setPressed(true);
9849                checkForLongClick(0);
9850                return true;
9851            }
9852        }
9853        return result;
9854    }
9855
9856    /**
9857     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9858     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9859     * the event).
9860     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9861     * although some may elect to do so in some situations. Do not rely on this to
9862     * catch software key presses.
9863     */
9864    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9865        return false;
9866    }
9867
9868    /**
9869     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9870     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9871     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9872     * {@link KeyEvent#KEYCODE_ENTER} is released.
9873     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9874     * although some may elect to do so in some situations. Do not rely on this to
9875     * catch software key presses.
9876     *
9877     * @param keyCode A key code that represents the button pressed, from
9878     *                {@link android.view.KeyEvent}.
9879     * @param event   The KeyEvent object that defines the button action.
9880     */
9881    public boolean onKeyUp(int keyCode, KeyEvent event) {
9882        if (KeyEvent.isConfirmKey(keyCode)) {
9883            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9884                return true;
9885            }
9886            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9887                setPressed(false);
9888
9889                if (!mHasPerformedLongPress) {
9890                    // This is a tap, so remove the longpress check
9891                    removeLongPressCallback();
9892                    return performClick();
9893                }
9894            }
9895        }
9896        return false;
9897    }
9898
9899    /**
9900     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9901     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9902     * the event).
9903     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9904     * although some may elect to do so in some situations. Do not rely on this to
9905     * catch software key presses.
9906     *
9907     * @param keyCode     A key code that represents the button pressed, from
9908     *                    {@link android.view.KeyEvent}.
9909     * @param repeatCount The number of times the action was made.
9910     * @param event       The KeyEvent object that defines the button action.
9911     */
9912    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9913        return false;
9914    }
9915
9916    /**
9917     * Called on the focused view when a key shortcut event is not handled.
9918     * Override this method to implement local key shortcuts for the View.
9919     * Key shortcuts can also be implemented by setting the
9920     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9921     *
9922     * @param keyCode The value in event.getKeyCode().
9923     * @param event Description of the key event.
9924     * @return If you handled the event, return true. If you want to allow the
9925     *         event to be handled by the next receiver, return false.
9926     */
9927    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9928        return false;
9929    }
9930
9931    /**
9932     * Check whether the called view is a text editor, in which case it
9933     * would make sense to automatically display a soft input window for
9934     * it.  Subclasses should override this if they implement
9935     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9936     * a call on that method would return a non-null InputConnection, and
9937     * they are really a first-class editor that the user would normally
9938     * start typing on when the go into a window containing your view.
9939     *
9940     * <p>The default implementation always returns false.  This does
9941     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9942     * will not be called or the user can not otherwise perform edits on your
9943     * view; it is just a hint to the system that this is not the primary
9944     * purpose of this view.
9945     *
9946     * @return Returns true if this view is a text editor, else false.
9947     */
9948    public boolean onCheckIsTextEditor() {
9949        return false;
9950    }
9951
9952    /**
9953     * Create a new InputConnection for an InputMethod to interact
9954     * with the view.  The default implementation returns null, since it doesn't
9955     * support input methods.  You can override this to implement such support.
9956     * This is only needed for views that take focus and text input.
9957     *
9958     * <p>When implementing this, you probably also want to implement
9959     * {@link #onCheckIsTextEditor()} to indicate you will return a
9960     * non-null InputConnection.</p>
9961     *
9962     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9963     * object correctly and in its entirety, so that the connected IME can rely
9964     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9965     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9966     * must be filled in with the correct cursor position for IMEs to work correctly
9967     * with your application.</p>
9968     *
9969     * @param outAttrs Fill in with attribute information about the connection.
9970     */
9971    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9972        return null;
9973    }
9974
9975    /**
9976     * Called by the {@link android.view.inputmethod.InputMethodManager}
9977     * when a view who is not the current
9978     * input connection target is trying to make a call on the manager.  The
9979     * default implementation returns false; you can override this to return
9980     * true for certain views if you are performing InputConnection proxying
9981     * to them.
9982     * @param view The View that is making the InputMethodManager call.
9983     * @return Return true to allow the call, false to reject.
9984     */
9985    public boolean checkInputConnectionProxy(View view) {
9986        return false;
9987    }
9988
9989    /**
9990     * Show the context menu for this view. It is not safe to hold on to the
9991     * menu after returning from this method.
9992     *
9993     * You should normally not overload this method. Overload
9994     * {@link #onCreateContextMenu(ContextMenu)} or define an
9995     * {@link OnCreateContextMenuListener} to add items to the context menu.
9996     *
9997     * @param menu The context menu to populate
9998     */
9999    public void createContextMenu(ContextMenu menu) {
10000        ContextMenuInfo menuInfo = getContextMenuInfo();
10001
10002        // Sets the current menu info so all items added to menu will have
10003        // my extra info set.
10004        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10005
10006        onCreateContextMenu(menu);
10007        ListenerInfo li = mListenerInfo;
10008        if (li != null && li.mOnCreateContextMenuListener != null) {
10009            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10010        }
10011
10012        // Clear the extra information so subsequent items that aren't mine don't
10013        // have my extra info.
10014        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10015
10016        if (mParent != null) {
10017            mParent.createContextMenu(menu);
10018        }
10019    }
10020
10021    /**
10022     * Views should implement this if they have extra information to associate
10023     * with the context menu. The return result is supplied as a parameter to
10024     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10025     * callback.
10026     *
10027     * @return Extra information about the item for which the context menu
10028     *         should be shown. This information will vary across different
10029     *         subclasses of View.
10030     */
10031    protected ContextMenuInfo getContextMenuInfo() {
10032        return null;
10033    }
10034
10035    /**
10036     * Views should implement this if the view itself is going to add items to
10037     * the context menu.
10038     *
10039     * @param menu the context menu to populate
10040     */
10041    protected void onCreateContextMenu(ContextMenu menu) {
10042    }
10043
10044    /**
10045     * Implement this method to handle trackball motion events.  The
10046     * <em>relative</em> movement of the trackball since the last event
10047     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10048     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10049     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10050     * they will often be fractional values, representing the more fine-grained
10051     * movement information available from a trackball).
10052     *
10053     * @param event The motion event.
10054     * @return True if the event was handled, false otherwise.
10055     */
10056    public boolean onTrackballEvent(MotionEvent event) {
10057        return false;
10058    }
10059
10060    /**
10061     * Implement this method to handle generic motion events.
10062     * <p>
10063     * Generic motion events describe joystick movements, mouse hovers, track pad
10064     * touches, scroll wheel movements and other input events.  The
10065     * {@link MotionEvent#getSource() source} of the motion event specifies
10066     * the class of input that was received.  Implementations of this method
10067     * must examine the bits in the source before processing the event.
10068     * The following code example shows how this is done.
10069     * </p><p>
10070     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10071     * are delivered to the view under the pointer.  All other generic motion events are
10072     * delivered to the focused view.
10073     * </p>
10074     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10075     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10076     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10077     *             // process the joystick movement...
10078     *             return true;
10079     *         }
10080     *     }
10081     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10082     *         switch (event.getAction()) {
10083     *             case MotionEvent.ACTION_HOVER_MOVE:
10084     *                 // process the mouse hover movement...
10085     *                 return true;
10086     *             case MotionEvent.ACTION_SCROLL:
10087     *                 // process the scroll wheel movement...
10088     *                 return true;
10089     *         }
10090     *     }
10091     *     return super.onGenericMotionEvent(event);
10092     * }</pre>
10093     *
10094     * @param event The generic motion event being processed.
10095     * @return True if the event was handled, false otherwise.
10096     */
10097    public boolean onGenericMotionEvent(MotionEvent event) {
10098        return false;
10099    }
10100
10101    /**
10102     * Implement this method to handle hover events.
10103     * <p>
10104     * This method is called whenever a pointer is hovering into, over, or out of the
10105     * bounds of a view and the view is not currently being touched.
10106     * Hover events are represented as pointer events with action
10107     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10108     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10109     * </p>
10110     * <ul>
10111     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10112     * when the pointer enters the bounds of the view.</li>
10113     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10114     * when the pointer has already entered the bounds of the view and has moved.</li>
10115     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10116     * when the pointer has exited the bounds of the view or when the pointer is
10117     * about to go down due to a button click, tap, or similar user action that
10118     * causes the view to be touched.</li>
10119     * </ul>
10120     * <p>
10121     * The view should implement this method to return true to indicate that it is
10122     * handling the hover event, such as by changing its drawable state.
10123     * </p><p>
10124     * The default implementation calls {@link #setHovered} to update the hovered state
10125     * of the view when a hover enter or hover exit event is received, if the view
10126     * is enabled and is clickable.  The default implementation also sends hover
10127     * accessibility events.
10128     * </p>
10129     *
10130     * @param event The motion event that describes the hover.
10131     * @return True if the view handled the hover event.
10132     *
10133     * @see #isHovered
10134     * @see #setHovered
10135     * @see #onHoverChanged
10136     */
10137    public boolean onHoverEvent(MotionEvent event) {
10138        // The root view may receive hover (or touch) events that are outside the bounds of
10139        // the window.  This code ensures that we only send accessibility events for
10140        // hovers that are actually within the bounds of the root view.
10141        final int action = event.getActionMasked();
10142        if (!mSendingHoverAccessibilityEvents) {
10143            if ((action == MotionEvent.ACTION_HOVER_ENTER
10144                    || action == MotionEvent.ACTION_HOVER_MOVE)
10145                    && !hasHoveredChild()
10146                    && pointInView(event.getX(), event.getY())) {
10147                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10148                mSendingHoverAccessibilityEvents = true;
10149            }
10150        } else {
10151            if (action == MotionEvent.ACTION_HOVER_EXIT
10152                    || (action == MotionEvent.ACTION_MOVE
10153                            && !pointInView(event.getX(), event.getY()))) {
10154                mSendingHoverAccessibilityEvents = false;
10155                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10156            }
10157        }
10158
10159        if (isHoverable()) {
10160            switch (action) {
10161                case MotionEvent.ACTION_HOVER_ENTER:
10162                    setHovered(true);
10163                    break;
10164                case MotionEvent.ACTION_HOVER_EXIT:
10165                    setHovered(false);
10166                    break;
10167            }
10168
10169            // Dispatch the event to onGenericMotionEvent before returning true.
10170            // This is to provide compatibility with existing applications that
10171            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10172            // break because of the new default handling for hoverable views
10173            // in onHoverEvent.
10174            // Note that onGenericMotionEvent will be called by default when
10175            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10176            dispatchGenericMotionEventInternal(event);
10177            // The event was already handled by calling setHovered(), so always
10178            // return true.
10179            return true;
10180        }
10181
10182        return false;
10183    }
10184
10185    /**
10186     * Returns true if the view should handle {@link #onHoverEvent}
10187     * by calling {@link #setHovered} to change its hovered state.
10188     *
10189     * @return True if the view is hoverable.
10190     */
10191    private boolean isHoverable() {
10192        final int viewFlags = mViewFlags;
10193        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10194            return false;
10195        }
10196
10197        return (viewFlags & CLICKABLE) == CLICKABLE
10198                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10199                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10200    }
10201
10202    /**
10203     * Returns true if the view is currently hovered.
10204     *
10205     * @return True if the view is currently hovered.
10206     *
10207     * @see #setHovered
10208     * @see #onHoverChanged
10209     */
10210    @ViewDebug.ExportedProperty
10211    public boolean isHovered() {
10212        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10213    }
10214
10215    /**
10216     * Sets whether the view is currently hovered.
10217     * <p>
10218     * Calling this method also changes the drawable state of the view.  This
10219     * enables the view to react to hover by using different drawable resources
10220     * to change its appearance.
10221     * </p><p>
10222     * The {@link #onHoverChanged} method is called when the hovered state changes.
10223     * </p>
10224     *
10225     * @param hovered True if the view is hovered.
10226     *
10227     * @see #isHovered
10228     * @see #onHoverChanged
10229     */
10230    public void setHovered(boolean hovered) {
10231        if (hovered) {
10232            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10233                mPrivateFlags |= PFLAG_HOVERED;
10234                refreshDrawableState();
10235                onHoverChanged(true);
10236            }
10237        } else {
10238            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10239                mPrivateFlags &= ~PFLAG_HOVERED;
10240                refreshDrawableState();
10241                onHoverChanged(false);
10242            }
10243        }
10244    }
10245
10246    /**
10247     * Implement this method to handle hover state changes.
10248     * <p>
10249     * This method is called whenever the hover state changes as a result of a
10250     * call to {@link #setHovered}.
10251     * </p>
10252     *
10253     * @param hovered The current hover state, as returned by {@link #isHovered}.
10254     *
10255     * @see #isHovered
10256     * @see #setHovered
10257     */
10258    public void onHoverChanged(boolean hovered) {
10259    }
10260
10261    /**
10262     * Implement this method to handle touch screen motion events.
10263     * <p>
10264     * If this method is used to detect click actions, it is recommended that
10265     * the actions be performed by implementing and calling
10266     * {@link #performClick()}. This will ensure consistent system behavior,
10267     * including:
10268     * <ul>
10269     * <li>obeying click sound preferences
10270     * <li>dispatching OnClickListener calls
10271     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10272     * accessibility features are enabled
10273     * </ul>
10274     *
10275     * @param event The motion event.
10276     * @return True if the event was handled, false otherwise.
10277     */
10278    public boolean onTouchEvent(MotionEvent event) {
10279        final float x = event.getX();
10280        final float y = event.getY();
10281        final int viewFlags = mViewFlags;
10282        final int action = event.getAction();
10283
10284        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10285            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10286                setPressed(false);
10287            }
10288            // A disabled view that is clickable still consumes the touch
10289            // events, it just doesn't respond to them.
10290            return (((viewFlags & CLICKABLE) == CLICKABLE
10291                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10292                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10293        }
10294
10295        if (mTouchDelegate != null) {
10296            if (mTouchDelegate.onTouchEvent(event)) {
10297                return true;
10298            }
10299        }
10300
10301        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10302                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10303                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10304            switch (action) {
10305                case MotionEvent.ACTION_UP:
10306                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10307                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10308                        // take focus if we don't have it already and we should in
10309                        // touch mode.
10310                        boolean focusTaken = false;
10311                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10312                            focusTaken = requestFocus();
10313                        }
10314
10315                        if (prepressed) {
10316                            // The button is being released before we actually
10317                            // showed it as pressed.  Make it show the pressed
10318                            // state now (before scheduling the click) to ensure
10319                            // the user sees it.
10320                            setPressed(true, x, y);
10321                       }
10322
10323                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10324                            // This is a tap, so remove the longpress check
10325                            removeLongPressCallback();
10326
10327                            // Only perform take click actions if we were in the pressed state
10328                            if (!focusTaken) {
10329                                // Use a Runnable and post this rather than calling
10330                                // performClick directly. This lets other visual state
10331                                // of the view update before click actions start.
10332                                if (mPerformClick == null) {
10333                                    mPerformClick = new PerformClick();
10334                                }
10335                                if (!post(mPerformClick)) {
10336                                    performClick();
10337                                }
10338                            }
10339                        }
10340
10341                        if (mUnsetPressedState == null) {
10342                            mUnsetPressedState = new UnsetPressedState();
10343                        }
10344
10345                        if (prepressed) {
10346                            postDelayed(mUnsetPressedState,
10347                                    ViewConfiguration.getPressedStateDuration());
10348                        } else if (!post(mUnsetPressedState)) {
10349                            // If the post failed, unpress right now
10350                            mUnsetPressedState.run();
10351                        }
10352
10353                        removeTapCallback();
10354                    }
10355                    mIgnoreNextUpEvent = false;
10356                    break;
10357
10358                case MotionEvent.ACTION_DOWN:
10359                    mHasPerformedLongPress = false;
10360
10361                    if (performButtonActionOnTouchDown(event)) {
10362                        break;
10363                    }
10364
10365                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10366                    boolean isInScrollingContainer = isInScrollingContainer();
10367
10368                    // For views inside a scrolling container, delay the pressed feedback for
10369                    // a short period in case this is a scroll.
10370                    if (isInScrollingContainer) {
10371                        mPrivateFlags |= PFLAG_PREPRESSED;
10372                        if (mPendingCheckForTap == null) {
10373                            mPendingCheckForTap = new CheckForTap();
10374                        }
10375                        mPendingCheckForTap.x = event.getX();
10376                        mPendingCheckForTap.y = event.getY();
10377                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10378                    } else {
10379                        // Not inside a scrolling container, so show the feedback right away
10380                        setPressed(true, x, y);
10381                        checkForLongClick(0);
10382                    }
10383                    break;
10384
10385                case MotionEvent.ACTION_CANCEL:
10386                    setPressed(false);
10387                    removeTapCallback();
10388                    removeLongPressCallback();
10389                    mInContextButtonPress = false;
10390                    mHasPerformedLongPress = false;
10391                    mIgnoreNextUpEvent = false;
10392                    break;
10393
10394                case MotionEvent.ACTION_MOVE:
10395                    drawableHotspotChanged(x, y);
10396
10397                    // Be lenient about moving outside of buttons
10398                    if (!pointInView(x, y, mTouchSlop)) {
10399                        // Outside button
10400                        removeTapCallback();
10401                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10402                            // Remove any future long press/tap checks
10403                            removeLongPressCallback();
10404
10405                            setPressed(false);
10406                        }
10407                    }
10408                    break;
10409            }
10410
10411            return true;
10412        }
10413
10414        return false;
10415    }
10416
10417    /**
10418     * @hide
10419     */
10420    public boolean isInScrollingContainer() {
10421        ViewParent p = getParent();
10422        while (p != null && p instanceof ViewGroup) {
10423            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10424                return true;
10425            }
10426            p = p.getParent();
10427        }
10428        return false;
10429    }
10430
10431    /**
10432     * Remove the longpress detection timer.
10433     */
10434    private void removeLongPressCallback() {
10435        if (mPendingCheckForLongPress != null) {
10436          removeCallbacks(mPendingCheckForLongPress);
10437        }
10438    }
10439
10440    /**
10441     * Remove the pending click action
10442     */
10443    private void removePerformClickCallback() {
10444        if (mPerformClick != null) {
10445            removeCallbacks(mPerformClick);
10446        }
10447    }
10448
10449    /**
10450     * Remove the prepress detection timer.
10451     */
10452    private void removeUnsetPressCallback() {
10453        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10454            setPressed(false);
10455            removeCallbacks(mUnsetPressedState);
10456        }
10457    }
10458
10459    /**
10460     * Remove the tap detection timer.
10461     */
10462    private void removeTapCallback() {
10463        if (mPendingCheckForTap != null) {
10464            mPrivateFlags &= ~PFLAG_PREPRESSED;
10465            removeCallbacks(mPendingCheckForTap);
10466        }
10467    }
10468
10469    /**
10470     * Cancels a pending long press.  Your subclass can use this if you
10471     * want the context menu to come up if the user presses and holds
10472     * at the same place, but you don't want it to come up if they press
10473     * and then move around enough to cause scrolling.
10474     */
10475    public void cancelLongPress() {
10476        removeLongPressCallback();
10477
10478        /*
10479         * The prepressed state handled by the tap callback is a display
10480         * construct, but the tap callback will post a long press callback
10481         * less its own timeout. Remove it here.
10482         */
10483        removeTapCallback();
10484    }
10485
10486    /**
10487     * Remove the pending callback for sending a
10488     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10489     */
10490    private void removeSendViewScrolledAccessibilityEventCallback() {
10491        if (mSendViewScrolledAccessibilityEvent != null) {
10492            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10493            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10494        }
10495    }
10496
10497    /**
10498     * Sets the TouchDelegate for this View.
10499     */
10500    public void setTouchDelegate(TouchDelegate delegate) {
10501        mTouchDelegate = delegate;
10502    }
10503
10504    /**
10505     * Gets the TouchDelegate for this View.
10506     */
10507    public TouchDelegate getTouchDelegate() {
10508        return mTouchDelegate;
10509    }
10510
10511    /**
10512     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10513     *
10514     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10515     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10516     * available. This method should only be called for touch events.
10517     *
10518     * <p class="note">This api is not intended for most applications. Buffered dispatch
10519     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10520     * streams will not improve your input latency. Side effects include: increased latency,
10521     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10522     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10523     * you.</p>
10524     */
10525    public final void requestUnbufferedDispatch(MotionEvent event) {
10526        final int action = event.getAction();
10527        if (mAttachInfo == null
10528                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10529                || !event.isTouchEvent()) {
10530            return;
10531        }
10532        mAttachInfo.mUnbufferedDispatchRequested = true;
10533    }
10534
10535    /**
10536     * Set flags controlling behavior of this view.
10537     *
10538     * @param flags Constant indicating the value which should be set
10539     * @param mask Constant indicating the bit range that should be changed
10540     */
10541    void setFlags(int flags, int mask) {
10542        final boolean accessibilityEnabled =
10543                AccessibilityManager.getInstance(mContext).isEnabled();
10544        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10545
10546        int old = mViewFlags;
10547        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10548
10549        int changed = mViewFlags ^ old;
10550        if (changed == 0) {
10551            return;
10552        }
10553        int privateFlags = mPrivateFlags;
10554
10555        /* Check if the FOCUSABLE bit has changed */
10556        if (((changed & FOCUSABLE_MASK) != 0) &&
10557                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10558            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10559                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10560                /* Give up focus if we are no longer focusable */
10561                clearFocus();
10562            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10563                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10564                /*
10565                 * Tell the view system that we are now available to take focus
10566                 * if no one else already has it.
10567                 */
10568                if (mParent != null) mParent.focusableViewAvailable(this);
10569            }
10570        }
10571
10572        final int newVisibility = flags & VISIBILITY_MASK;
10573        if (newVisibility == VISIBLE) {
10574            if ((changed & VISIBILITY_MASK) != 0) {
10575                /*
10576                 * If this view is becoming visible, invalidate it in case it changed while
10577                 * it was not visible. Marking it drawn ensures that the invalidation will
10578                 * go through.
10579                 */
10580                mPrivateFlags |= PFLAG_DRAWN;
10581                invalidate(true);
10582
10583                needGlobalAttributesUpdate(true);
10584
10585                // a view becoming visible is worth notifying the parent
10586                // about in case nothing has focus.  even if this specific view
10587                // isn't focusable, it may contain something that is, so let
10588                // the root view try to give this focus if nothing else does.
10589                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10590                    mParent.focusableViewAvailable(this);
10591                }
10592            }
10593        }
10594
10595        /* Check if the GONE bit has changed */
10596        if ((changed & GONE) != 0) {
10597            needGlobalAttributesUpdate(false);
10598            requestLayout();
10599
10600            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10601                if (hasFocus()) clearFocus();
10602                clearAccessibilityFocus();
10603                destroyDrawingCache();
10604                if (mParent instanceof View) {
10605                    // GONE views noop invalidation, so invalidate the parent
10606                    ((View) mParent).invalidate(true);
10607                }
10608                // Mark the view drawn to ensure that it gets invalidated properly the next
10609                // time it is visible and gets invalidated
10610                mPrivateFlags |= PFLAG_DRAWN;
10611            }
10612            if (mAttachInfo != null) {
10613                mAttachInfo.mViewVisibilityChanged = true;
10614            }
10615        }
10616
10617        /* Check if the VISIBLE bit has changed */
10618        if ((changed & INVISIBLE) != 0) {
10619            needGlobalAttributesUpdate(false);
10620            /*
10621             * If this view is becoming invisible, set the DRAWN flag so that
10622             * the next invalidate() will not be skipped.
10623             */
10624            mPrivateFlags |= PFLAG_DRAWN;
10625
10626            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10627                // root view becoming invisible shouldn't clear focus and accessibility focus
10628                if (getRootView() != this) {
10629                    if (hasFocus()) clearFocus();
10630                    clearAccessibilityFocus();
10631                }
10632            }
10633            if (mAttachInfo != null) {
10634                mAttachInfo.mViewVisibilityChanged = true;
10635            }
10636        }
10637
10638        if ((changed & VISIBILITY_MASK) != 0) {
10639            // If the view is invisible, cleanup its display list to free up resources
10640            if (newVisibility != VISIBLE && mAttachInfo != null) {
10641                cleanupDraw();
10642            }
10643
10644            if (mParent instanceof ViewGroup) {
10645                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10646                        (changed & VISIBILITY_MASK), newVisibility);
10647                ((View) mParent).invalidate(true);
10648            } else if (mParent != null) {
10649                mParent.invalidateChild(this, null);
10650            }
10651
10652            if (mAttachInfo != null) {
10653                dispatchVisibilityChanged(this, newVisibility);
10654                notifySubtreeAccessibilityStateChangedIfNeeded();
10655            }
10656        }
10657
10658        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10659            destroyDrawingCache();
10660        }
10661
10662        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10663            destroyDrawingCache();
10664            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10665            invalidateParentCaches();
10666        }
10667
10668        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10669            destroyDrawingCache();
10670            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10671        }
10672
10673        if ((changed & DRAW_MASK) != 0) {
10674            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10675                if (mBackground != null
10676                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10677                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10678                } else {
10679                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10680                }
10681            } else {
10682                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10683            }
10684            requestLayout();
10685            invalidate(true);
10686        }
10687
10688        if ((changed & KEEP_SCREEN_ON) != 0) {
10689            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10690                mParent.recomputeViewAttributes(this);
10691            }
10692        }
10693
10694        if (accessibilityEnabled) {
10695            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10696                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10697                    || (changed & CONTEXT_CLICKABLE) != 0) {
10698                if (oldIncludeForAccessibility != includeForAccessibility()) {
10699                    notifySubtreeAccessibilityStateChangedIfNeeded();
10700                } else {
10701                    notifyViewAccessibilityStateChangedIfNeeded(
10702                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10703                }
10704            } else if ((changed & ENABLED_MASK) != 0) {
10705                notifyViewAccessibilityStateChangedIfNeeded(
10706                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10707            }
10708        }
10709    }
10710
10711    /**
10712     * Change the view's z order in the tree, so it's on top of other sibling
10713     * views. This ordering change may affect layout, if the parent container
10714     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10715     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10716     * method should be followed by calls to {@link #requestLayout()} and
10717     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10718     * with the new child ordering.
10719     *
10720     * @see ViewGroup#bringChildToFront(View)
10721     */
10722    public void bringToFront() {
10723        if (mParent != null) {
10724            mParent.bringChildToFront(this);
10725        }
10726    }
10727
10728    /**
10729     * This is called in response to an internal scroll in this view (i.e., the
10730     * view scrolled its own contents). This is typically as a result of
10731     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10732     * called.
10733     *
10734     * @param l Current horizontal scroll origin.
10735     * @param t Current vertical scroll origin.
10736     * @param oldl Previous horizontal scroll origin.
10737     * @param oldt Previous vertical scroll origin.
10738     */
10739    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10740        notifySubtreeAccessibilityStateChangedIfNeeded();
10741
10742        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10743            postSendViewScrolledAccessibilityEventCallback();
10744        }
10745
10746        mBackgroundSizeChanged = true;
10747        if (mForegroundInfo != null) {
10748            mForegroundInfo.mBoundsChanged = true;
10749        }
10750
10751        final AttachInfo ai = mAttachInfo;
10752        if (ai != null) {
10753            ai.mViewScrollChanged = true;
10754        }
10755
10756        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10757            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10758        }
10759    }
10760
10761    /**
10762     * Interface definition for a callback to be invoked when the scroll
10763     * X or Y positions of a view change.
10764     * <p>
10765     * <b>Note:</b> Some views handle scrolling independently from View and may
10766     * have their own separate listeners for scroll-type events. For example,
10767     * {@link android.widget.ListView ListView} allows clients to register an
10768     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10769     * to listen for changes in list scroll position.
10770     *
10771     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10772     */
10773    public interface OnScrollChangeListener {
10774        /**
10775         * Called when the scroll position of a view changes.
10776         *
10777         * @param v The view whose scroll position has changed.
10778         * @param scrollX Current horizontal scroll origin.
10779         * @param scrollY Current vertical scroll origin.
10780         * @param oldScrollX Previous horizontal scroll origin.
10781         * @param oldScrollY Previous vertical scroll origin.
10782         */
10783        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10784    }
10785
10786    /**
10787     * Interface definition for a callback to be invoked when the layout bounds of a view
10788     * changes due to layout processing.
10789     */
10790    public interface OnLayoutChangeListener {
10791        /**
10792         * Called when the layout bounds of a view changes due to layout processing.
10793         *
10794         * @param v The view whose bounds have changed.
10795         * @param left The new value of the view's left property.
10796         * @param top The new value of the view's top property.
10797         * @param right The new value of the view's right property.
10798         * @param bottom The new value of the view's bottom property.
10799         * @param oldLeft The previous value of the view's left property.
10800         * @param oldTop The previous value of the view's top property.
10801         * @param oldRight The previous value of the view's right property.
10802         * @param oldBottom The previous value of the view's bottom property.
10803         */
10804        void onLayoutChange(View v, int left, int top, int right, int bottom,
10805            int oldLeft, int oldTop, int oldRight, int oldBottom);
10806    }
10807
10808    /**
10809     * This is called during layout when the size of this view has changed. If
10810     * you were just added to the view hierarchy, you're called with the old
10811     * values of 0.
10812     *
10813     * @param w Current width of this view.
10814     * @param h Current height of this view.
10815     * @param oldw Old width of this view.
10816     * @param oldh Old height of this view.
10817     */
10818    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10819    }
10820
10821    /**
10822     * Called by draw to draw the child views. This may be overridden
10823     * by derived classes to gain control just before its children are drawn
10824     * (but after its own view has been drawn).
10825     * @param canvas the canvas on which to draw the view
10826     */
10827    protected void dispatchDraw(Canvas canvas) {
10828
10829    }
10830
10831    /**
10832     * Gets the parent of this view. Note that the parent is a
10833     * ViewParent and not necessarily a View.
10834     *
10835     * @return Parent of this view.
10836     */
10837    public final ViewParent getParent() {
10838        return mParent;
10839    }
10840
10841    /**
10842     * Set the horizontal scrolled position of your view. This will cause a call to
10843     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10844     * invalidated.
10845     * @param value the x position to scroll to
10846     */
10847    public void setScrollX(int value) {
10848        scrollTo(value, mScrollY);
10849    }
10850
10851    /**
10852     * Set the vertical 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 y position to scroll to
10856     */
10857    public void setScrollY(int value) {
10858        scrollTo(mScrollX, value);
10859    }
10860
10861    /**
10862     * Return the scrolled left position of this view. This is the left edge of
10863     * the displayed part of your view. You do not need to draw any pixels
10864     * farther left, since those are outside of the frame of your view on
10865     * screen.
10866     *
10867     * @return The left edge of the displayed part of your view, in pixels.
10868     */
10869    public final int getScrollX() {
10870        return mScrollX;
10871    }
10872
10873    /**
10874     * Return the scrolled top position of this view. This is the top edge of
10875     * the displayed part of your view. You do not need to draw any pixels above
10876     * it, since those are outside of the frame of your view on screen.
10877     *
10878     * @return The top edge of the displayed part of your view, in pixels.
10879     */
10880    public final int getScrollY() {
10881        return mScrollY;
10882    }
10883
10884    /**
10885     * Return the width of the your view.
10886     *
10887     * @return The width of your view, in pixels.
10888     */
10889    @ViewDebug.ExportedProperty(category = "layout")
10890    public final int getWidth() {
10891        return mRight - mLeft;
10892    }
10893
10894    /**
10895     * Return the height of your view.
10896     *
10897     * @return The height of your view, in pixels.
10898     */
10899    @ViewDebug.ExportedProperty(category = "layout")
10900    public final int getHeight() {
10901        return mBottom - mTop;
10902    }
10903
10904    /**
10905     * Return the visible drawing bounds of your view. Fills in the output
10906     * rectangle with the values from getScrollX(), getScrollY(),
10907     * getWidth(), and getHeight(). These bounds do not account for any
10908     * transformation properties currently set on the view, such as
10909     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10910     *
10911     * @param outRect The (scrolled) drawing bounds of the view.
10912     */
10913    public void getDrawingRect(Rect outRect) {
10914        outRect.left = mScrollX;
10915        outRect.top = mScrollY;
10916        outRect.right = mScrollX + (mRight - mLeft);
10917        outRect.bottom = mScrollY + (mBottom - mTop);
10918    }
10919
10920    /**
10921     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10922     * raw width component (that is the result is masked by
10923     * {@link #MEASURED_SIZE_MASK}).
10924     *
10925     * @return The raw measured width of this view.
10926     */
10927    public final int getMeasuredWidth() {
10928        return mMeasuredWidth & MEASURED_SIZE_MASK;
10929    }
10930
10931    /**
10932     * Return the full width measurement information for this view as computed
10933     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10934     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10935     * This should be used during measurement and layout calculations only. Use
10936     * {@link #getWidth()} to see how wide a view is after layout.
10937     *
10938     * @return The measured width of this view as a bit mask.
10939     */
10940    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10941            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10942                    name = "MEASURED_STATE_TOO_SMALL"),
10943    })
10944    public final int getMeasuredWidthAndState() {
10945        return mMeasuredWidth;
10946    }
10947
10948    /**
10949     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10950     * raw width component (that is the result is masked by
10951     * {@link #MEASURED_SIZE_MASK}).
10952     *
10953     * @return The raw measured height of this view.
10954     */
10955    public final int getMeasuredHeight() {
10956        return mMeasuredHeight & MEASURED_SIZE_MASK;
10957    }
10958
10959    /**
10960     * Return the full height measurement information for this view as computed
10961     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10962     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10963     * This should be used during measurement and layout calculations only. Use
10964     * {@link #getHeight()} to see how wide a view is after layout.
10965     *
10966     * @return The measured width of this view as a bit mask.
10967     */
10968    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10969            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10970                    name = "MEASURED_STATE_TOO_SMALL"),
10971    })
10972    public final int getMeasuredHeightAndState() {
10973        return mMeasuredHeight;
10974    }
10975
10976    /**
10977     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10978     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10979     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10980     * and the height component is at the shifted bits
10981     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10982     */
10983    public final int getMeasuredState() {
10984        return (mMeasuredWidth&MEASURED_STATE_MASK)
10985                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10986                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10987    }
10988
10989    /**
10990     * The transform matrix of this view, which is calculated based on the current
10991     * rotation, scale, and pivot properties.
10992     *
10993     * @see #getRotation()
10994     * @see #getScaleX()
10995     * @see #getScaleY()
10996     * @see #getPivotX()
10997     * @see #getPivotY()
10998     * @return The current transform matrix for the view
10999     */
11000    public Matrix getMatrix() {
11001        ensureTransformationInfo();
11002        final Matrix matrix = mTransformationInfo.mMatrix;
11003        mRenderNode.getMatrix(matrix);
11004        return matrix;
11005    }
11006
11007    /**
11008     * Returns true if the transform matrix is the identity matrix.
11009     * Recomputes the matrix if necessary.
11010     *
11011     * @return True if the transform matrix is the identity matrix, false otherwise.
11012     */
11013    final boolean hasIdentityMatrix() {
11014        return mRenderNode.hasIdentityMatrix();
11015    }
11016
11017    void ensureTransformationInfo() {
11018        if (mTransformationInfo == null) {
11019            mTransformationInfo = new TransformationInfo();
11020        }
11021    }
11022
11023   /**
11024     * Utility method to retrieve the inverse of the current mMatrix property.
11025     * We cache the matrix to avoid recalculating it when transform properties
11026     * have not changed.
11027     *
11028     * @return The inverse of the current matrix of this view.
11029     * @hide
11030     */
11031    public final Matrix getInverseMatrix() {
11032        ensureTransformationInfo();
11033        if (mTransformationInfo.mInverseMatrix == null) {
11034            mTransformationInfo.mInverseMatrix = new Matrix();
11035        }
11036        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11037        mRenderNode.getInverseMatrix(matrix);
11038        return matrix;
11039    }
11040
11041    /**
11042     * Gets the distance along the Z axis from the camera to this view.
11043     *
11044     * @see #setCameraDistance(float)
11045     *
11046     * @return The distance along the Z axis.
11047     */
11048    public float getCameraDistance() {
11049        final float dpi = mResources.getDisplayMetrics().densityDpi;
11050        return -(mRenderNode.getCameraDistance() * dpi);
11051    }
11052
11053    /**
11054     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11055     * views are drawn) from the camera to this view. The camera's distance
11056     * affects 3D transformations, for instance rotations around the X and Y
11057     * axis. If the rotationX or rotationY properties are changed and this view is
11058     * large (more than half the size of the screen), it is recommended to always
11059     * use a camera distance that's greater than the height (X axis rotation) or
11060     * the width (Y axis rotation) of this view.</p>
11061     *
11062     * <p>The distance of the camera from the view plane can have an affect on the
11063     * perspective distortion of the view when it is rotated around the x or y axis.
11064     * For example, a large distance will result in a large viewing angle, and there
11065     * will not be much perspective distortion of the view as it rotates. A short
11066     * distance may cause much more perspective distortion upon rotation, and can
11067     * also result in some drawing artifacts if the rotated view ends up partially
11068     * behind the camera (which is why the recommendation is to use a distance at
11069     * least as far as the size of the view, if the view is to be rotated.)</p>
11070     *
11071     * <p>The distance is expressed in "depth pixels." The default distance depends
11072     * on the screen density. For instance, on a medium density display, the
11073     * default distance is 1280. On a high density display, the default distance
11074     * is 1920.</p>
11075     *
11076     * <p>If you want to specify a distance that leads to visually consistent
11077     * results across various densities, use the following formula:</p>
11078     * <pre>
11079     * float scale = context.getResources().getDisplayMetrics().density;
11080     * view.setCameraDistance(distance * scale);
11081     * </pre>
11082     *
11083     * <p>The density scale factor of a high density display is 1.5,
11084     * and 1920 = 1280 * 1.5.</p>
11085     *
11086     * @param distance The distance in "depth pixels", if negative the opposite
11087     *        value is used
11088     *
11089     * @see #setRotationX(float)
11090     * @see #setRotationY(float)
11091     */
11092    public void setCameraDistance(float distance) {
11093        final float dpi = mResources.getDisplayMetrics().densityDpi;
11094
11095        invalidateViewProperty(true, false);
11096        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11097        invalidateViewProperty(false, false);
11098
11099        invalidateParentIfNeededAndWasQuickRejected();
11100    }
11101
11102    /**
11103     * The degrees that the view is rotated around the pivot point.
11104     *
11105     * @see #setRotation(float)
11106     * @see #getPivotX()
11107     * @see #getPivotY()
11108     *
11109     * @return The degrees of rotation.
11110     */
11111    @ViewDebug.ExportedProperty(category = "drawing")
11112    public float getRotation() {
11113        return mRenderNode.getRotation();
11114    }
11115
11116    /**
11117     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11118     * result in clockwise rotation.
11119     *
11120     * @param rotation The degrees of rotation.
11121     *
11122     * @see #getRotation()
11123     * @see #getPivotX()
11124     * @see #getPivotY()
11125     * @see #setRotationX(float)
11126     * @see #setRotationY(float)
11127     *
11128     * @attr ref android.R.styleable#View_rotation
11129     */
11130    public void setRotation(float rotation) {
11131        if (rotation != getRotation()) {
11132            // Double-invalidation is necessary to capture view's old and new areas
11133            invalidateViewProperty(true, false);
11134            mRenderNode.setRotation(rotation);
11135            invalidateViewProperty(false, true);
11136
11137            invalidateParentIfNeededAndWasQuickRejected();
11138            notifySubtreeAccessibilityStateChangedIfNeeded();
11139        }
11140    }
11141
11142    /**
11143     * The degrees that the view is rotated around the vertical axis through the pivot point.
11144     *
11145     * @see #getPivotX()
11146     * @see #getPivotY()
11147     * @see #setRotationY(float)
11148     *
11149     * @return The degrees of Y rotation.
11150     */
11151    @ViewDebug.ExportedProperty(category = "drawing")
11152    public float getRotationY() {
11153        return mRenderNode.getRotationY();
11154    }
11155
11156    /**
11157     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11158     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11159     * down the y axis.
11160     *
11161     * When rotating large views, it is recommended to adjust the camera distance
11162     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11163     *
11164     * @param rotationY The degrees of Y rotation.
11165     *
11166     * @see #getRotationY()
11167     * @see #getPivotX()
11168     * @see #getPivotY()
11169     * @see #setRotation(float)
11170     * @see #setRotationX(float)
11171     * @see #setCameraDistance(float)
11172     *
11173     * @attr ref android.R.styleable#View_rotationY
11174     */
11175    public void setRotationY(float rotationY) {
11176        if (rotationY != getRotationY()) {
11177            invalidateViewProperty(true, false);
11178            mRenderNode.setRotationY(rotationY);
11179            invalidateViewProperty(false, true);
11180
11181            invalidateParentIfNeededAndWasQuickRejected();
11182            notifySubtreeAccessibilityStateChangedIfNeeded();
11183        }
11184    }
11185
11186    /**
11187     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11188     *
11189     * @see #getPivotX()
11190     * @see #getPivotY()
11191     * @see #setRotationX(float)
11192     *
11193     * @return The degrees of X rotation.
11194     */
11195    @ViewDebug.ExportedProperty(category = "drawing")
11196    public float getRotationX() {
11197        return mRenderNode.getRotationX();
11198    }
11199
11200    /**
11201     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11202     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11203     * x axis.
11204     *
11205     * When rotating large views, it is recommended to adjust the camera distance
11206     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11207     *
11208     * @param rotationX The degrees of X rotation.
11209     *
11210     * @see #getRotationX()
11211     * @see #getPivotX()
11212     * @see #getPivotY()
11213     * @see #setRotation(float)
11214     * @see #setRotationY(float)
11215     * @see #setCameraDistance(float)
11216     *
11217     * @attr ref android.R.styleable#View_rotationX
11218     */
11219    public void setRotationX(float rotationX) {
11220        if (rotationX != getRotationX()) {
11221            invalidateViewProperty(true, false);
11222            mRenderNode.setRotationX(rotationX);
11223            invalidateViewProperty(false, true);
11224
11225            invalidateParentIfNeededAndWasQuickRejected();
11226            notifySubtreeAccessibilityStateChangedIfNeeded();
11227        }
11228    }
11229
11230    /**
11231     * The amount that the view is scaled in x around the pivot point, as a proportion of
11232     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11233     *
11234     * <p>By default, this is 1.0f.
11235     *
11236     * @see #getPivotX()
11237     * @see #getPivotY()
11238     * @return The scaling factor.
11239     */
11240    @ViewDebug.ExportedProperty(category = "drawing")
11241    public float getScaleX() {
11242        return mRenderNode.getScaleX();
11243    }
11244
11245    /**
11246     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11247     * the view's unscaled width. A value of 1 means that no scaling is applied.
11248     *
11249     * @param scaleX The scaling factor.
11250     * @see #getPivotX()
11251     * @see #getPivotY()
11252     *
11253     * @attr ref android.R.styleable#View_scaleX
11254     */
11255    public void setScaleX(float scaleX) {
11256        if (scaleX != getScaleX()) {
11257            invalidateViewProperty(true, false);
11258            mRenderNode.setScaleX(scaleX);
11259            invalidateViewProperty(false, true);
11260
11261            invalidateParentIfNeededAndWasQuickRejected();
11262            notifySubtreeAccessibilityStateChangedIfNeeded();
11263        }
11264    }
11265
11266    /**
11267     * The amount that the view is scaled in y around the pivot point, as a proportion of
11268     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11269     *
11270     * <p>By default, this is 1.0f.
11271     *
11272     * @see #getPivotX()
11273     * @see #getPivotY()
11274     * @return The scaling factor.
11275     */
11276    @ViewDebug.ExportedProperty(category = "drawing")
11277    public float getScaleY() {
11278        return mRenderNode.getScaleY();
11279    }
11280
11281    /**
11282     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11283     * the view's unscaled width. A value of 1 means that no scaling is applied.
11284     *
11285     * @param scaleY The scaling factor.
11286     * @see #getPivotX()
11287     * @see #getPivotY()
11288     *
11289     * @attr ref android.R.styleable#View_scaleY
11290     */
11291    public void setScaleY(float scaleY) {
11292        if (scaleY != getScaleY()) {
11293            invalidateViewProperty(true, false);
11294            mRenderNode.setScaleY(scaleY);
11295            invalidateViewProperty(false, true);
11296
11297            invalidateParentIfNeededAndWasQuickRejected();
11298            notifySubtreeAccessibilityStateChangedIfNeeded();
11299        }
11300    }
11301
11302    /**
11303     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11304     * and {@link #setScaleX(float) scaled}.
11305     *
11306     * @see #getRotation()
11307     * @see #getScaleX()
11308     * @see #getScaleY()
11309     * @see #getPivotY()
11310     * @return The x location of the pivot point.
11311     *
11312     * @attr ref android.R.styleable#View_transformPivotX
11313     */
11314    @ViewDebug.ExportedProperty(category = "drawing")
11315    public float getPivotX() {
11316        return mRenderNode.getPivotX();
11317    }
11318
11319    /**
11320     * Sets the x location of the point around which the view is
11321     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11322     * By default, the pivot point is centered on the object.
11323     * Setting this property disables this behavior and causes the view to use only the
11324     * explicitly set pivotX and pivotY values.
11325     *
11326     * @param pivotX The x location of the pivot point.
11327     * @see #getRotation()
11328     * @see #getScaleX()
11329     * @see #getScaleY()
11330     * @see #getPivotY()
11331     *
11332     * @attr ref android.R.styleable#View_transformPivotX
11333     */
11334    public void setPivotX(float pivotX) {
11335        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11336            invalidateViewProperty(true, false);
11337            mRenderNode.setPivotX(pivotX);
11338            invalidateViewProperty(false, true);
11339
11340            invalidateParentIfNeededAndWasQuickRejected();
11341        }
11342    }
11343
11344    /**
11345     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11346     * and {@link #setScaleY(float) scaled}.
11347     *
11348     * @see #getRotation()
11349     * @see #getScaleX()
11350     * @see #getScaleY()
11351     * @see #getPivotY()
11352     * @return The y location of the pivot point.
11353     *
11354     * @attr ref android.R.styleable#View_transformPivotY
11355     */
11356    @ViewDebug.ExportedProperty(category = "drawing")
11357    public float getPivotY() {
11358        return mRenderNode.getPivotY();
11359    }
11360
11361    /**
11362     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11363     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11364     * Setting this property disables this behavior and causes the view to use only the
11365     * explicitly set pivotX and pivotY values.
11366     *
11367     * @param pivotY The y location of the pivot point.
11368     * @see #getRotation()
11369     * @see #getScaleX()
11370     * @see #getScaleY()
11371     * @see #getPivotY()
11372     *
11373     * @attr ref android.R.styleable#View_transformPivotY
11374     */
11375    public void setPivotY(float pivotY) {
11376        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11377            invalidateViewProperty(true, false);
11378            mRenderNode.setPivotY(pivotY);
11379            invalidateViewProperty(false, true);
11380
11381            invalidateParentIfNeededAndWasQuickRejected();
11382        }
11383    }
11384
11385    /**
11386     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11387     * completely transparent and 1 means the view is completely opaque.
11388     *
11389     * <p>By default this is 1.0f.
11390     * @return The opacity of the view.
11391     */
11392    @ViewDebug.ExportedProperty(category = "drawing")
11393    public float getAlpha() {
11394        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11395    }
11396
11397    /**
11398     * Returns whether this View has content which overlaps.
11399     *
11400     * <p>This function, intended to be overridden by specific View types, is an optimization when
11401     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11402     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11403     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11404     * directly. An example of overlapping rendering is a TextView with a background image, such as
11405     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11406     * ImageView with only the foreground image. The default implementation returns true; subclasses
11407     * should override if they have cases which can be optimized.</p>
11408     *
11409     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11410     * necessitates that a View return true if it uses the methods internally without passing the
11411     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11412     *
11413     * @return true if the content in this view might overlap, false otherwise.
11414     */
11415    @ViewDebug.ExportedProperty(category = "drawing")
11416    public boolean hasOverlappingRendering() {
11417        return true;
11418    }
11419
11420    /**
11421     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11422     * completely transparent and 1 means the view is completely opaque.
11423     *
11424     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11425     * can have significant performance implications, especially for large views. It is best to use
11426     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11427     *
11428     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11429     * strongly recommended for performance reasons to either override
11430     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11431     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11432     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11433     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11434     * of rendering cost, even for simple or small views. Starting with
11435     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11436     * applied to the view at the rendering level.</p>
11437     *
11438     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11439     * responsible for applying the opacity itself.</p>
11440     *
11441     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11442     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11443     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11444     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11445     *
11446     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11447     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11448     * {@link #hasOverlappingRendering}.</p>
11449     *
11450     * @param alpha The opacity of the view.
11451     *
11452     * @see #hasOverlappingRendering()
11453     * @see #setLayerType(int, android.graphics.Paint)
11454     *
11455     * @attr ref android.R.styleable#View_alpha
11456     */
11457    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11458        ensureTransformationInfo();
11459        if (mTransformationInfo.mAlpha != alpha) {
11460            mTransformationInfo.mAlpha = alpha;
11461            if (onSetAlpha((int) (alpha * 255))) {
11462                mPrivateFlags |= PFLAG_ALPHA_SET;
11463                // subclass is handling alpha - don't optimize rendering cache invalidation
11464                invalidateParentCaches();
11465                invalidate(true);
11466            } else {
11467                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11468                invalidateViewProperty(true, false);
11469                mRenderNode.setAlpha(getFinalAlpha());
11470                notifyViewAccessibilityStateChangedIfNeeded(
11471                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11472            }
11473        }
11474    }
11475
11476    /**
11477     * Faster version of setAlpha() which performs the same steps except there are
11478     * no calls to invalidate(). The caller of this function should perform proper invalidation
11479     * on the parent and this object. The return value indicates whether the subclass handles
11480     * alpha (the return value for onSetAlpha()).
11481     *
11482     * @param alpha The new value for the alpha property
11483     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11484     *         the new value for the alpha property is different from the old value
11485     */
11486    boolean setAlphaNoInvalidation(float alpha) {
11487        ensureTransformationInfo();
11488        if (mTransformationInfo.mAlpha != alpha) {
11489            mTransformationInfo.mAlpha = alpha;
11490            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11491            if (subclassHandlesAlpha) {
11492                mPrivateFlags |= PFLAG_ALPHA_SET;
11493                return true;
11494            } else {
11495                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11496                mRenderNode.setAlpha(getFinalAlpha());
11497            }
11498        }
11499        return false;
11500    }
11501
11502    /**
11503     * This property is hidden and intended only for use by the Fade transition, which
11504     * animates it to produce a visual translucency that does not side-effect (or get
11505     * affected by) the real alpha property. This value is composited with the other
11506     * alpha value (and the AlphaAnimation value, when that is present) to produce
11507     * a final visual translucency result, which is what is passed into the DisplayList.
11508     *
11509     * @hide
11510     */
11511    public void setTransitionAlpha(float alpha) {
11512        ensureTransformationInfo();
11513        if (mTransformationInfo.mTransitionAlpha != alpha) {
11514            mTransformationInfo.mTransitionAlpha = alpha;
11515            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11516            invalidateViewProperty(true, false);
11517            mRenderNode.setAlpha(getFinalAlpha());
11518        }
11519    }
11520
11521    /**
11522     * Calculates the visual alpha of this view, which is a combination of the actual
11523     * alpha value and the transitionAlpha value (if set).
11524     */
11525    private float getFinalAlpha() {
11526        if (mTransformationInfo != null) {
11527            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11528        }
11529        return 1;
11530    }
11531
11532    /**
11533     * This property is hidden and intended only for use by the Fade transition, which
11534     * animates it to produce a visual translucency that does not side-effect (or get
11535     * affected by) the real alpha property. This value is composited with the other
11536     * alpha value (and the AlphaAnimation value, when that is present) to produce
11537     * a final visual translucency result, which is what is passed into the DisplayList.
11538     *
11539     * @hide
11540     */
11541    @ViewDebug.ExportedProperty(category = "drawing")
11542    public float getTransitionAlpha() {
11543        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11544    }
11545
11546    /**
11547     * Top position of this view relative to its parent.
11548     *
11549     * @return The top of this view, in pixels.
11550     */
11551    @ViewDebug.CapturedViewProperty
11552    public final int getTop() {
11553        return mTop;
11554    }
11555
11556    /**
11557     * Sets the top position of this view relative to its parent. This method is meant to be called
11558     * by the layout system and should not generally be called otherwise, because the property
11559     * may be changed at any time by the layout.
11560     *
11561     * @param top The top of this view, in pixels.
11562     */
11563    public final void setTop(int top) {
11564        if (top != mTop) {
11565            final boolean matrixIsIdentity = hasIdentityMatrix();
11566            if (matrixIsIdentity) {
11567                if (mAttachInfo != null) {
11568                    int minTop;
11569                    int yLoc;
11570                    if (top < mTop) {
11571                        minTop = top;
11572                        yLoc = top - mTop;
11573                    } else {
11574                        minTop = mTop;
11575                        yLoc = 0;
11576                    }
11577                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11578                }
11579            } else {
11580                // Double-invalidation is necessary to capture view's old and new areas
11581                invalidate(true);
11582            }
11583
11584            int width = mRight - mLeft;
11585            int oldHeight = mBottom - mTop;
11586
11587            mTop = top;
11588            mRenderNode.setTop(mTop);
11589
11590            sizeChange(width, mBottom - mTop, width, oldHeight);
11591
11592            if (!matrixIsIdentity) {
11593                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11594                invalidate(true);
11595            }
11596            mBackgroundSizeChanged = true;
11597            if (mForegroundInfo != null) {
11598                mForegroundInfo.mBoundsChanged = true;
11599            }
11600            invalidateParentIfNeeded();
11601            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11602                // View was rejected last time it was drawn by its parent; this may have changed
11603                invalidateParentIfNeeded();
11604            }
11605        }
11606    }
11607
11608    /**
11609     * Bottom position of this view relative to its parent.
11610     *
11611     * @return The bottom of this view, in pixels.
11612     */
11613    @ViewDebug.CapturedViewProperty
11614    public final int getBottom() {
11615        return mBottom;
11616    }
11617
11618    /**
11619     * True if this view has changed since the last time being drawn.
11620     *
11621     * @return The dirty state of this view.
11622     */
11623    public boolean isDirty() {
11624        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11625    }
11626
11627    /**
11628     * Sets the bottom position of this view relative to its parent. This method is meant to be
11629     * called by the layout system and should not generally be called otherwise, because the
11630     * property may be changed at any time by the layout.
11631     *
11632     * @param bottom The bottom of this view, in pixels.
11633     */
11634    public final void setBottom(int bottom) {
11635        if (bottom != mBottom) {
11636            final boolean matrixIsIdentity = hasIdentityMatrix();
11637            if (matrixIsIdentity) {
11638                if (mAttachInfo != null) {
11639                    int maxBottom;
11640                    if (bottom < mBottom) {
11641                        maxBottom = mBottom;
11642                    } else {
11643                        maxBottom = bottom;
11644                    }
11645                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11646                }
11647            } else {
11648                // Double-invalidation is necessary to capture view's old and new areas
11649                invalidate(true);
11650            }
11651
11652            int width = mRight - mLeft;
11653            int oldHeight = mBottom - mTop;
11654
11655            mBottom = bottom;
11656            mRenderNode.setBottom(mBottom);
11657
11658            sizeChange(width, mBottom - mTop, width, oldHeight);
11659
11660            if (!matrixIsIdentity) {
11661                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11662                invalidate(true);
11663            }
11664            mBackgroundSizeChanged = true;
11665            if (mForegroundInfo != null) {
11666                mForegroundInfo.mBoundsChanged = true;
11667            }
11668            invalidateParentIfNeeded();
11669            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11670                // View was rejected last time it was drawn by its parent; this may have changed
11671                invalidateParentIfNeeded();
11672            }
11673        }
11674    }
11675
11676    /**
11677     * Left position of this view relative to its parent.
11678     *
11679     * @return The left edge of this view, in pixels.
11680     */
11681    @ViewDebug.CapturedViewProperty
11682    public final int getLeft() {
11683        return mLeft;
11684    }
11685
11686    /**
11687     * Sets the left position of this view relative to its parent. This method is meant to be called
11688     * by the layout system and should not generally be called otherwise, because the property
11689     * may be changed at any time by the layout.
11690     *
11691     * @param left The left of this view, in pixels.
11692     */
11693    public final void setLeft(int left) {
11694        if (left != mLeft) {
11695            final boolean matrixIsIdentity = hasIdentityMatrix();
11696            if (matrixIsIdentity) {
11697                if (mAttachInfo != null) {
11698                    int minLeft;
11699                    int xLoc;
11700                    if (left < mLeft) {
11701                        minLeft = left;
11702                        xLoc = left - mLeft;
11703                    } else {
11704                        minLeft = mLeft;
11705                        xLoc = 0;
11706                    }
11707                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11708                }
11709            } else {
11710                // Double-invalidation is necessary to capture view's old and new areas
11711                invalidate(true);
11712            }
11713
11714            int oldWidth = mRight - mLeft;
11715            int height = mBottom - mTop;
11716
11717            mLeft = left;
11718            mRenderNode.setLeft(left);
11719
11720            sizeChange(mRight - mLeft, height, oldWidth, height);
11721
11722            if (!matrixIsIdentity) {
11723                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11724                invalidate(true);
11725            }
11726            mBackgroundSizeChanged = true;
11727            if (mForegroundInfo != null) {
11728                mForegroundInfo.mBoundsChanged = true;
11729            }
11730            invalidateParentIfNeeded();
11731            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11732                // View was rejected last time it was drawn by its parent; this may have changed
11733                invalidateParentIfNeeded();
11734            }
11735        }
11736    }
11737
11738    /**
11739     * Right position of this view relative to its parent.
11740     *
11741     * @return The right edge of this view, in pixels.
11742     */
11743    @ViewDebug.CapturedViewProperty
11744    public final int getRight() {
11745        return mRight;
11746    }
11747
11748    /**
11749     * Sets the right position of this view relative to its parent. This method is meant to be called
11750     * by the layout system and should not generally be called otherwise, because the property
11751     * may be changed at any time by the layout.
11752     *
11753     * @param right The right of this view, in pixels.
11754     */
11755    public final void setRight(int right) {
11756        if (right != mRight) {
11757            final boolean matrixIsIdentity = hasIdentityMatrix();
11758            if (matrixIsIdentity) {
11759                if (mAttachInfo != null) {
11760                    int maxRight;
11761                    if (right < mRight) {
11762                        maxRight = mRight;
11763                    } else {
11764                        maxRight = right;
11765                    }
11766                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11767                }
11768            } else {
11769                // Double-invalidation is necessary to capture view's old and new areas
11770                invalidate(true);
11771            }
11772
11773            int oldWidth = mRight - mLeft;
11774            int height = mBottom - mTop;
11775
11776            mRight = right;
11777            mRenderNode.setRight(mRight);
11778
11779            sizeChange(mRight - mLeft, height, oldWidth, height);
11780
11781            if (!matrixIsIdentity) {
11782                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11783                invalidate(true);
11784            }
11785            mBackgroundSizeChanged = true;
11786            if (mForegroundInfo != null) {
11787                mForegroundInfo.mBoundsChanged = true;
11788            }
11789            invalidateParentIfNeeded();
11790            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11791                // View was rejected last time it was drawn by its parent; this may have changed
11792                invalidateParentIfNeeded();
11793            }
11794        }
11795    }
11796
11797    /**
11798     * The visual x position of this view, in pixels. This is equivalent to the
11799     * {@link #setTranslationX(float) translationX} property plus the current
11800     * {@link #getLeft() left} property.
11801     *
11802     * @return The visual x position of this view, in pixels.
11803     */
11804    @ViewDebug.ExportedProperty(category = "drawing")
11805    public float getX() {
11806        return mLeft + getTranslationX();
11807    }
11808
11809    /**
11810     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11811     * {@link #setTranslationX(float) translationX} property to be the difference between
11812     * the x value passed in and the current {@link #getLeft() left} property.
11813     *
11814     * @param x The visual x position of this view, in pixels.
11815     */
11816    public void setX(float x) {
11817        setTranslationX(x - mLeft);
11818    }
11819
11820    /**
11821     * The visual y position of this view, in pixels. This is equivalent to the
11822     * {@link #setTranslationY(float) translationY} property plus the current
11823     * {@link #getTop() top} property.
11824     *
11825     * @return The visual y position of this view, in pixels.
11826     */
11827    @ViewDebug.ExportedProperty(category = "drawing")
11828    public float getY() {
11829        return mTop + getTranslationY();
11830    }
11831
11832    /**
11833     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11834     * {@link #setTranslationY(float) translationY} property to be the difference between
11835     * the y value passed in and the current {@link #getTop() top} property.
11836     *
11837     * @param y The visual y position of this view, in pixels.
11838     */
11839    public void setY(float y) {
11840        setTranslationY(y - mTop);
11841    }
11842
11843    /**
11844     * The visual z position of this view, in pixels. This is equivalent to the
11845     * {@link #setTranslationZ(float) translationZ} property plus the current
11846     * {@link #getElevation() elevation} property.
11847     *
11848     * @return The visual z position of this view, in pixels.
11849     */
11850    @ViewDebug.ExportedProperty(category = "drawing")
11851    public float getZ() {
11852        return getElevation() + getTranslationZ();
11853    }
11854
11855    /**
11856     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11857     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11858     * the x value passed in and the current {@link #getElevation() elevation} property.
11859     *
11860     * @param z The visual z position of this view, in pixels.
11861     */
11862    public void setZ(float z) {
11863        setTranslationZ(z - getElevation());
11864    }
11865
11866    /**
11867     * The base elevation of this view relative to its parent, in pixels.
11868     *
11869     * @return The base depth position of the view, in pixels.
11870     */
11871    @ViewDebug.ExportedProperty(category = "drawing")
11872    public float getElevation() {
11873        return mRenderNode.getElevation();
11874    }
11875
11876    /**
11877     * Sets the base elevation of this view, in pixels.
11878     *
11879     * @attr ref android.R.styleable#View_elevation
11880     */
11881    public void setElevation(float elevation) {
11882        if (elevation != getElevation()) {
11883            invalidateViewProperty(true, false);
11884            mRenderNode.setElevation(elevation);
11885            invalidateViewProperty(false, true);
11886
11887            invalidateParentIfNeededAndWasQuickRejected();
11888        }
11889    }
11890
11891    /**
11892     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11893     * This position is post-layout, in addition to wherever the object's
11894     * layout placed it.
11895     *
11896     * @return The horizontal position of this view relative to its left position, in pixels.
11897     */
11898    @ViewDebug.ExportedProperty(category = "drawing")
11899    public float getTranslationX() {
11900        return mRenderNode.getTranslationX();
11901    }
11902
11903    /**
11904     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11905     * This effectively positions the object post-layout, in addition to wherever the object's
11906     * layout placed it.
11907     *
11908     * @param translationX The horizontal position of this view relative to its left position,
11909     * in pixels.
11910     *
11911     * @attr ref android.R.styleable#View_translationX
11912     */
11913    public void setTranslationX(float translationX) {
11914        if (translationX != getTranslationX()) {
11915            invalidateViewProperty(true, false);
11916            mRenderNode.setTranslationX(translationX);
11917            invalidateViewProperty(false, true);
11918
11919            invalidateParentIfNeededAndWasQuickRejected();
11920            notifySubtreeAccessibilityStateChangedIfNeeded();
11921        }
11922    }
11923
11924    /**
11925     * The vertical location of this view relative to its {@link #getTop() top} position.
11926     * This position is post-layout, in addition to wherever the object's
11927     * layout placed it.
11928     *
11929     * @return The vertical position of this view relative to its top position,
11930     * in pixels.
11931     */
11932    @ViewDebug.ExportedProperty(category = "drawing")
11933    public float getTranslationY() {
11934        return mRenderNode.getTranslationY();
11935    }
11936
11937    /**
11938     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11939     * This effectively positions the object post-layout, in addition to wherever the object's
11940     * layout placed it.
11941     *
11942     * @param translationY The vertical position of this view relative to its top position,
11943     * in pixels.
11944     *
11945     * @attr ref android.R.styleable#View_translationY
11946     */
11947    public void setTranslationY(float translationY) {
11948        if (translationY != getTranslationY()) {
11949            invalidateViewProperty(true, false);
11950            mRenderNode.setTranslationY(translationY);
11951            invalidateViewProperty(false, true);
11952
11953            invalidateParentIfNeededAndWasQuickRejected();
11954            notifySubtreeAccessibilityStateChangedIfNeeded();
11955        }
11956    }
11957
11958    /**
11959     * The depth location of this view relative to its {@link #getElevation() elevation}.
11960     *
11961     * @return The depth of this view relative to its elevation.
11962     */
11963    @ViewDebug.ExportedProperty(category = "drawing")
11964    public float getTranslationZ() {
11965        return mRenderNode.getTranslationZ();
11966    }
11967
11968    /**
11969     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11970     *
11971     * @attr ref android.R.styleable#View_translationZ
11972     */
11973    public void setTranslationZ(float translationZ) {
11974        if (translationZ != getTranslationZ()) {
11975            invalidateViewProperty(true, false);
11976            mRenderNode.setTranslationZ(translationZ);
11977            invalidateViewProperty(false, true);
11978
11979            invalidateParentIfNeededAndWasQuickRejected();
11980        }
11981    }
11982
11983    /** @hide */
11984    public void setAnimationMatrix(Matrix matrix) {
11985        invalidateViewProperty(true, false);
11986        mRenderNode.setAnimationMatrix(matrix);
11987        invalidateViewProperty(false, true);
11988
11989        invalidateParentIfNeededAndWasQuickRejected();
11990    }
11991
11992    /**
11993     * Returns the current StateListAnimator if exists.
11994     *
11995     * @return StateListAnimator or null if it does not exists
11996     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11997     */
11998    public StateListAnimator getStateListAnimator() {
11999        return mStateListAnimator;
12000    }
12001
12002    /**
12003     * Attaches the provided StateListAnimator to this View.
12004     * <p>
12005     * Any previously attached StateListAnimator will be detached.
12006     *
12007     * @param stateListAnimator The StateListAnimator to update the view
12008     * @see {@link android.animation.StateListAnimator}
12009     */
12010    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12011        if (mStateListAnimator == stateListAnimator) {
12012            return;
12013        }
12014        if (mStateListAnimator != null) {
12015            mStateListAnimator.setTarget(null);
12016        }
12017        mStateListAnimator = stateListAnimator;
12018        if (stateListAnimator != null) {
12019            stateListAnimator.setTarget(this);
12020            if (isAttachedToWindow()) {
12021                stateListAnimator.setState(getDrawableState());
12022            }
12023        }
12024    }
12025
12026    /**
12027     * Returns whether the Outline should be used to clip the contents of the View.
12028     * <p>
12029     * Note that this flag will only be respected if the View's Outline returns true from
12030     * {@link Outline#canClip()}.
12031     *
12032     * @see #setOutlineProvider(ViewOutlineProvider)
12033     * @see #setClipToOutline(boolean)
12034     */
12035    public final boolean getClipToOutline() {
12036        return mRenderNode.getClipToOutline();
12037    }
12038
12039    /**
12040     * Sets whether the View's Outline should be used to clip the contents of the View.
12041     * <p>
12042     * Only a single non-rectangular clip can be applied on a View at any time.
12043     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12044     * circular reveal} animation take priority over Outline clipping, and
12045     * child Outline clipping takes priority over Outline clipping done by a
12046     * parent.
12047     * <p>
12048     * Note that this flag will only be respected if the View's Outline returns true from
12049     * {@link Outline#canClip()}.
12050     *
12051     * @see #setOutlineProvider(ViewOutlineProvider)
12052     * @see #getClipToOutline()
12053     */
12054    public void setClipToOutline(boolean clipToOutline) {
12055        damageInParent();
12056        if (getClipToOutline() != clipToOutline) {
12057            mRenderNode.setClipToOutline(clipToOutline);
12058        }
12059    }
12060
12061    // correspond to the enum values of View_outlineProvider
12062    private static final int PROVIDER_BACKGROUND = 0;
12063    private static final int PROVIDER_NONE = 1;
12064    private static final int PROVIDER_BOUNDS = 2;
12065    private static final int PROVIDER_PADDED_BOUNDS = 3;
12066    private void setOutlineProviderFromAttribute(int providerInt) {
12067        switch (providerInt) {
12068            case PROVIDER_BACKGROUND:
12069                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12070                break;
12071            case PROVIDER_NONE:
12072                setOutlineProvider(null);
12073                break;
12074            case PROVIDER_BOUNDS:
12075                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12076                break;
12077            case PROVIDER_PADDED_BOUNDS:
12078                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12079                break;
12080        }
12081    }
12082
12083    /**
12084     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12085     * the shape of the shadow it casts, and enables outline clipping.
12086     * <p>
12087     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12088     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12089     * outline provider with this method allows this behavior to be overridden.
12090     * <p>
12091     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12092     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12093     * <p>
12094     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12095     *
12096     * @see #setClipToOutline(boolean)
12097     * @see #getClipToOutline()
12098     * @see #getOutlineProvider()
12099     */
12100    public void setOutlineProvider(ViewOutlineProvider provider) {
12101        mOutlineProvider = provider;
12102        invalidateOutline();
12103    }
12104
12105    /**
12106     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12107     * that defines the shape of the shadow it casts, and enables outline clipping.
12108     *
12109     * @see #setOutlineProvider(ViewOutlineProvider)
12110     */
12111    public ViewOutlineProvider getOutlineProvider() {
12112        return mOutlineProvider;
12113    }
12114
12115    /**
12116     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12117     *
12118     * @see #setOutlineProvider(ViewOutlineProvider)
12119     */
12120    public void invalidateOutline() {
12121        rebuildOutline();
12122
12123        notifySubtreeAccessibilityStateChangedIfNeeded();
12124        invalidateViewProperty(false, false);
12125    }
12126
12127    /**
12128     * Internal version of {@link #invalidateOutline()} which invalidates the
12129     * outline without invalidating the view itself. This is intended to be called from
12130     * within methods in the View class itself which are the result of the view being
12131     * invalidated already. For example, when we are drawing the background of a View,
12132     * we invalidate the outline in case it changed in the meantime, but we do not
12133     * need to invalidate the view because we're already drawing the background as part
12134     * of drawing the view in response to an earlier invalidation of the view.
12135     */
12136    private void rebuildOutline() {
12137        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12138        if (mAttachInfo == null) return;
12139
12140        if (mOutlineProvider == null) {
12141            // no provider, remove outline
12142            mRenderNode.setOutline(null);
12143        } else {
12144            final Outline outline = mAttachInfo.mTmpOutline;
12145            outline.setEmpty();
12146            outline.setAlpha(1.0f);
12147
12148            mOutlineProvider.getOutline(this, outline);
12149            mRenderNode.setOutline(outline);
12150        }
12151    }
12152
12153    /**
12154     * HierarchyViewer only
12155     *
12156     * @hide
12157     */
12158    @ViewDebug.ExportedProperty(category = "drawing")
12159    public boolean hasShadow() {
12160        return mRenderNode.hasShadow();
12161    }
12162
12163
12164    /** @hide */
12165    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12166        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12167        invalidateViewProperty(false, false);
12168    }
12169
12170    /**
12171     * Hit rectangle in parent's coordinates
12172     *
12173     * @param outRect The hit rectangle of the view.
12174     */
12175    public void getHitRect(Rect outRect) {
12176        if (hasIdentityMatrix() || mAttachInfo == null) {
12177            outRect.set(mLeft, mTop, mRight, mBottom);
12178        } else {
12179            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12180            tmpRect.set(0, 0, getWidth(), getHeight());
12181            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12182            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12183                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12184        }
12185    }
12186
12187    /**
12188     * Determines whether the given point, in local coordinates is inside the view.
12189     */
12190    /*package*/ final boolean pointInView(float localX, float localY) {
12191        return localX >= 0 && localX < (mRight - mLeft)
12192                && localY >= 0 && localY < (mBottom - mTop);
12193    }
12194
12195    /**
12196     * Utility method to determine whether the given point, in local coordinates,
12197     * is inside the view, where the area of the view is expanded by the slop factor.
12198     * This method is called while processing touch-move events to determine if the event
12199     * is still within the view.
12200     *
12201     * @hide
12202     */
12203    public boolean pointInView(float localX, float localY, float slop) {
12204        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12205                localY < ((mBottom - mTop) + slop);
12206    }
12207
12208    /**
12209     * When a view has focus and the user navigates away from it, the next view is searched for
12210     * starting from the rectangle filled in by this method.
12211     *
12212     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12213     * of the view.  However, if your view maintains some idea of internal selection,
12214     * such as a cursor, or a selected row or column, you should override this method and
12215     * fill in a more specific rectangle.
12216     *
12217     * @param r The rectangle to fill in, in this view's coordinates.
12218     */
12219    public void getFocusedRect(Rect r) {
12220        getDrawingRect(r);
12221    }
12222
12223    /**
12224     * If some part of this view is not clipped by any of its parents, then
12225     * return that area in r in global (root) coordinates. To convert r to local
12226     * coordinates (without taking possible View rotations into account), offset
12227     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12228     * If the view is completely clipped or translated out, return false.
12229     *
12230     * @param r If true is returned, r holds the global coordinates of the
12231     *        visible portion of this view.
12232     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12233     *        between this view and its root. globalOffet may be null.
12234     * @return true if r is non-empty (i.e. part of the view is visible at the
12235     *         root level.
12236     */
12237    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12238        int width = mRight - mLeft;
12239        int height = mBottom - mTop;
12240        if (width > 0 && height > 0) {
12241            r.set(0, 0, width, height);
12242            if (globalOffset != null) {
12243                globalOffset.set(-mScrollX, -mScrollY);
12244            }
12245            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12246        }
12247        return false;
12248    }
12249
12250    public final boolean getGlobalVisibleRect(Rect r) {
12251        return getGlobalVisibleRect(r, null);
12252    }
12253
12254    public final boolean getLocalVisibleRect(Rect r) {
12255        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12256        if (getGlobalVisibleRect(r, offset)) {
12257            r.offset(-offset.x, -offset.y); // make r local
12258            return true;
12259        }
12260        return false;
12261    }
12262
12263    /**
12264     * Offset this view's vertical location by the specified number of pixels.
12265     *
12266     * @param offset the number of pixels to offset the view by
12267     */
12268    public void offsetTopAndBottom(int offset) {
12269        if (offset != 0) {
12270            final boolean matrixIsIdentity = hasIdentityMatrix();
12271            if (matrixIsIdentity) {
12272                if (isHardwareAccelerated()) {
12273                    invalidateViewProperty(false, false);
12274                } else {
12275                    final ViewParent p = mParent;
12276                    if (p != null && mAttachInfo != null) {
12277                        final Rect r = mAttachInfo.mTmpInvalRect;
12278                        int minTop;
12279                        int maxBottom;
12280                        int yLoc;
12281                        if (offset < 0) {
12282                            minTop = mTop + offset;
12283                            maxBottom = mBottom;
12284                            yLoc = offset;
12285                        } else {
12286                            minTop = mTop;
12287                            maxBottom = mBottom + offset;
12288                            yLoc = 0;
12289                        }
12290                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12291                        p.invalidateChild(this, r);
12292                    }
12293                }
12294            } else {
12295                invalidateViewProperty(false, false);
12296            }
12297
12298            mTop += offset;
12299            mBottom += offset;
12300            mRenderNode.offsetTopAndBottom(offset);
12301            if (isHardwareAccelerated()) {
12302                invalidateViewProperty(false, false);
12303                invalidateParentIfNeededAndWasQuickRejected();
12304            } else {
12305                if (!matrixIsIdentity) {
12306                    invalidateViewProperty(false, true);
12307                }
12308                invalidateParentIfNeeded();
12309            }
12310            notifySubtreeAccessibilityStateChangedIfNeeded();
12311        }
12312    }
12313
12314    /**
12315     * Offset this view's horizontal location by the specified amount of pixels.
12316     *
12317     * @param offset the number of pixels to offset the view by
12318     */
12319    public void offsetLeftAndRight(int offset) {
12320        if (offset != 0) {
12321            final boolean matrixIsIdentity = hasIdentityMatrix();
12322            if (matrixIsIdentity) {
12323                if (isHardwareAccelerated()) {
12324                    invalidateViewProperty(false, false);
12325                } else {
12326                    final ViewParent p = mParent;
12327                    if (p != null && mAttachInfo != null) {
12328                        final Rect r = mAttachInfo.mTmpInvalRect;
12329                        int minLeft;
12330                        int maxRight;
12331                        if (offset < 0) {
12332                            minLeft = mLeft + offset;
12333                            maxRight = mRight;
12334                        } else {
12335                            minLeft = mLeft;
12336                            maxRight = mRight + offset;
12337                        }
12338                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12339                        p.invalidateChild(this, r);
12340                    }
12341                }
12342            } else {
12343                invalidateViewProperty(false, false);
12344            }
12345
12346            mLeft += offset;
12347            mRight += offset;
12348            mRenderNode.offsetLeftAndRight(offset);
12349            if (isHardwareAccelerated()) {
12350                invalidateViewProperty(false, false);
12351                invalidateParentIfNeededAndWasQuickRejected();
12352            } else {
12353                if (!matrixIsIdentity) {
12354                    invalidateViewProperty(false, true);
12355                }
12356                invalidateParentIfNeeded();
12357            }
12358            notifySubtreeAccessibilityStateChangedIfNeeded();
12359        }
12360    }
12361
12362    /**
12363     * Get the LayoutParams associated with this view. All views should have
12364     * layout parameters. These supply parameters to the <i>parent</i> of this
12365     * view specifying how it should be arranged. There are many subclasses of
12366     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12367     * of ViewGroup that are responsible for arranging their children.
12368     *
12369     * This method may return null if this View is not attached to a parent
12370     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12371     * was not invoked successfully. When a View is attached to a parent
12372     * ViewGroup, this method must not return null.
12373     *
12374     * @return The LayoutParams associated with this view, or null if no
12375     *         parameters have been set yet
12376     */
12377    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12378    public ViewGroup.LayoutParams getLayoutParams() {
12379        return mLayoutParams;
12380    }
12381
12382    /**
12383     * Set the layout parameters associated with this view. These supply
12384     * parameters to the <i>parent</i> of this view specifying how it should be
12385     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12386     * correspond to the different subclasses of ViewGroup that are responsible
12387     * for arranging their children.
12388     *
12389     * @param params The layout parameters for this view, cannot be null
12390     */
12391    public void setLayoutParams(ViewGroup.LayoutParams params) {
12392        if (params == null) {
12393            throw new NullPointerException("Layout parameters cannot be null");
12394        }
12395        mLayoutParams = params;
12396        resolveLayoutParams();
12397        if (mParent instanceof ViewGroup) {
12398            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12399        }
12400        requestLayout();
12401    }
12402
12403    /**
12404     * Resolve the layout parameters depending on the resolved layout direction
12405     *
12406     * @hide
12407     */
12408    public void resolveLayoutParams() {
12409        if (mLayoutParams != null) {
12410            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12411        }
12412    }
12413
12414    /**
12415     * Set the scrolled position of your view. This will cause a call to
12416     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12417     * invalidated.
12418     * @param x the x position to scroll to
12419     * @param y the y position to scroll to
12420     */
12421    public void scrollTo(int x, int y) {
12422        if (mScrollX != x || mScrollY != y) {
12423            int oldX = mScrollX;
12424            int oldY = mScrollY;
12425            mScrollX = x;
12426            mScrollY = y;
12427            invalidateParentCaches();
12428            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12429            if (!awakenScrollBars()) {
12430                postInvalidateOnAnimation();
12431            }
12432        }
12433    }
12434
12435    /**
12436     * Move the scrolled position of your view. This will cause a call to
12437     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12438     * invalidated.
12439     * @param x the amount of pixels to scroll by horizontally
12440     * @param y the amount of pixels to scroll by vertically
12441     */
12442    public void scrollBy(int x, int y) {
12443        scrollTo(mScrollX + x, mScrollY + y);
12444    }
12445
12446    /**
12447     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12448     * animation to fade the scrollbars out after a default delay. If a subclass
12449     * provides animated scrolling, the start delay should equal the duration
12450     * of the scrolling animation.</p>
12451     *
12452     * <p>The animation starts only if at least one of the scrollbars is
12453     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12454     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12455     * this method returns true, and false otherwise. If the animation is
12456     * started, this method calls {@link #invalidate()}; in that case the
12457     * caller should not call {@link #invalidate()}.</p>
12458     *
12459     * <p>This method should be invoked every time a subclass directly updates
12460     * the scroll parameters.</p>
12461     *
12462     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12463     * and {@link #scrollTo(int, int)}.</p>
12464     *
12465     * @return true if the animation is played, false otherwise
12466     *
12467     * @see #awakenScrollBars(int)
12468     * @see #scrollBy(int, int)
12469     * @see #scrollTo(int, int)
12470     * @see #isHorizontalScrollBarEnabled()
12471     * @see #isVerticalScrollBarEnabled()
12472     * @see #setHorizontalScrollBarEnabled(boolean)
12473     * @see #setVerticalScrollBarEnabled(boolean)
12474     */
12475    protected boolean awakenScrollBars() {
12476        return mScrollCache != null &&
12477                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12478    }
12479
12480    /**
12481     * Trigger the scrollbars to draw.
12482     * This method differs from awakenScrollBars() only in its default duration.
12483     * initialAwakenScrollBars() will show the scroll bars for longer than
12484     * usual to give the user more of a chance to notice them.
12485     *
12486     * @return true if the animation is played, false otherwise.
12487     */
12488    private boolean initialAwakenScrollBars() {
12489        return mScrollCache != null &&
12490                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12491    }
12492
12493    /**
12494     * <p>
12495     * Trigger the scrollbars to draw. When invoked this method starts an
12496     * animation to fade the scrollbars out after a fixed delay. If a subclass
12497     * provides animated scrolling, the start delay should equal the duration of
12498     * the scrolling animation.
12499     * </p>
12500     *
12501     * <p>
12502     * The animation starts only if at least one of the scrollbars is enabled,
12503     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12504     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12505     * this method returns true, and false otherwise. If the animation is
12506     * started, this method calls {@link #invalidate()}; in that case the caller
12507     * should not call {@link #invalidate()}.
12508     * </p>
12509     *
12510     * <p>
12511     * This method should be invoked every time a subclass directly updates the
12512     * scroll parameters.
12513     * </p>
12514     *
12515     * @param startDelay the delay, in milliseconds, after which the animation
12516     *        should start; when the delay is 0, the animation starts
12517     *        immediately
12518     * @return true if the animation is played, false otherwise
12519     *
12520     * @see #scrollBy(int, int)
12521     * @see #scrollTo(int, int)
12522     * @see #isHorizontalScrollBarEnabled()
12523     * @see #isVerticalScrollBarEnabled()
12524     * @see #setHorizontalScrollBarEnabled(boolean)
12525     * @see #setVerticalScrollBarEnabled(boolean)
12526     */
12527    protected boolean awakenScrollBars(int startDelay) {
12528        return awakenScrollBars(startDelay, true);
12529    }
12530
12531    /**
12532     * <p>
12533     * Trigger the scrollbars to draw. When invoked this method starts an
12534     * animation to fade the scrollbars out after a fixed delay. If a subclass
12535     * provides animated scrolling, the start delay should equal the duration of
12536     * the scrolling animation.
12537     * </p>
12538     *
12539     * <p>
12540     * The animation starts only if at least one of the scrollbars is enabled,
12541     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12542     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12543     * this method returns true, and false otherwise. If the animation is
12544     * started, this method calls {@link #invalidate()} if the invalidate parameter
12545     * is set to true; in that case the caller
12546     * should not call {@link #invalidate()}.
12547     * </p>
12548     *
12549     * <p>
12550     * This method should be invoked every time a subclass directly updates the
12551     * scroll parameters.
12552     * </p>
12553     *
12554     * @param startDelay the delay, in milliseconds, after which the animation
12555     *        should start; when the delay is 0, the animation starts
12556     *        immediately
12557     *
12558     * @param invalidate Whether this method should call invalidate
12559     *
12560     * @return true if the animation is played, false otherwise
12561     *
12562     * @see #scrollBy(int, int)
12563     * @see #scrollTo(int, int)
12564     * @see #isHorizontalScrollBarEnabled()
12565     * @see #isVerticalScrollBarEnabled()
12566     * @see #setHorizontalScrollBarEnabled(boolean)
12567     * @see #setVerticalScrollBarEnabled(boolean)
12568     */
12569    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12570        final ScrollabilityCache scrollCache = mScrollCache;
12571
12572        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12573            return false;
12574        }
12575
12576        if (scrollCache.scrollBar == null) {
12577            scrollCache.scrollBar = new ScrollBarDrawable();
12578            scrollCache.scrollBar.setCallback(this);
12579            scrollCache.scrollBar.setState(getDrawableState());
12580        }
12581
12582        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12583
12584            if (invalidate) {
12585                // Invalidate to show the scrollbars
12586                postInvalidateOnAnimation();
12587            }
12588
12589            if (scrollCache.state == ScrollabilityCache.OFF) {
12590                // FIXME: this is copied from WindowManagerService.
12591                // We should get this value from the system when it
12592                // is possible to do so.
12593                final int KEY_REPEAT_FIRST_DELAY = 750;
12594                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12595            }
12596
12597            // Tell mScrollCache when we should start fading. This may
12598            // extend the fade start time if one was already scheduled
12599            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12600            scrollCache.fadeStartTime = fadeStartTime;
12601            scrollCache.state = ScrollabilityCache.ON;
12602
12603            // Schedule our fader to run, unscheduling any old ones first
12604            if (mAttachInfo != null) {
12605                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12606                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12607            }
12608
12609            return true;
12610        }
12611
12612        return false;
12613    }
12614
12615    /**
12616     * Do not invalidate views which are not visible and which are not running an animation. They
12617     * will not get drawn and they should not set dirty flags as if they will be drawn
12618     */
12619    private boolean skipInvalidate() {
12620        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12621                (!(mParent instanceof ViewGroup) ||
12622                        !((ViewGroup) mParent).isViewTransitioning(this));
12623    }
12624
12625    /**
12626     * Mark the area defined by dirty as needing to be drawn. If the view is
12627     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12628     * point in the future.
12629     * <p>
12630     * This must be called from a UI thread. To call from a non-UI thread, call
12631     * {@link #postInvalidate()}.
12632     * <p>
12633     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12634     * {@code dirty}.
12635     *
12636     * @param dirty the rectangle representing the bounds of the dirty region
12637     */
12638    public void invalidate(Rect dirty) {
12639        final int scrollX = mScrollX;
12640        final int scrollY = mScrollY;
12641        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12642                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12643    }
12644
12645    /**
12646     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12647     * coordinates of the dirty rect are relative to the view. If the view is
12648     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12649     * point in the future.
12650     * <p>
12651     * This must be called from a UI thread. To call from a non-UI thread, call
12652     * {@link #postInvalidate()}.
12653     *
12654     * @param l the left position of the dirty region
12655     * @param t the top position of the dirty region
12656     * @param r the right position of the dirty region
12657     * @param b the bottom position of the dirty region
12658     */
12659    public void invalidate(int l, int t, int r, int b) {
12660        final int scrollX = mScrollX;
12661        final int scrollY = mScrollY;
12662        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12663    }
12664
12665    /**
12666     * Invalidate the whole view. If the view is visible,
12667     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12668     * the future.
12669     * <p>
12670     * This must be called from a UI thread. To call from a non-UI thread, call
12671     * {@link #postInvalidate()}.
12672     */
12673    public void invalidate() {
12674        invalidate(true);
12675    }
12676
12677    /**
12678     * This is where the invalidate() work actually happens. A full invalidate()
12679     * causes the drawing cache to be invalidated, but this function can be
12680     * called with invalidateCache set to false to skip that invalidation step
12681     * for cases that do not need it (for example, a component that remains at
12682     * the same dimensions with the same content).
12683     *
12684     * @param invalidateCache Whether the drawing cache for this view should be
12685     *            invalidated as well. This is usually true for a full
12686     *            invalidate, but may be set to false if the View's contents or
12687     *            dimensions have not changed.
12688     */
12689    void invalidate(boolean invalidateCache) {
12690        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12691    }
12692
12693    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12694            boolean fullInvalidate) {
12695        if (mGhostView != null) {
12696            mGhostView.invalidate(true);
12697            return;
12698        }
12699
12700        if (skipInvalidate()) {
12701            return;
12702        }
12703
12704        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12705                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12706                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12707                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12708            if (fullInvalidate) {
12709                mLastIsOpaque = isOpaque();
12710                mPrivateFlags &= ~PFLAG_DRAWN;
12711            }
12712
12713            mPrivateFlags |= PFLAG_DIRTY;
12714
12715            if (invalidateCache) {
12716                mPrivateFlags |= PFLAG_INVALIDATED;
12717                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12718            }
12719
12720            // Propagate the damage rectangle to the parent view.
12721            final AttachInfo ai = mAttachInfo;
12722            final ViewParent p = mParent;
12723            if (p != null && ai != null && l < r && t < b) {
12724                final Rect damage = ai.mTmpInvalRect;
12725                damage.set(l, t, r, b);
12726                p.invalidateChild(this, damage);
12727            }
12728
12729            // Damage the entire projection receiver, if necessary.
12730            if (mBackground != null && mBackground.isProjected()) {
12731                final View receiver = getProjectionReceiver();
12732                if (receiver != null) {
12733                    receiver.damageInParent();
12734                }
12735            }
12736
12737            // Damage the entire IsolatedZVolume receiving this view's shadow.
12738            if (isHardwareAccelerated() && getZ() != 0) {
12739                damageShadowReceiver();
12740            }
12741        }
12742    }
12743
12744    /**
12745     * @return this view's projection receiver, or {@code null} if none exists
12746     */
12747    private View getProjectionReceiver() {
12748        ViewParent p = getParent();
12749        while (p != null && p instanceof View) {
12750            final View v = (View) p;
12751            if (v.isProjectionReceiver()) {
12752                return v;
12753            }
12754            p = p.getParent();
12755        }
12756
12757        return null;
12758    }
12759
12760    /**
12761     * @return whether the view is a projection receiver
12762     */
12763    private boolean isProjectionReceiver() {
12764        return mBackground != null;
12765    }
12766
12767    /**
12768     * Damage area of the screen that can be covered by this View's shadow.
12769     *
12770     * This method will guarantee that any changes to shadows cast by a View
12771     * are damaged on the screen for future redraw.
12772     */
12773    private void damageShadowReceiver() {
12774        final AttachInfo ai = mAttachInfo;
12775        if (ai != null) {
12776            ViewParent p = getParent();
12777            if (p != null && p instanceof ViewGroup) {
12778                final ViewGroup vg = (ViewGroup) p;
12779                vg.damageInParent();
12780            }
12781        }
12782    }
12783
12784    /**
12785     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12786     * set any flags or handle all of the cases handled by the default invalidation methods.
12787     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12788     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12789     * walk up the hierarchy, transforming the dirty rect as necessary.
12790     *
12791     * The method also handles normal invalidation logic if display list properties are not
12792     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12793     * backup approach, to handle these cases used in the various property-setting methods.
12794     *
12795     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12796     * are not being used in this view
12797     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12798     * list properties are not being used in this view
12799     */
12800    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12801        if (!isHardwareAccelerated()
12802                || !mRenderNode.isValid()
12803                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12804            if (invalidateParent) {
12805                invalidateParentCaches();
12806            }
12807            if (forceRedraw) {
12808                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12809            }
12810            invalidate(false);
12811        } else {
12812            damageInParent();
12813        }
12814        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12815            damageShadowReceiver();
12816        }
12817    }
12818
12819    /**
12820     * Tells the parent view to damage this view's bounds.
12821     *
12822     * @hide
12823     */
12824    protected void damageInParent() {
12825        final AttachInfo ai = mAttachInfo;
12826        final ViewParent p = mParent;
12827        if (p != null && ai != null) {
12828            final Rect r = ai.mTmpInvalRect;
12829            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12830            if (mParent instanceof ViewGroup) {
12831                ((ViewGroup) mParent).damageChild(this, r);
12832            } else {
12833                mParent.invalidateChild(this, r);
12834            }
12835        }
12836    }
12837
12838    /**
12839     * Utility method to transform a given Rect by the current matrix of this view.
12840     */
12841    void transformRect(final Rect rect) {
12842        if (!getMatrix().isIdentity()) {
12843            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12844            boundingRect.set(rect);
12845            getMatrix().mapRect(boundingRect);
12846            rect.set((int) Math.floor(boundingRect.left),
12847                    (int) Math.floor(boundingRect.top),
12848                    (int) Math.ceil(boundingRect.right),
12849                    (int) Math.ceil(boundingRect.bottom));
12850        }
12851    }
12852
12853    /**
12854     * Used to indicate that the parent of this view should clear its caches. This functionality
12855     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12856     * which is necessary when various parent-managed properties of the view change, such as
12857     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12858     * clears the parent caches and does not causes an invalidate event.
12859     *
12860     * @hide
12861     */
12862    protected void invalidateParentCaches() {
12863        if (mParent instanceof View) {
12864            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12865        }
12866    }
12867
12868    /**
12869     * Used to indicate that the parent of this view should be invalidated. This functionality
12870     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12871     * which is necessary when various parent-managed properties of the view change, such as
12872     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12873     * an invalidation event to the parent.
12874     *
12875     * @hide
12876     */
12877    protected void invalidateParentIfNeeded() {
12878        if (isHardwareAccelerated() && mParent instanceof View) {
12879            ((View) mParent).invalidate(true);
12880        }
12881    }
12882
12883    /**
12884     * @hide
12885     */
12886    protected void invalidateParentIfNeededAndWasQuickRejected() {
12887        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12888            // View was rejected last time it was drawn by its parent; this may have changed
12889            invalidateParentIfNeeded();
12890        }
12891    }
12892
12893    /**
12894     * Indicates whether this View is opaque. An opaque View guarantees that it will
12895     * draw all the pixels overlapping its bounds using a fully opaque color.
12896     *
12897     * Subclasses of View should override this method whenever possible to indicate
12898     * whether an instance is opaque. Opaque Views are treated in a special way by
12899     * the View hierarchy, possibly allowing it to perform optimizations during
12900     * invalidate/draw passes.
12901     *
12902     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12903     */
12904    @ViewDebug.ExportedProperty(category = "drawing")
12905    public boolean isOpaque() {
12906        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12907                getFinalAlpha() >= 1.0f;
12908    }
12909
12910    /**
12911     * @hide
12912     */
12913    protected void computeOpaqueFlags() {
12914        // Opaque if:
12915        //   - Has a background
12916        //   - Background is opaque
12917        //   - Doesn't have scrollbars or scrollbars overlay
12918
12919        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12920            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12921        } else {
12922            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12923        }
12924
12925        final int flags = mViewFlags;
12926        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12927                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12928                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12929            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12930        } else {
12931            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12932        }
12933    }
12934
12935    /**
12936     * @hide
12937     */
12938    protected boolean hasOpaqueScrollbars() {
12939        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12940    }
12941
12942    /**
12943     * @return A handler associated with the thread running the View. This
12944     * handler can be used to pump events in the UI events queue.
12945     */
12946    public Handler getHandler() {
12947        final AttachInfo attachInfo = mAttachInfo;
12948        if (attachInfo != null) {
12949            return attachInfo.mHandler;
12950        }
12951        return null;
12952    }
12953
12954    /**
12955     * Gets the view root associated with the View.
12956     * @return The view root, or null if none.
12957     * @hide
12958     */
12959    public ViewRootImpl getViewRootImpl() {
12960        if (mAttachInfo != null) {
12961            return mAttachInfo.mViewRootImpl;
12962        }
12963        return null;
12964    }
12965
12966    /**
12967     * @hide
12968     */
12969    public HardwareRenderer getHardwareRenderer() {
12970        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12971    }
12972
12973    /**
12974     * <p>Causes the Runnable to be added to the message queue.
12975     * The runnable will be run on the user interface thread.</p>
12976     *
12977     * @param action The Runnable that will be executed.
12978     *
12979     * @return Returns true if the Runnable was successfully placed in to the
12980     *         message queue.  Returns false on failure, usually because the
12981     *         looper processing the message queue is exiting.
12982     *
12983     * @see #postDelayed
12984     * @see #removeCallbacks
12985     */
12986    public boolean post(Runnable action) {
12987        final AttachInfo attachInfo = mAttachInfo;
12988        if (attachInfo != null) {
12989            return attachInfo.mHandler.post(action);
12990        }
12991        // Assume that post will succeed later
12992        ViewRootImpl.getRunQueue().post(action);
12993        return true;
12994    }
12995
12996    /**
12997     * <p>Causes the Runnable to be added to the message queue, to be run
12998     * after the specified amount of time elapses.
12999     * The runnable will be run on the user interface thread.</p>
13000     *
13001     * @param action The Runnable that will be executed.
13002     * @param delayMillis The delay (in milliseconds) until the Runnable
13003     *        will be executed.
13004     *
13005     * @return true if the Runnable was successfully placed in to the
13006     *         message queue.  Returns false on failure, usually because the
13007     *         looper processing the message queue is exiting.  Note that a
13008     *         result of true does not mean the Runnable will be processed --
13009     *         if the looper is quit before the delivery time of the message
13010     *         occurs then the message will be dropped.
13011     *
13012     * @see #post
13013     * @see #removeCallbacks
13014     */
13015    public boolean postDelayed(Runnable action, long delayMillis) {
13016        final AttachInfo attachInfo = mAttachInfo;
13017        if (attachInfo != null) {
13018            return attachInfo.mHandler.postDelayed(action, delayMillis);
13019        }
13020        // Assume that post will succeed later
13021        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13022        return true;
13023    }
13024
13025    /**
13026     * <p>Causes the Runnable to execute on the next animation time step.
13027     * The runnable will be run on the user interface thread.</p>
13028     *
13029     * @param action The Runnable that will be executed.
13030     *
13031     * @see #postOnAnimationDelayed
13032     * @see #removeCallbacks
13033     */
13034    public void postOnAnimation(Runnable action) {
13035        final AttachInfo attachInfo = mAttachInfo;
13036        if (attachInfo != null) {
13037            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13038                    Choreographer.CALLBACK_ANIMATION, action, null);
13039        } else {
13040            // Assume that post will succeed later
13041            ViewRootImpl.getRunQueue().post(action);
13042        }
13043    }
13044
13045    /**
13046     * <p>Causes the Runnable to execute on the next animation time step,
13047     * after the specified amount of time elapses.
13048     * The runnable will be run on the user interface thread.</p>
13049     *
13050     * @param action The Runnable that will be executed.
13051     * @param delayMillis The delay (in milliseconds) until the Runnable
13052     *        will be executed.
13053     *
13054     * @see #postOnAnimation
13055     * @see #removeCallbacks
13056     */
13057    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13058        final AttachInfo attachInfo = mAttachInfo;
13059        if (attachInfo != null) {
13060            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13061                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13062        } else {
13063            // Assume that post will succeed later
13064            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13065        }
13066    }
13067
13068    /**
13069     * <p>Removes the specified Runnable from the message queue.</p>
13070     *
13071     * @param action The Runnable to remove from the message handling queue
13072     *
13073     * @return true if this view could ask the Handler to remove the Runnable,
13074     *         false otherwise. When the returned value is true, the Runnable
13075     *         may or may not have been actually removed from the message queue
13076     *         (for instance, if the Runnable was not in the queue already.)
13077     *
13078     * @see #post
13079     * @see #postDelayed
13080     * @see #postOnAnimation
13081     * @see #postOnAnimationDelayed
13082     */
13083    public boolean removeCallbacks(Runnable action) {
13084        if (action != null) {
13085            final AttachInfo attachInfo = mAttachInfo;
13086            if (attachInfo != null) {
13087                attachInfo.mHandler.removeCallbacks(action);
13088                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13089                        Choreographer.CALLBACK_ANIMATION, action, null);
13090            }
13091            // Assume that post will succeed later
13092            ViewRootImpl.getRunQueue().removeCallbacks(action);
13093        }
13094        return true;
13095    }
13096
13097    /**
13098     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13099     * Use this to invalidate the View from a non-UI thread.</p>
13100     *
13101     * <p>This method can be invoked from outside of the UI thread
13102     * only when this View is attached to a window.</p>
13103     *
13104     * @see #invalidate()
13105     * @see #postInvalidateDelayed(long)
13106     */
13107    public void postInvalidate() {
13108        postInvalidateDelayed(0);
13109    }
13110
13111    /**
13112     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13113     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13114     *
13115     * <p>This method can be invoked from outside of the UI thread
13116     * only when this View is attached to a window.</p>
13117     *
13118     * @param left The left coordinate of the rectangle to invalidate.
13119     * @param top The top coordinate of the rectangle to invalidate.
13120     * @param right The right coordinate of the rectangle to invalidate.
13121     * @param bottom The bottom coordinate of the rectangle to invalidate.
13122     *
13123     * @see #invalidate(int, int, int, int)
13124     * @see #invalidate(Rect)
13125     * @see #postInvalidateDelayed(long, int, int, int, int)
13126     */
13127    public void postInvalidate(int left, int top, int right, int bottom) {
13128        postInvalidateDelayed(0, left, top, right, bottom);
13129    }
13130
13131    /**
13132     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13133     * loop. Waits for the specified amount of time.</p>
13134     *
13135     * <p>This method can be invoked from outside of the UI thread
13136     * only when this View is attached to a window.</p>
13137     *
13138     * @param delayMilliseconds the duration in milliseconds to delay the
13139     *         invalidation by
13140     *
13141     * @see #invalidate()
13142     * @see #postInvalidate()
13143     */
13144    public void postInvalidateDelayed(long delayMilliseconds) {
13145        // We try only with the AttachInfo because there's no point in invalidating
13146        // if we are not attached to our window
13147        final AttachInfo attachInfo = mAttachInfo;
13148        if (attachInfo != null) {
13149            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13150        }
13151    }
13152
13153    /**
13154     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13155     * through the event loop. Waits for the specified amount of time.</p>
13156     *
13157     * <p>This method can be invoked from outside of the UI thread
13158     * only when this View is attached to a window.</p>
13159     *
13160     * @param delayMilliseconds the duration in milliseconds to delay the
13161     *         invalidation by
13162     * @param left The left coordinate of the rectangle to invalidate.
13163     * @param top The top coordinate of the rectangle to invalidate.
13164     * @param right The right coordinate of the rectangle to invalidate.
13165     * @param bottom The bottom coordinate of the rectangle to invalidate.
13166     *
13167     * @see #invalidate(int, int, int, int)
13168     * @see #invalidate(Rect)
13169     * @see #postInvalidate(int, int, int, int)
13170     */
13171    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13172            int right, int bottom) {
13173
13174        // We try only with the AttachInfo because there's no point in invalidating
13175        // if we are not attached to our window
13176        final AttachInfo attachInfo = mAttachInfo;
13177        if (attachInfo != null) {
13178            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13179            info.target = this;
13180            info.left = left;
13181            info.top = top;
13182            info.right = right;
13183            info.bottom = bottom;
13184
13185            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13186        }
13187    }
13188
13189    /**
13190     * <p>Cause an invalidate to happen on the next animation time step, typically the
13191     * next display frame.</p>
13192     *
13193     * <p>This method can be invoked from outside of the UI thread
13194     * only when this View is attached to a window.</p>
13195     *
13196     * @see #invalidate()
13197     */
13198    public void postInvalidateOnAnimation() {
13199        // We try only with the AttachInfo because there's no point in invalidating
13200        // if we are not attached to our window
13201        final AttachInfo attachInfo = mAttachInfo;
13202        if (attachInfo != null) {
13203            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13204        }
13205    }
13206
13207    /**
13208     * <p>Cause an invalidate of the specified area to happen on the next animation
13209     * time step, typically the next display frame.</p>
13210     *
13211     * <p>This method can be invoked from outside of the UI thread
13212     * only when this View is attached to a window.</p>
13213     *
13214     * @param left The left coordinate of the rectangle to invalidate.
13215     * @param top The top coordinate of the rectangle to invalidate.
13216     * @param right The right coordinate of the rectangle to invalidate.
13217     * @param bottom The bottom coordinate of the rectangle to invalidate.
13218     *
13219     * @see #invalidate(int, int, int, int)
13220     * @see #invalidate(Rect)
13221     */
13222    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13223        // We try only with the AttachInfo because there's no point in invalidating
13224        // if we are not attached to our window
13225        final AttachInfo attachInfo = mAttachInfo;
13226        if (attachInfo != null) {
13227            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13228            info.target = this;
13229            info.left = left;
13230            info.top = top;
13231            info.right = right;
13232            info.bottom = bottom;
13233
13234            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13235        }
13236    }
13237
13238    /**
13239     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13240     * This event is sent at most once every
13241     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13242     */
13243    private void postSendViewScrolledAccessibilityEventCallback() {
13244        if (mSendViewScrolledAccessibilityEvent == null) {
13245            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13246        }
13247        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13248            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13249            postDelayed(mSendViewScrolledAccessibilityEvent,
13250                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13251        }
13252    }
13253
13254    /**
13255     * Called by a parent to request that a child update its values for mScrollX
13256     * and mScrollY if necessary. This will typically be done if the child is
13257     * animating a scroll using a {@link android.widget.Scroller Scroller}
13258     * object.
13259     */
13260    public void computeScroll() {
13261    }
13262
13263    /**
13264     * <p>Indicate whether the horizontal edges are faded when the view is
13265     * scrolled horizontally.</p>
13266     *
13267     * @return true if the horizontal edges should are faded on scroll, false
13268     *         otherwise
13269     *
13270     * @see #setHorizontalFadingEdgeEnabled(boolean)
13271     *
13272     * @attr ref android.R.styleable#View_requiresFadingEdge
13273     */
13274    public boolean isHorizontalFadingEdgeEnabled() {
13275        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13276    }
13277
13278    /**
13279     * <p>Define whether the horizontal edges should be faded when this view
13280     * is scrolled horizontally.</p>
13281     *
13282     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13283     *                                    be faded when the view is scrolled
13284     *                                    horizontally
13285     *
13286     * @see #isHorizontalFadingEdgeEnabled()
13287     *
13288     * @attr ref android.R.styleable#View_requiresFadingEdge
13289     */
13290    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13291        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13292            if (horizontalFadingEdgeEnabled) {
13293                initScrollCache();
13294            }
13295
13296            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13297        }
13298    }
13299
13300    /**
13301     * <p>Indicate whether the vertical edges are faded when the view is
13302     * scrolled horizontally.</p>
13303     *
13304     * @return true if the vertical edges should are faded on scroll, false
13305     *         otherwise
13306     *
13307     * @see #setVerticalFadingEdgeEnabled(boolean)
13308     *
13309     * @attr ref android.R.styleable#View_requiresFadingEdge
13310     */
13311    public boolean isVerticalFadingEdgeEnabled() {
13312        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13313    }
13314
13315    /**
13316     * <p>Define whether the vertical edges should be faded when this view
13317     * is scrolled vertically.</p>
13318     *
13319     * @param verticalFadingEdgeEnabled true if the vertical edges should
13320     *                                  be faded when the view is scrolled
13321     *                                  vertically
13322     *
13323     * @see #isVerticalFadingEdgeEnabled()
13324     *
13325     * @attr ref android.R.styleable#View_requiresFadingEdge
13326     */
13327    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13328        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13329            if (verticalFadingEdgeEnabled) {
13330                initScrollCache();
13331            }
13332
13333            mViewFlags ^= FADING_EDGE_VERTICAL;
13334        }
13335    }
13336
13337    /**
13338     * Returns the strength, or intensity, of the top faded edge. The strength is
13339     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13340     * returns 0.0 or 1.0 but no value in between.
13341     *
13342     * Subclasses should override this method to provide a smoother fade transition
13343     * when scrolling occurs.
13344     *
13345     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13346     */
13347    protected float getTopFadingEdgeStrength() {
13348        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13349    }
13350
13351    /**
13352     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13353     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13354     * returns 0.0 or 1.0 but no value in between.
13355     *
13356     * Subclasses should override this method to provide a smoother fade transition
13357     * when scrolling occurs.
13358     *
13359     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13360     */
13361    protected float getBottomFadingEdgeStrength() {
13362        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13363                computeVerticalScrollRange() ? 1.0f : 0.0f;
13364    }
13365
13366    /**
13367     * Returns the strength, or intensity, of the left faded edge. The strength is
13368     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13369     * returns 0.0 or 1.0 but no value in between.
13370     *
13371     * Subclasses should override this method to provide a smoother fade transition
13372     * when scrolling occurs.
13373     *
13374     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13375     */
13376    protected float getLeftFadingEdgeStrength() {
13377        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13378    }
13379
13380    /**
13381     * Returns the strength, or intensity, of the right faded edge. The strength is
13382     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13383     * returns 0.0 or 1.0 but no value in between.
13384     *
13385     * Subclasses should override this method to provide a smoother fade transition
13386     * when scrolling occurs.
13387     *
13388     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13389     */
13390    protected float getRightFadingEdgeStrength() {
13391        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13392                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13393    }
13394
13395    /**
13396     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13397     * scrollbar is not drawn by default.</p>
13398     *
13399     * @return true if the horizontal scrollbar should be painted, false
13400     *         otherwise
13401     *
13402     * @see #setHorizontalScrollBarEnabled(boolean)
13403     */
13404    public boolean isHorizontalScrollBarEnabled() {
13405        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13406    }
13407
13408    /**
13409     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13410     * scrollbar is not drawn by default.</p>
13411     *
13412     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13413     *                                   be painted
13414     *
13415     * @see #isHorizontalScrollBarEnabled()
13416     */
13417    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13418        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13419            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13420            computeOpaqueFlags();
13421            resolvePadding();
13422        }
13423    }
13424
13425    /**
13426     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13427     * scrollbar is not drawn by default.</p>
13428     *
13429     * @return true if the vertical scrollbar should be painted, false
13430     *         otherwise
13431     *
13432     * @see #setVerticalScrollBarEnabled(boolean)
13433     */
13434    public boolean isVerticalScrollBarEnabled() {
13435        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13436    }
13437
13438    /**
13439     * <p>Define whether the vertical scrollbar should be drawn or not. The
13440     * scrollbar is not drawn by default.</p>
13441     *
13442     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13443     *                                 be painted
13444     *
13445     * @see #isVerticalScrollBarEnabled()
13446     */
13447    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13448        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13449            mViewFlags ^= SCROLLBARS_VERTICAL;
13450            computeOpaqueFlags();
13451            resolvePadding();
13452        }
13453    }
13454
13455    /**
13456     * @hide
13457     */
13458    protected void recomputePadding() {
13459        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13460    }
13461
13462    /**
13463     * Define whether scrollbars will fade when the view is not scrolling.
13464     *
13465     * @param fadeScrollbars whether to enable fading
13466     *
13467     * @attr ref android.R.styleable#View_fadeScrollbars
13468     */
13469    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13470        initScrollCache();
13471        final ScrollabilityCache scrollabilityCache = mScrollCache;
13472        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13473        if (fadeScrollbars) {
13474            scrollabilityCache.state = ScrollabilityCache.OFF;
13475        } else {
13476            scrollabilityCache.state = ScrollabilityCache.ON;
13477        }
13478    }
13479
13480    /**
13481     *
13482     * Returns true if scrollbars will fade when this view is not scrolling
13483     *
13484     * @return true if scrollbar fading is enabled
13485     *
13486     * @attr ref android.R.styleable#View_fadeScrollbars
13487     */
13488    public boolean isScrollbarFadingEnabled() {
13489        return mScrollCache != null && mScrollCache.fadeScrollBars;
13490    }
13491
13492    /**
13493     *
13494     * Returns the delay before scrollbars fade.
13495     *
13496     * @return the delay before scrollbars fade
13497     *
13498     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13499     */
13500    public int getScrollBarDefaultDelayBeforeFade() {
13501        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13502                mScrollCache.scrollBarDefaultDelayBeforeFade;
13503    }
13504
13505    /**
13506     * Define the delay before scrollbars fade.
13507     *
13508     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13509     *
13510     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13511     */
13512    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13513        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13514    }
13515
13516    /**
13517     *
13518     * Returns the scrollbar fade duration.
13519     *
13520     * @return the scrollbar fade duration
13521     *
13522     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13523     */
13524    public int getScrollBarFadeDuration() {
13525        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13526                mScrollCache.scrollBarFadeDuration;
13527    }
13528
13529    /**
13530     * Define the scrollbar fade duration.
13531     *
13532     * @param scrollBarFadeDuration - the scrollbar fade duration
13533     *
13534     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13535     */
13536    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13537        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13538    }
13539
13540    /**
13541     *
13542     * Returns the scrollbar size.
13543     *
13544     * @return the scrollbar size
13545     *
13546     * @attr ref android.R.styleable#View_scrollbarSize
13547     */
13548    public int getScrollBarSize() {
13549        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13550                mScrollCache.scrollBarSize;
13551    }
13552
13553    /**
13554     * Define the scrollbar size.
13555     *
13556     * @param scrollBarSize - the scrollbar size
13557     *
13558     * @attr ref android.R.styleable#View_scrollbarSize
13559     */
13560    public void setScrollBarSize(int scrollBarSize) {
13561        getScrollCache().scrollBarSize = scrollBarSize;
13562    }
13563
13564    /**
13565     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13566     * inset. When inset, they add to the padding of the view. And the scrollbars
13567     * can be drawn inside the padding area or on the edge of the view. For example,
13568     * if a view has a background drawable and you want to draw the scrollbars
13569     * inside the padding specified by the drawable, you can use
13570     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13571     * appear at the edge of the view, ignoring the padding, then you can use
13572     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13573     * @param style the style of the scrollbars. Should be one of
13574     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13575     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13576     * @see #SCROLLBARS_INSIDE_OVERLAY
13577     * @see #SCROLLBARS_INSIDE_INSET
13578     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13579     * @see #SCROLLBARS_OUTSIDE_INSET
13580     *
13581     * @attr ref android.R.styleable#View_scrollbarStyle
13582     */
13583    public void setScrollBarStyle(@ScrollBarStyle int style) {
13584        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13585            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13586            computeOpaqueFlags();
13587            resolvePadding();
13588        }
13589    }
13590
13591    /**
13592     * <p>Returns the current scrollbar style.</p>
13593     * @return the current scrollbar style
13594     * @see #SCROLLBARS_INSIDE_OVERLAY
13595     * @see #SCROLLBARS_INSIDE_INSET
13596     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13597     * @see #SCROLLBARS_OUTSIDE_INSET
13598     *
13599     * @attr ref android.R.styleable#View_scrollbarStyle
13600     */
13601    @ViewDebug.ExportedProperty(mapping = {
13602            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13603            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13604            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13605            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13606    })
13607    @ScrollBarStyle
13608    public int getScrollBarStyle() {
13609        return mViewFlags & SCROLLBARS_STYLE_MASK;
13610    }
13611
13612    /**
13613     * <p>Compute the horizontal range that the horizontal scrollbar
13614     * represents.</p>
13615     *
13616     * <p>The range is expressed in arbitrary units that must be the same as the
13617     * units used by {@link #computeHorizontalScrollExtent()} and
13618     * {@link #computeHorizontalScrollOffset()}.</p>
13619     *
13620     * <p>The default range is the drawing width of this view.</p>
13621     *
13622     * @return the total horizontal range represented by the horizontal
13623     *         scrollbar
13624     *
13625     * @see #computeHorizontalScrollExtent()
13626     * @see #computeHorizontalScrollOffset()
13627     * @see android.widget.ScrollBarDrawable
13628     */
13629    protected int computeHorizontalScrollRange() {
13630        return getWidth();
13631    }
13632
13633    /**
13634     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13635     * within the horizontal range. This value is used to compute the position
13636     * of the thumb within the scrollbar's track.</p>
13637     *
13638     * <p>The range is expressed in arbitrary units that must be the same as the
13639     * units used by {@link #computeHorizontalScrollRange()} and
13640     * {@link #computeHorizontalScrollExtent()}.</p>
13641     *
13642     * <p>The default offset is the scroll offset of this view.</p>
13643     *
13644     * @return the horizontal offset of the scrollbar's thumb
13645     *
13646     * @see #computeHorizontalScrollRange()
13647     * @see #computeHorizontalScrollExtent()
13648     * @see android.widget.ScrollBarDrawable
13649     */
13650    protected int computeHorizontalScrollOffset() {
13651        return mScrollX;
13652    }
13653
13654    /**
13655     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13656     * within the horizontal range. This value is used to compute the length
13657     * of the thumb within the scrollbar's track.</p>
13658     *
13659     * <p>The range is expressed in arbitrary units that must be the same as the
13660     * units used by {@link #computeHorizontalScrollRange()} and
13661     * {@link #computeHorizontalScrollOffset()}.</p>
13662     *
13663     * <p>The default extent is the drawing width of this view.</p>
13664     *
13665     * @return the horizontal extent of the scrollbar's thumb
13666     *
13667     * @see #computeHorizontalScrollRange()
13668     * @see #computeHorizontalScrollOffset()
13669     * @see android.widget.ScrollBarDrawable
13670     */
13671    protected int computeHorizontalScrollExtent() {
13672        return getWidth();
13673    }
13674
13675    /**
13676     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13677     *
13678     * <p>The range is expressed in arbitrary units that must be the same as the
13679     * units used by {@link #computeVerticalScrollExtent()} and
13680     * {@link #computeVerticalScrollOffset()}.</p>
13681     *
13682     * @return the total vertical range represented by the vertical scrollbar
13683     *
13684     * <p>The default range is the drawing height of this view.</p>
13685     *
13686     * @see #computeVerticalScrollExtent()
13687     * @see #computeVerticalScrollOffset()
13688     * @see android.widget.ScrollBarDrawable
13689     */
13690    protected int computeVerticalScrollRange() {
13691        return getHeight();
13692    }
13693
13694    /**
13695     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13696     * within the horizontal range. This value is used to compute the position
13697     * of the thumb within the scrollbar's track.</p>
13698     *
13699     * <p>The range is expressed in arbitrary units that must be the same as the
13700     * units used by {@link #computeVerticalScrollRange()} and
13701     * {@link #computeVerticalScrollExtent()}.</p>
13702     *
13703     * <p>The default offset is the scroll offset of this view.</p>
13704     *
13705     * @return the vertical offset of the scrollbar's thumb
13706     *
13707     * @see #computeVerticalScrollRange()
13708     * @see #computeVerticalScrollExtent()
13709     * @see android.widget.ScrollBarDrawable
13710     */
13711    protected int computeVerticalScrollOffset() {
13712        return mScrollY;
13713    }
13714
13715    /**
13716     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13717     * within the vertical range. This value is used to compute the length
13718     * of the thumb within the scrollbar's track.</p>
13719     *
13720     * <p>The range is expressed in arbitrary units that must be the same as the
13721     * units used by {@link #computeVerticalScrollRange()} and
13722     * {@link #computeVerticalScrollOffset()}.</p>
13723     *
13724     * <p>The default extent is the drawing height of this view.</p>
13725     *
13726     * @return the vertical extent of the scrollbar's thumb
13727     *
13728     * @see #computeVerticalScrollRange()
13729     * @see #computeVerticalScrollOffset()
13730     * @see android.widget.ScrollBarDrawable
13731     */
13732    protected int computeVerticalScrollExtent() {
13733        return getHeight();
13734    }
13735
13736    /**
13737     * Check if this view can be scrolled horizontally in a certain direction.
13738     *
13739     * @param direction Negative to check scrolling left, positive to check scrolling right.
13740     * @return true if this view can be scrolled in the specified direction, false otherwise.
13741     */
13742    public boolean canScrollHorizontally(int direction) {
13743        final int offset = computeHorizontalScrollOffset();
13744        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13745        if (range == 0) return false;
13746        if (direction < 0) {
13747            return offset > 0;
13748        } else {
13749            return offset < range - 1;
13750        }
13751    }
13752
13753    /**
13754     * Check if this view can be scrolled vertically in a certain direction.
13755     *
13756     * @param direction Negative to check scrolling up, positive to check scrolling down.
13757     * @return true if this view can be scrolled in the specified direction, false otherwise.
13758     */
13759    public boolean canScrollVertically(int direction) {
13760        final int offset = computeVerticalScrollOffset();
13761        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13762        if (range == 0) return false;
13763        if (direction < 0) {
13764            return offset > 0;
13765        } else {
13766            return offset < range - 1;
13767        }
13768    }
13769
13770    void getScrollIndicatorBounds(@NonNull Rect out) {
13771        out.left = mScrollX;
13772        out.right = mScrollX + mRight - mLeft;
13773        out.top = mScrollY;
13774        out.bottom = mScrollY + mBottom - mTop;
13775    }
13776
13777    private void onDrawScrollIndicators(Canvas c) {
13778        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13779            // No scroll indicators enabled.
13780            return;
13781        }
13782
13783        final Drawable dr = mScrollIndicatorDrawable;
13784        if (dr == null) {
13785            // Scroll indicators aren't supported here.
13786            return;
13787        }
13788
13789        final int h = dr.getIntrinsicHeight();
13790        final int w = dr.getIntrinsicWidth();
13791        final Rect rect = mAttachInfo.mTmpInvalRect;
13792        getScrollIndicatorBounds(rect);
13793
13794        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13795            final boolean canScrollUp = canScrollVertically(-1);
13796            if (canScrollUp) {
13797                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13798                dr.draw(c);
13799            }
13800        }
13801
13802        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13803            final boolean canScrollDown = canScrollVertically(1);
13804            if (canScrollDown) {
13805                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13806                dr.draw(c);
13807            }
13808        }
13809
13810        final int leftRtl;
13811        final int rightRtl;
13812        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13813            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13814            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13815        } else {
13816            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13817            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13818        }
13819
13820        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13821        if ((mPrivateFlags3 & leftMask) != 0) {
13822            final boolean canScrollLeft = canScrollHorizontally(-1);
13823            if (canScrollLeft) {
13824                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13825                dr.draw(c);
13826            }
13827        }
13828
13829        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13830        if ((mPrivateFlags3 & rightMask) != 0) {
13831            final boolean canScrollRight = canScrollHorizontally(1);
13832            if (canScrollRight) {
13833                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13834                dr.draw(c);
13835            }
13836        }
13837    }
13838
13839    /**
13840     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13841     * scrollbars are painted only if they have been awakened first.</p>
13842     *
13843     * @param canvas the canvas on which to draw the scrollbars
13844     *
13845     * @see #awakenScrollBars(int)
13846     */
13847    protected final void onDrawScrollBars(Canvas canvas) {
13848        // scrollbars are drawn only when the animation is running
13849        final ScrollabilityCache cache = mScrollCache;
13850        if (cache != null) {
13851
13852            int state = cache.state;
13853
13854            if (state == ScrollabilityCache.OFF) {
13855                return;
13856            }
13857
13858            boolean invalidate = false;
13859
13860            if (state == ScrollabilityCache.FADING) {
13861                // We're fading -- get our fade interpolation
13862                if (cache.interpolatorValues == null) {
13863                    cache.interpolatorValues = new float[1];
13864                }
13865
13866                float[] values = cache.interpolatorValues;
13867
13868                // Stops the animation if we're done
13869                if (cache.scrollBarInterpolator.timeToValues(values) ==
13870                        Interpolator.Result.FREEZE_END) {
13871                    cache.state = ScrollabilityCache.OFF;
13872                } else {
13873                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13874                }
13875
13876                // This will make the scroll bars inval themselves after
13877                // drawing. We only want this when we're fading so that
13878                // we prevent excessive redraws
13879                invalidate = true;
13880            } else {
13881                // We're just on -- but we may have been fading before so
13882                // reset alpha
13883                cache.scrollBar.mutate().setAlpha(255);
13884            }
13885
13886
13887            final int viewFlags = mViewFlags;
13888
13889            final boolean drawHorizontalScrollBar =
13890                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13891            final boolean drawVerticalScrollBar =
13892                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13893                && !isVerticalScrollBarHidden();
13894
13895            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13896                final int width = mRight - mLeft;
13897                final int height = mBottom - mTop;
13898
13899                final ScrollBarDrawable scrollBar = cache.scrollBar;
13900
13901                final int scrollX = mScrollX;
13902                final int scrollY = mScrollY;
13903                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13904
13905                int left;
13906                int top;
13907                int right;
13908                int bottom;
13909
13910                if (drawHorizontalScrollBar) {
13911                    int size = scrollBar.getSize(false);
13912                    if (size <= 0) {
13913                        size = cache.scrollBarSize;
13914                    }
13915
13916                    scrollBar.setParameters(computeHorizontalScrollRange(),
13917                                            computeHorizontalScrollOffset(),
13918                                            computeHorizontalScrollExtent(), false);
13919                    final int verticalScrollBarGap = drawVerticalScrollBar ?
13920                            getVerticalScrollbarWidth() : 0;
13921                    top = scrollY + height - size - (mUserPaddingBottom & inside);
13922                    left = scrollX + (mPaddingLeft & inside);
13923                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13924                    bottom = top + size;
13925                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13926                    if (invalidate) {
13927                        invalidate(left, top, right, bottom);
13928                    }
13929                }
13930
13931                if (drawVerticalScrollBar) {
13932                    int size = scrollBar.getSize(true);
13933                    if (size <= 0) {
13934                        size = cache.scrollBarSize;
13935                    }
13936
13937                    scrollBar.setParameters(computeVerticalScrollRange(),
13938                                            computeVerticalScrollOffset(),
13939                                            computeVerticalScrollExtent(), true);
13940                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
13941                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13942                        verticalScrollbarPosition = isLayoutRtl() ?
13943                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13944                    }
13945                    switch (verticalScrollbarPosition) {
13946                        default:
13947                        case SCROLLBAR_POSITION_RIGHT:
13948                            left = scrollX + width - size - (mUserPaddingRight & inside);
13949                            break;
13950                        case SCROLLBAR_POSITION_LEFT:
13951                            left = scrollX + (mUserPaddingLeft & inside);
13952                            break;
13953                    }
13954                    top = scrollY + (mPaddingTop & inside);
13955                    right = left + size;
13956                    bottom = scrollY + height - (mUserPaddingBottom & inside);
13957                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13958                    if (invalidate) {
13959                        invalidate(left, top, right, bottom);
13960                    }
13961                }
13962            }
13963        }
13964    }
13965
13966    /**
13967     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13968     * FastScroller is visible.
13969     * @return whether to temporarily hide the vertical scrollbar
13970     * @hide
13971     */
13972    protected boolean isVerticalScrollBarHidden() {
13973        return false;
13974    }
13975
13976    /**
13977     * <p>Draw the horizontal scrollbar if
13978     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13979     *
13980     * @param canvas the canvas on which to draw the scrollbar
13981     * @param scrollBar the scrollbar's drawable
13982     *
13983     * @see #isHorizontalScrollBarEnabled()
13984     * @see #computeHorizontalScrollRange()
13985     * @see #computeHorizontalScrollExtent()
13986     * @see #computeHorizontalScrollOffset()
13987     * @see android.widget.ScrollBarDrawable
13988     * @hide
13989     */
13990    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13991            int l, int t, int r, int b) {
13992        scrollBar.setBounds(l, t, r, b);
13993        scrollBar.draw(canvas);
13994    }
13995
13996    /**
13997     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13998     * returns true.</p>
13999     *
14000     * @param canvas the canvas on which to draw the scrollbar
14001     * @param scrollBar the scrollbar's drawable
14002     *
14003     * @see #isVerticalScrollBarEnabled()
14004     * @see #computeVerticalScrollRange()
14005     * @see #computeVerticalScrollExtent()
14006     * @see #computeVerticalScrollOffset()
14007     * @see android.widget.ScrollBarDrawable
14008     * @hide
14009     */
14010    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14011            int l, int t, int r, int b) {
14012        scrollBar.setBounds(l, t, r, b);
14013        scrollBar.draw(canvas);
14014    }
14015
14016    /**
14017     * Implement this to do your drawing.
14018     *
14019     * @param canvas the canvas on which the background will be drawn
14020     */
14021    protected void onDraw(Canvas canvas) {
14022    }
14023
14024    /*
14025     * Caller is responsible for calling requestLayout if necessary.
14026     * (This allows addViewInLayout to not request a new layout.)
14027     */
14028    void assignParent(ViewParent parent) {
14029        if (mParent == null) {
14030            mParent = parent;
14031        } else if (parent == null) {
14032            mParent = null;
14033        } else {
14034            throw new RuntimeException("view " + this + " being added, but"
14035                    + " it already has a parent");
14036        }
14037    }
14038
14039    /**
14040     * This is called when the view is attached to a window.  At this point it
14041     * has a Surface and will start drawing.  Note that this function is
14042     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14043     * however it may be called any time before the first onDraw -- including
14044     * before or after {@link #onMeasure(int, int)}.
14045     *
14046     * @see #onDetachedFromWindow()
14047     */
14048    @CallSuper
14049    protected void onAttachedToWindow() {
14050        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14051            mParent.requestTransparentRegion(this);
14052        }
14053
14054        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14055
14056        jumpDrawablesToCurrentState();
14057
14058        resetSubtreeAccessibilityStateChanged();
14059
14060        // rebuild, since Outline not maintained while View is detached
14061        rebuildOutline();
14062
14063        if (isFocused()) {
14064            InputMethodManager imm = InputMethodManager.peekInstance();
14065            if (imm != null) {
14066                imm.focusIn(this);
14067            }
14068        }
14069    }
14070
14071    /**
14072     * Resolve all RTL related properties.
14073     *
14074     * @return true if resolution of RTL properties has been done
14075     *
14076     * @hide
14077     */
14078    public boolean resolveRtlPropertiesIfNeeded() {
14079        if (!needRtlPropertiesResolution()) return false;
14080
14081        // Order is important here: LayoutDirection MUST be resolved first
14082        if (!isLayoutDirectionResolved()) {
14083            resolveLayoutDirection();
14084            resolveLayoutParams();
14085        }
14086        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14087        if (!isTextDirectionResolved()) {
14088            resolveTextDirection();
14089        }
14090        if (!isTextAlignmentResolved()) {
14091            resolveTextAlignment();
14092        }
14093        // Should resolve Drawables before Padding because we need the layout direction of the
14094        // Drawable to correctly resolve Padding.
14095        if (!areDrawablesResolved()) {
14096            resolveDrawables();
14097        }
14098        if (!isPaddingResolved()) {
14099            resolvePadding();
14100        }
14101        onRtlPropertiesChanged(getLayoutDirection());
14102        return true;
14103    }
14104
14105    /**
14106     * Reset resolution of all RTL related properties.
14107     *
14108     * @hide
14109     */
14110    public void resetRtlProperties() {
14111        resetResolvedLayoutDirection();
14112        resetResolvedTextDirection();
14113        resetResolvedTextAlignment();
14114        resetResolvedPadding();
14115        resetResolvedDrawables();
14116    }
14117
14118    /**
14119     * @see #onScreenStateChanged(int)
14120     */
14121    void dispatchScreenStateChanged(int screenState) {
14122        onScreenStateChanged(screenState);
14123    }
14124
14125    /**
14126     * This method is called whenever the state of the screen this view is
14127     * attached to changes. A state change will usually occurs when the screen
14128     * turns on or off (whether it happens automatically or the user does it
14129     * manually.)
14130     *
14131     * @param screenState The new state of the screen. Can be either
14132     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14133     */
14134    public void onScreenStateChanged(int screenState) {
14135    }
14136
14137    /**
14138     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14139     */
14140    private boolean hasRtlSupport() {
14141        return mContext.getApplicationInfo().hasRtlSupport();
14142    }
14143
14144    /**
14145     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14146     * RTL not supported)
14147     */
14148    private boolean isRtlCompatibilityMode() {
14149        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14150        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14151    }
14152
14153    /**
14154     * @return true if RTL properties need resolution.
14155     *
14156     */
14157    private boolean needRtlPropertiesResolution() {
14158        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14159    }
14160
14161    /**
14162     * Called when any RTL property (layout direction or text direction or text alignment) has
14163     * been changed.
14164     *
14165     * Subclasses need to override this method to take care of cached information that depends on the
14166     * resolved layout direction, or to inform child views that inherit their layout direction.
14167     *
14168     * The default implementation does nothing.
14169     *
14170     * @param layoutDirection the direction of the layout
14171     *
14172     * @see #LAYOUT_DIRECTION_LTR
14173     * @see #LAYOUT_DIRECTION_RTL
14174     */
14175    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14176    }
14177
14178    /**
14179     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14180     * that the parent directionality can and will be resolved before its children.
14181     *
14182     * @return true if resolution has been done, false otherwise.
14183     *
14184     * @hide
14185     */
14186    public boolean resolveLayoutDirection() {
14187        // Clear any previous layout direction resolution
14188        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14189
14190        if (hasRtlSupport()) {
14191            // Set resolved depending on layout direction
14192            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14193                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14194                case LAYOUT_DIRECTION_INHERIT:
14195                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14196                    // later to get the correct resolved value
14197                    if (!canResolveLayoutDirection()) return false;
14198
14199                    // Parent has not yet resolved, LTR is still the default
14200                    try {
14201                        if (!mParent.isLayoutDirectionResolved()) return false;
14202
14203                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14204                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14205                        }
14206                    } catch (AbstractMethodError e) {
14207                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14208                                " does not fully implement ViewParent", e);
14209                    }
14210                    break;
14211                case LAYOUT_DIRECTION_RTL:
14212                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14213                    break;
14214                case LAYOUT_DIRECTION_LOCALE:
14215                    if((LAYOUT_DIRECTION_RTL ==
14216                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14217                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14218                    }
14219                    break;
14220                default:
14221                    // Nothing to do, LTR by default
14222            }
14223        }
14224
14225        // Set to resolved
14226        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14227        return true;
14228    }
14229
14230    /**
14231     * Check if layout direction resolution can be done.
14232     *
14233     * @return true if layout direction resolution can be done otherwise return false.
14234     */
14235    public boolean canResolveLayoutDirection() {
14236        switch (getRawLayoutDirection()) {
14237            case LAYOUT_DIRECTION_INHERIT:
14238                if (mParent != null) {
14239                    try {
14240                        return mParent.canResolveLayoutDirection();
14241                    } catch (AbstractMethodError e) {
14242                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14243                                " does not fully implement ViewParent", e);
14244                    }
14245                }
14246                return false;
14247
14248            default:
14249                return true;
14250        }
14251    }
14252
14253    /**
14254     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14255     * {@link #onMeasure(int, int)}.
14256     *
14257     * @hide
14258     */
14259    public void resetResolvedLayoutDirection() {
14260        // Reset the current resolved bits
14261        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14262    }
14263
14264    /**
14265     * @return true if the layout direction is inherited.
14266     *
14267     * @hide
14268     */
14269    public boolean isLayoutDirectionInherited() {
14270        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14271    }
14272
14273    /**
14274     * @return true if layout direction has been resolved.
14275     */
14276    public boolean isLayoutDirectionResolved() {
14277        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14278    }
14279
14280    /**
14281     * Return if padding has been resolved
14282     *
14283     * @hide
14284     */
14285    boolean isPaddingResolved() {
14286        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14287    }
14288
14289    /**
14290     * Resolves padding depending on layout direction, if applicable, and
14291     * recomputes internal padding values to adjust for scroll bars.
14292     *
14293     * @hide
14294     */
14295    public void resolvePadding() {
14296        final int resolvedLayoutDirection = getLayoutDirection();
14297
14298        if (!isRtlCompatibilityMode()) {
14299            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14300            // If start / end padding are defined, they will be resolved (hence overriding) to
14301            // left / right or right / left depending on the resolved layout direction.
14302            // If start / end padding are not defined, use the left / right ones.
14303            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14304                Rect padding = sThreadLocal.get();
14305                if (padding == null) {
14306                    padding = new Rect();
14307                    sThreadLocal.set(padding);
14308                }
14309                mBackground.getPadding(padding);
14310                if (!mLeftPaddingDefined) {
14311                    mUserPaddingLeftInitial = padding.left;
14312                }
14313                if (!mRightPaddingDefined) {
14314                    mUserPaddingRightInitial = padding.right;
14315                }
14316            }
14317            switch (resolvedLayoutDirection) {
14318                case LAYOUT_DIRECTION_RTL:
14319                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14320                        mUserPaddingRight = mUserPaddingStart;
14321                    } else {
14322                        mUserPaddingRight = mUserPaddingRightInitial;
14323                    }
14324                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14325                        mUserPaddingLeft = mUserPaddingEnd;
14326                    } else {
14327                        mUserPaddingLeft = mUserPaddingLeftInitial;
14328                    }
14329                    break;
14330                case LAYOUT_DIRECTION_LTR:
14331                default:
14332                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14333                        mUserPaddingLeft = mUserPaddingStart;
14334                    } else {
14335                        mUserPaddingLeft = mUserPaddingLeftInitial;
14336                    }
14337                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14338                        mUserPaddingRight = mUserPaddingEnd;
14339                    } else {
14340                        mUserPaddingRight = mUserPaddingRightInitial;
14341                    }
14342            }
14343
14344            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14345        }
14346
14347        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14348        onRtlPropertiesChanged(resolvedLayoutDirection);
14349
14350        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14351    }
14352
14353    /**
14354     * Reset the resolved layout direction.
14355     *
14356     * @hide
14357     */
14358    public void resetResolvedPadding() {
14359        resetResolvedPaddingInternal();
14360    }
14361
14362    /**
14363     * Used when we only want to reset *this* view's padding and not trigger overrides
14364     * in ViewGroup that reset children too.
14365     */
14366    void resetResolvedPaddingInternal() {
14367        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14368    }
14369
14370    /**
14371     * This is called when the view is detached from a window.  At this point it
14372     * no longer has a surface for drawing.
14373     *
14374     * @see #onAttachedToWindow()
14375     */
14376    @CallSuper
14377    protected void onDetachedFromWindow() {
14378    }
14379
14380    /**
14381     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14382     * after onDetachedFromWindow().
14383     *
14384     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14385     * The super method should be called at the end of the overridden method to ensure
14386     * subclasses are destroyed first
14387     *
14388     * @hide
14389     */
14390    @CallSuper
14391    protected void onDetachedFromWindowInternal() {
14392        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14393        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14394
14395        removeUnsetPressCallback();
14396        removeLongPressCallback();
14397        removePerformClickCallback();
14398        removeSendViewScrolledAccessibilityEventCallback();
14399        stopNestedScroll();
14400
14401        // Anything that started animating right before detach should already
14402        // be in its final state when re-attached.
14403        jumpDrawablesToCurrentState();
14404
14405        destroyDrawingCache();
14406
14407        cleanupDraw();
14408        mCurrentAnimation = null;
14409    }
14410
14411    private void cleanupDraw() {
14412        resetDisplayList();
14413        if (mAttachInfo != null) {
14414            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14415        }
14416    }
14417
14418    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14419    }
14420
14421    /**
14422     * @return The number of times this view has been attached to a window
14423     */
14424    protected int getWindowAttachCount() {
14425        return mWindowAttachCount;
14426    }
14427
14428    /**
14429     * Retrieve a unique token identifying the window this view is attached to.
14430     * @return Return the window's token for use in
14431     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14432     */
14433    public IBinder getWindowToken() {
14434        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14435    }
14436
14437    /**
14438     * Retrieve the {@link WindowId} for the window this view is
14439     * currently attached to.
14440     */
14441    public WindowId getWindowId() {
14442        if (mAttachInfo == null) {
14443            return null;
14444        }
14445        if (mAttachInfo.mWindowId == null) {
14446            try {
14447                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14448                        mAttachInfo.mWindowToken);
14449                mAttachInfo.mWindowId = new WindowId(
14450                        mAttachInfo.mIWindowId);
14451            } catch (RemoteException e) {
14452            }
14453        }
14454        return mAttachInfo.mWindowId;
14455    }
14456
14457    /**
14458     * Retrieve a unique token identifying the top-level "real" window of
14459     * the window that this view is attached to.  That is, this is like
14460     * {@link #getWindowToken}, except if the window this view in is a panel
14461     * window (attached to another containing window), then the token of
14462     * the containing window is returned instead.
14463     *
14464     * @return Returns the associated window token, either
14465     * {@link #getWindowToken()} or the containing window's token.
14466     */
14467    public IBinder getApplicationWindowToken() {
14468        AttachInfo ai = mAttachInfo;
14469        if (ai != null) {
14470            IBinder appWindowToken = ai.mPanelParentWindowToken;
14471            if (appWindowToken == null) {
14472                appWindowToken = ai.mWindowToken;
14473            }
14474            return appWindowToken;
14475        }
14476        return null;
14477    }
14478
14479    /**
14480     * Gets the logical display to which the view's window has been attached.
14481     *
14482     * @return The logical display, or null if the view is not currently attached to a window.
14483     */
14484    public Display getDisplay() {
14485        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14486    }
14487
14488    /**
14489     * Retrieve private session object this view hierarchy is using to
14490     * communicate with the window manager.
14491     * @return the session object to communicate with the window manager
14492     */
14493    /*package*/ IWindowSession getWindowSession() {
14494        return mAttachInfo != null ? mAttachInfo.mSession : null;
14495    }
14496
14497    /**
14498     * Return the visibility value of the least visible component passed.
14499     */
14500    int combineVisibility(int vis1, int vis2) {
14501        // This works because VISIBLE < INVISIBLE < GONE.
14502        return Math.max(vis1, vis2);
14503    }
14504
14505    /**
14506     * @param info the {@link android.view.View.AttachInfo} to associated with
14507     *        this view
14508     */
14509    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14510        //System.out.println("Attached! " + this);
14511        mAttachInfo = info;
14512        if (mOverlay != null) {
14513            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14514        }
14515        mWindowAttachCount++;
14516        // We will need to evaluate the drawable state at least once.
14517        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14518        if (mFloatingTreeObserver != null) {
14519            info.mTreeObserver.merge(mFloatingTreeObserver);
14520            mFloatingTreeObserver = null;
14521        }
14522        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14523            mAttachInfo.mScrollContainers.add(this);
14524            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14525        }
14526        performCollectViewAttributes(mAttachInfo, visibility);
14527        onAttachedToWindow();
14528
14529        ListenerInfo li = mListenerInfo;
14530        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14531                li != null ? li.mOnAttachStateChangeListeners : null;
14532        if (listeners != null && listeners.size() > 0) {
14533            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14534            // perform the dispatching. The iterator is a safe guard against listeners that
14535            // could mutate the list by calling the various add/remove methods. This prevents
14536            // the array from being modified while we iterate it.
14537            for (OnAttachStateChangeListener listener : listeners) {
14538                listener.onViewAttachedToWindow(this);
14539            }
14540        }
14541
14542        int vis = info.mWindowVisibility;
14543        if (vis != GONE) {
14544            onWindowVisibilityChanged(vis);
14545        }
14546
14547        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14548        // As all views in the subtree will already receive dispatchAttachedToWindow
14549        // traversing the subtree again here is not desired.
14550        onVisibilityChanged(this, visibility);
14551
14552        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14553            // If nobody has evaluated the drawable state yet, then do it now.
14554            refreshDrawableState();
14555        }
14556        needGlobalAttributesUpdate(false);
14557    }
14558
14559    void dispatchDetachedFromWindow() {
14560        AttachInfo info = mAttachInfo;
14561        if (info != null) {
14562            int vis = info.mWindowVisibility;
14563            if (vis != GONE) {
14564                onWindowVisibilityChanged(GONE);
14565            }
14566        }
14567
14568        onDetachedFromWindow();
14569        onDetachedFromWindowInternal();
14570
14571        InputMethodManager imm = InputMethodManager.peekInstance();
14572        if (imm != null) {
14573            imm.onViewDetachedFromWindow(this);
14574        }
14575
14576        ListenerInfo li = mListenerInfo;
14577        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14578                li != null ? li.mOnAttachStateChangeListeners : null;
14579        if (listeners != null && listeners.size() > 0) {
14580            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14581            // perform the dispatching. The iterator is a safe guard against listeners that
14582            // could mutate the list by calling the various add/remove methods. This prevents
14583            // the array from being modified while we iterate it.
14584            for (OnAttachStateChangeListener listener : listeners) {
14585                listener.onViewDetachedFromWindow(this);
14586            }
14587        }
14588
14589        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14590            mAttachInfo.mScrollContainers.remove(this);
14591            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14592        }
14593
14594        mAttachInfo = null;
14595        if (mOverlay != null) {
14596            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14597        }
14598    }
14599
14600    /**
14601     * Cancel any deferred high-level input events that were previously posted to the event queue.
14602     *
14603     * <p>Many views post high-level events such as click handlers to the event queue
14604     * to run deferred in order to preserve a desired user experience - clearing visible
14605     * pressed states before executing, etc. This method will abort any events of this nature
14606     * that are currently in flight.</p>
14607     *
14608     * <p>Custom views that generate their own high-level deferred input events should override
14609     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14610     *
14611     * <p>This will also cancel pending input events for any child views.</p>
14612     *
14613     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14614     * This will not impact newer events posted after this call that may occur as a result of
14615     * lower-level input events still waiting in the queue. If you are trying to prevent
14616     * double-submitted  events for the duration of some sort of asynchronous transaction
14617     * you should also take other steps to protect against unexpected double inputs e.g. calling
14618     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14619     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14620     */
14621    public final void cancelPendingInputEvents() {
14622        dispatchCancelPendingInputEvents();
14623    }
14624
14625    /**
14626     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14627     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14628     */
14629    void dispatchCancelPendingInputEvents() {
14630        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14631        onCancelPendingInputEvents();
14632        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14633            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14634                    " did not call through to super.onCancelPendingInputEvents()");
14635        }
14636    }
14637
14638    /**
14639     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14640     * a parent view.
14641     *
14642     * <p>This method is responsible for removing any pending high-level input events that were
14643     * posted to the event queue to run later. Custom view classes that post their own deferred
14644     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14645     * {@link android.os.Handler} should override this method, call
14646     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14647     * </p>
14648     */
14649    public void onCancelPendingInputEvents() {
14650        removePerformClickCallback();
14651        cancelLongPress();
14652        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14653    }
14654
14655    /**
14656     * Store this view hierarchy's frozen state into the given container.
14657     *
14658     * @param container The SparseArray in which to save the view's state.
14659     *
14660     * @see #restoreHierarchyState(android.util.SparseArray)
14661     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14662     * @see #onSaveInstanceState()
14663     */
14664    public void saveHierarchyState(SparseArray<Parcelable> container) {
14665        dispatchSaveInstanceState(container);
14666    }
14667
14668    /**
14669     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14670     * this view and its children. May be overridden to modify how freezing happens to a
14671     * view's children; for example, some views may want to not store state for their children.
14672     *
14673     * @param container The SparseArray in which to save the view's state.
14674     *
14675     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14676     * @see #saveHierarchyState(android.util.SparseArray)
14677     * @see #onSaveInstanceState()
14678     */
14679    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14680        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14681            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14682            Parcelable state = onSaveInstanceState();
14683            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14684                throw new IllegalStateException(
14685                        "Derived class did not call super.onSaveInstanceState()");
14686            }
14687            if (state != null) {
14688                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14689                // + ": " + state);
14690                container.put(mID, state);
14691            }
14692        }
14693    }
14694
14695    /**
14696     * Hook allowing a view to generate a representation of its internal state
14697     * that can later be used to create a new instance with that same state.
14698     * This state should only contain information that is not persistent or can
14699     * not be reconstructed later. For example, you will never store your
14700     * current position on screen because that will be computed again when a
14701     * new instance of the view is placed in its view hierarchy.
14702     * <p>
14703     * Some examples of things you may store here: the current cursor position
14704     * in a text view (but usually not the text itself since that is stored in a
14705     * content provider or other persistent storage), the currently selected
14706     * item in a list view.
14707     *
14708     * @return Returns a Parcelable object containing the view's current dynamic
14709     *         state, or null if there is nothing interesting to save. The
14710     *         default implementation returns null.
14711     * @see #onRestoreInstanceState(android.os.Parcelable)
14712     * @see #saveHierarchyState(android.util.SparseArray)
14713     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14714     * @see #setSaveEnabled(boolean)
14715     */
14716    @CallSuper
14717    protected Parcelable onSaveInstanceState() {
14718        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14719        if (mStartActivityRequestWho != null) {
14720            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14721            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14722            return state;
14723        }
14724        return BaseSavedState.EMPTY_STATE;
14725    }
14726
14727    /**
14728     * Restore this view hierarchy's frozen state from the given container.
14729     *
14730     * @param container The SparseArray which holds previously frozen states.
14731     *
14732     * @see #saveHierarchyState(android.util.SparseArray)
14733     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14734     * @see #onRestoreInstanceState(android.os.Parcelable)
14735     */
14736    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14737        dispatchRestoreInstanceState(container);
14738    }
14739
14740    /**
14741     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14742     * state for this view and its children. May be overridden to modify how restoring
14743     * happens to a view's children; for example, some views may want to not store state
14744     * for their children.
14745     *
14746     * @param container The SparseArray which holds previously saved state.
14747     *
14748     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14749     * @see #restoreHierarchyState(android.util.SparseArray)
14750     * @see #onRestoreInstanceState(android.os.Parcelable)
14751     */
14752    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14753        if (mID != NO_ID) {
14754            Parcelable state = container.get(mID);
14755            if (state != null) {
14756                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14757                // + ": " + state);
14758                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14759                onRestoreInstanceState(state);
14760                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14761                    throw new IllegalStateException(
14762                            "Derived class did not call super.onRestoreInstanceState()");
14763                }
14764            }
14765        }
14766    }
14767
14768    /**
14769     * Hook allowing a view to re-apply a representation of its internal state that had previously
14770     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14771     * null state.
14772     *
14773     * @param state The frozen state that had previously been returned by
14774     *        {@link #onSaveInstanceState}.
14775     *
14776     * @see #onSaveInstanceState()
14777     * @see #restoreHierarchyState(android.util.SparseArray)
14778     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14779     */
14780    @CallSuper
14781    protected void onRestoreInstanceState(Parcelable state) {
14782        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14783        if (state != null && !(state instanceof AbsSavedState)) {
14784            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14785                    + "received " + state.getClass().toString() + " instead. This usually happens "
14786                    + "when two views of different type have the same id in the same hierarchy. "
14787                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14788                    + "other views do not use the same id.");
14789        }
14790        if (state != null && state instanceof BaseSavedState) {
14791            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14792        }
14793    }
14794
14795    /**
14796     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14797     *
14798     * @return the drawing start time in milliseconds
14799     */
14800    public long getDrawingTime() {
14801        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14802    }
14803
14804    /**
14805     * <p>Enables or disables the duplication of the parent's state into this view. When
14806     * duplication is enabled, this view gets its drawable state from its parent rather
14807     * than from its own internal properties.</p>
14808     *
14809     * <p>Note: in the current implementation, setting this property to true after the
14810     * view was added to a ViewGroup might have no effect at all. This property should
14811     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14812     *
14813     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14814     * property is enabled, an exception will be thrown.</p>
14815     *
14816     * <p>Note: if the child view uses and updates additional states which are unknown to the
14817     * parent, these states should not be affected by this method.</p>
14818     *
14819     * @param enabled True to enable duplication of the parent's drawable state, false
14820     *                to disable it.
14821     *
14822     * @see #getDrawableState()
14823     * @see #isDuplicateParentStateEnabled()
14824     */
14825    public void setDuplicateParentStateEnabled(boolean enabled) {
14826        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14827    }
14828
14829    /**
14830     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14831     *
14832     * @return True if this view's drawable state is duplicated from the parent,
14833     *         false otherwise
14834     *
14835     * @see #getDrawableState()
14836     * @see #setDuplicateParentStateEnabled(boolean)
14837     */
14838    public boolean isDuplicateParentStateEnabled() {
14839        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14840    }
14841
14842    /**
14843     * <p>Specifies the type of layer backing this view. The layer can be
14844     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14845     * {@link #LAYER_TYPE_HARDWARE}.</p>
14846     *
14847     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14848     * instance that controls how the layer is composed on screen. The following
14849     * properties of the paint are taken into account when composing the layer:</p>
14850     * <ul>
14851     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14852     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14853     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14854     * </ul>
14855     *
14856     * <p>If this view has an alpha value set to < 1.0 by calling
14857     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14858     * by this view's alpha value.</p>
14859     *
14860     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14861     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14862     * for more information on when and how to use layers.</p>
14863     *
14864     * @param layerType The type of layer to use with this view, must be one of
14865     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14866     *        {@link #LAYER_TYPE_HARDWARE}
14867     * @param paint The paint used to compose the layer. This argument is optional
14868     *        and can be null. It is ignored when the layer type is
14869     *        {@link #LAYER_TYPE_NONE}
14870     *
14871     * @see #getLayerType()
14872     * @see #LAYER_TYPE_NONE
14873     * @see #LAYER_TYPE_SOFTWARE
14874     * @see #LAYER_TYPE_HARDWARE
14875     * @see #setAlpha(float)
14876     *
14877     * @attr ref android.R.styleable#View_layerType
14878     */
14879    public void setLayerType(int layerType, Paint paint) {
14880        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14881            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14882                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14883        }
14884
14885        boolean typeChanged = mRenderNode.setLayerType(layerType);
14886
14887        if (!typeChanged) {
14888            setLayerPaint(paint);
14889            return;
14890        }
14891
14892        // Destroy any previous software drawing cache if needed
14893        if (mLayerType == LAYER_TYPE_SOFTWARE) {
14894            destroyDrawingCache();
14895        }
14896
14897        mLayerType = layerType;
14898        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14899        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14900        mRenderNode.setLayerPaint(mLayerPaint);
14901
14902        // draw() behaves differently if we are on a layer, so we need to
14903        // invalidate() here
14904        invalidateParentCaches();
14905        invalidate(true);
14906    }
14907
14908    /**
14909     * Updates the {@link Paint} object used with the current layer (used only if the current
14910     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14911     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14912     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14913     * ensure that the view gets redrawn immediately.
14914     *
14915     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14916     * instance that controls how the layer is composed on screen. The following
14917     * properties of the paint are taken into account when composing the layer:</p>
14918     * <ul>
14919     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14920     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14921     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14922     * </ul>
14923     *
14924     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14925     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14926     *
14927     * @param paint The paint used to compose the layer. This argument is optional
14928     *        and can be null. It is ignored when the layer type is
14929     *        {@link #LAYER_TYPE_NONE}
14930     *
14931     * @see #setLayerType(int, android.graphics.Paint)
14932     */
14933    public void setLayerPaint(Paint paint) {
14934        int layerType = getLayerType();
14935        if (layerType != LAYER_TYPE_NONE) {
14936            mLayerPaint = paint == null ? new Paint() : paint;
14937            if (layerType == LAYER_TYPE_HARDWARE) {
14938                if (mRenderNode.setLayerPaint(mLayerPaint)) {
14939                    invalidateViewProperty(false, false);
14940                }
14941            } else {
14942                invalidate();
14943            }
14944        }
14945    }
14946
14947    /**
14948     * Indicates what type of layer is currently associated with this view. By default
14949     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14950     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14951     * for more information on the different types of layers.
14952     *
14953     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14954     *         {@link #LAYER_TYPE_HARDWARE}
14955     *
14956     * @see #setLayerType(int, android.graphics.Paint)
14957     * @see #buildLayer()
14958     * @see #LAYER_TYPE_NONE
14959     * @see #LAYER_TYPE_SOFTWARE
14960     * @see #LAYER_TYPE_HARDWARE
14961     */
14962    public int getLayerType() {
14963        return mLayerType;
14964    }
14965
14966    /**
14967     * Forces this view's layer to be created and this view to be rendered
14968     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14969     * invoking this method will have no effect.
14970     *
14971     * This method can for instance be used to render a view into its layer before
14972     * starting an animation. If this view is complex, rendering into the layer
14973     * before starting the animation will avoid skipping frames.
14974     *
14975     * @throws IllegalStateException If this view is not attached to a window
14976     *
14977     * @see #setLayerType(int, android.graphics.Paint)
14978     */
14979    public void buildLayer() {
14980        if (mLayerType == LAYER_TYPE_NONE) return;
14981
14982        final AttachInfo attachInfo = mAttachInfo;
14983        if (attachInfo == null) {
14984            throw new IllegalStateException("This view must be attached to a window first");
14985        }
14986
14987        if (getWidth() == 0 || getHeight() == 0) {
14988            return;
14989        }
14990
14991        switch (mLayerType) {
14992            case LAYER_TYPE_HARDWARE:
14993                updateDisplayListIfDirty();
14994                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14995                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14996                }
14997                break;
14998            case LAYER_TYPE_SOFTWARE:
14999                buildDrawingCache(true);
15000                break;
15001        }
15002    }
15003
15004    /**
15005     * If this View draws with a HardwareLayer, returns it.
15006     * Otherwise returns null
15007     *
15008     * TODO: Only TextureView uses this, can we eliminate it?
15009     */
15010    HardwareLayer getHardwareLayer() {
15011        return null;
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                final HardwareLayer layer = getHardwareLayer();
15165                if (layer != null && layer.isValid()) {
15166                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
15167                } else if (layerType == LAYER_TYPE_SOFTWARE) {
15168                    buildDrawingCache(true);
15169                    Bitmap cache = getDrawingCache(true);
15170                    if (cache != null) {
15171                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15172                    }
15173                } else {
15174                    computeScroll();
15175
15176                    canvas.translate(-mScrollX, -mScrollY);
15177                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15178                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15179
15180                    // Fast path for layouts with no backgrounds
15181                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15182                        dispatchDraw(canvas);
15183                        if (mOverlay != null && !mOverlay.isEmpty()) {
15184                            mOverlay.getOverlayView().draw(canvas);
15185                        }
15186                    } else {
15187                        draw(canvas);
15188                    }
15189                }
15190            } finally {
15191                renderNode.end(canvas);
15192                setDisplayListProperties(renderNode);
15193            }
15194        } else {
15195            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15196            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15197        }
15198        return renderNode;
15199    }
15200
15201    private void resetDisplayList() {
15202        if (mRenderNode.isValid()) {
15203            mRenderNode.destroyDisplayListData();
15204        }
15205
15206        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15207            mBackgroundRenderNode.destroyDisplayListData();
15208        }
15209    }
15210
15211    /**
15212     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15213     *
15214     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15215     *
15216     * @see #getDrawingCache(boolean)
15217     */
15218    public Bitmap getDrawingCache() {
15219        return getDrawingCache(false);
15220    }
15221
15222    /**
15223     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15224     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15225     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15226     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15227     * request the drawing cache by calling this method and draw it on screen if the
15228     * returned bitmap is not null.</p>
15229     *
15230     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15231     * this method will create a bitmap of the same size as this view. Because this bitmap
15232     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15233     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15234     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15235     * size than the view. This implies that your application must be able to handle this
15236     * size.</p>
15237     *
15238     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15239     *        the current density of the screen when the application is in compatibility
15240     *        mode.
15241     *
15242     * @return A bitmap representing this view or null if cache is disabled.
15243     *
15244     * @see #setDrawingCacheEnabled(boolean)
15245     * @see #isDrawingCacheEnabled()
15246     * @see #buildDrawingCache(boolean)
15247     * @see #destroyDrawingCache()
15248     */
15249    public Bitmap getDrawingCache(boolean autoScale) {
15250        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15251            return null;
15252        }
15253        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15254            buildDrawingCache(autoScale);
15255        }
15256        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15257    }
15258
15259    /**
15260     * <p>Frees the resources used by the drawing cache. If you call
15261     * {@link #buildDrawingCache()} manually without calling
15262     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15263     * should cleanup the cache with this method afterwards.</p>
15264     *
15265     * @see #setDrawingCacheEnabled(boolean)
15266     * @see #buildDrawingCache()
15267     * @see #getDrawingCache()
15268     */
15269    public void destroyDrawingCache() {
15270        if (mDrawingCache != null) {
15271            mDrawingCache.recycle();
15272            mDrawingCache = null;
15273        }
15274        if (mUnscaledDrawingCache != null) {
15275            mUnscaledDrawingCache.recycle();
15276            mUnscaledDrawingCache = null;
15277        }
15278    }
15279
15280    /**
15281     * Setting a solid background color for the drawing cache's bitmaps will improve
15282     * performance and memory usage. Note, though that this should only be used if this
15283     * view will always be drawn on top of a solid color.
15284     *
15285     * @param color The background color to use for the drawing cache's bitmap
15286     *
15287     * @see #setDrawingCacheEnabled(boolean)
15288     * @see #buildDrawingCache()
15289     * @see #getDrawingCache()
15290     */
15291    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15292        if (color != mDrawingCacheBackgroundColor) {
15293            mDrawingCacheBackgroundColor = color;
15294            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15295        }
15296    }
15297
15298    /**
15299     * @see #setDrawingCacheBackgroundColor(int)
15300     *
15301     * @return The background color to used for the drawing cache's bitmap
15302     */
15303    @ColorInt
15304    public int getDrawingCacheBackgroundColor() {
15305        return mDrawingCacheBackgroundColor;
15306    }
15307
15308    /**
15309     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15310     *
15311     * @see #buildDrawingCache(boolean)
15312     */
15313    public void buildDrawingCache() {
15314        buildDrawingCache(false);
15315    }
15316
15317    /**
15318     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15319     *
15320     * <p>If you call {@link #buildDrawingCache()} manually without calling
15321     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15322     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15323     *
15324     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15325     * this method will create a bitmap of the same size as this view. Because this bitmap
15326     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15327     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15328     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15329     * size than the view. This implies that your application must be able to handle this
15330     * size.</p>
15331     *
15332     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15333     * you do not need the drawing cache bitmap, calling this method will increase memory
15334     * usage and cause the view to be rendered in software once, thus negatively impacting
15335     * performance.</p>
15336     *
15337     * @see #getDrawingCache()
15338     * @see #destroyDrawingCache()
15339     */
15340    public void buildDrawingCache(boolean autoScale) {
15341        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15342                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15343            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15344                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15345                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15346            }
15347            try {
15348                buildDrawingCacheImpl(autoScale);
15349            } finally {
15350                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15351            }
15352        }
15353    }
15354
15355    /**
15356     * private, internal implementation of buildDrawingCache, used to enable tracing
15357     */
15358    private void buildDrawingCacheImpl(boolean autoScale) {
15359        mCachingFailed = false;
15360
15361        int width = mRight - mLeft;
15362        int height = mBottom - mTop;
15363
15364        final AttachInfo attachInfo = mAttachInfo;
15365        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15366
15367        if (autoScale && scalingRequired) {
15368            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15369            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15370        }
15371
15372        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15373        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15374        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15375
15376        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15377        final long drawingCacheSize =
15378                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15379        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15380            if (width > 0 && height > 0) {
15381                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15382                        + " too large to fit into a software layer (or drawing cache), needs "
15383                        + projectedBitmapSize + " bytes, only "
15384                        + drawingCacheSize + " available");
15385            }
15386            destroyDrawingCache();
15387            mCachingFailed = true;
15388            return;
15389        }
15390
15391        boolean clear = true;
15392        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15393
15394        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15395            Bitmap.Config quality;
15396            if (!opaque) {
15397                // Never pick ARGB_4444 because it looks awful
15398                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15399                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15400                    case DRAWING_CACHE_QUALITY_AUTO:
15401                    case DRAWING_CACHE_QUALITY_LOW:
15402                    case DRAWING_CACHE_QUALITY_HIGH:
15403                    default:
15404                        quality = Bitmap.Config.ARGB_8888;
15405                        break;
15406                }
15407            } else {
15408                // Optimization for translucent windows
15409                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15410                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15411            }
15412
15413            // Try to cleanup memory
15414            if (bitmap != null) bitmap.recycle();
15415
15416            try {
15417                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15418                        width, height, quality);
15419                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15420                if (autoScale) {
15421                    mDrawingCache = bitmap;
15422                } else {
15423                    mUnscaledDrawingCache = bitmap;
15424                }
15425                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15426            } catch (OutOfMemoryError e) {
15427                // If there is not enough memory to create the bitmap cache, just
15428                // ignore the issue as bitmap caches are not required to draw the
15429                // view hierarchy
15430                if (autoScale) {
15431                    mDrawingCache = null;
15432                } else {
15433                    mUnscaledDrawingCache = null;
15434                }
15435                mCachingFailed = true;
15436                return;
15437            }
15438
15439            clear = drawingCacheBackgroundColor != 0;
15440        }
15441
15442        Canvas canvas;
15443        if (attachInfo != null) {
15444            canvas = attachInfo.mCanvas;
15445            if (canvas == null) {
15446                canvas = new Canvas();
15447            }
15448            canvas.setBitmap(bitmap);
15449            // Temporarily clobber the cached Canvas in case one of our children
15450            // is also using a drawing cache. Without this, the children would
15451            // steal the canvas by attaching their own bitmap to it and bad, bad
15452            // thing would happen (invisible views, corrupted drawings, etc.)
15453            attachInfo.mCanvas = null;
15454        } else {
15455            // This case should hopefully never or seldom happen
15456            canvas = new Canvas(bitmap);
15457        }
15458
15459        if (clear) {
15460            bitmap.eraseColor(drawingCacheBackgroundColor);
15461        }
15462
15463        computeScroll();
15464        final int restoreCount = canvas.save();
15465
15466        if (autoScale && scalingRequired) {
15467            final float scale = attachInfo.mApplicationScale;
15468            canvas.scale(scale, scale);
15469        }
15470
15471        canvas.translate(-mScrollX, -mScrollY);
15472
15473        mPrivateFlags |= PFLAG_DRAWN;
15474        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15475                mLayerType != LAYER_TYPE_NONE) {
15476            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15477        }
15478
15479        // Fast path for layouts with no backgrounds
15480        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15481            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15482            dispatchDraw(canvas);
15483            if (mOverlay != null && !mOverlay.isEmpty()) {
15484                mOverlay.getOverlayView().draw(canvas);
15485            }
15486        } else {
15487            draw(canvas);
15488        }
15489
15490        canvas.restoreToCount(restoreCount);
15491        canvas.setBitmap(null);
15492
15493        if (attachInfo != null) {
15494            // Restore the cached Canvas for our siblings
15495            attachInfo.mCanvas = canvas;
15496        }
15497    }
15498
15499    /**
15500     * Create a snapshot of the view into a bitmap.  We should probably make
15501     * some form of this public, but should think about the API.
15502     */
15503    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15504        int width = mRight - mLeft;
15505        int height = mBottom - mTop;
15506
15507        final AttachInfo attachInfo = mAttachInfo;
15508        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15509        width = (int) ((width * scale) + 0.5f);
15510        height = (int) ((height * scale) + 0.5f);
15511
15512        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15513                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15514        if (bitmap == null) {
15515            throw new OutOfMemoryError();
15516        }
15517
15518        Resources resources = getResources();
15519        if (resources != null) {
15520            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15521        }
15522
15523        Canvas canvas;
15524        if (attachInfo != null) {
15525            canvas = attachInfo.mCanvas;
15526            if (canvas == null) {
15527                canvas = new Canvas();
15528            }
15529            canvas.setBitmap(bitmap);
15530            // Temporarily clobber the cached Canvas in case one of our children
15531            // is also using a drawing cache. Without this, the children would
15532            // steal the canvas by attaching their own bitmap to it and bad, bad
15533            // things would happen (invisible views, corrupted drawings, etc.)
15534            attachInfo.mCanvas = null;
15535        } else {
15536            // This case should hopefully never or seldom happen
15537            canvas = new Canvas(bitmap);
15538        }
15539
15540        if ((backgroundColor & 0xff000000) != 0) {
15541            bitmap.eraseColor(backgroundColor);
15542        }
15543
15544        computeScroll();
15545        final int restoreCount = canvas.save();
15546        canvas.scale(scale, scale);
15547        canvas.translate(-mScrollX, -mScrollY);
15548
15549        // Temporarily remove the dirty mask
15550        int flags = mPrivateFlags;
15551        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15552
15553        // Fast path for layouts with no backgrounds
15554        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15555            dispatchDraw(canvas);
15556            if (mOverlay != null && !mOverlay.isEmpty()) {
15557                mOverlay.getOverlayView().draw(canvas);
15558            }
15559        } else {
15560            draw(canvas);
15561        }
15562
15563        mPrivateFlags = flags;
15564
15565        canvas.restoreToCount(restoreCount);
15566        canvas.setBitmap(null);
15567
15568        if (attachInfo != null) {
15569            // Restore the cached Canvas for our siblings
15570            attachInfo.mCanvas = canvas;
15571        }
15572
15573        return bitmap;
15574    }
15575
15576    /**
15577     * Indicates whether this View is currently in edit mode. A View is usually
15578     * in edit mode when displayed within a developer tool. For instance, if
15579     * this View is being drawn by a visual user interface builder, this method
15580     * should return true.
15581     *
15582     * Subclasses should check the return value of this method to provide
15583     * different behaviors if their normal behavior might interfere with the
15584     * host environment. For instance: the class spawns a thread in its
15585     * constructor, the drawing code relies on device-specific features, etc.
15586     *
15587     * This method is usually checked in the drawing code of custom widgets.
15588     *
15589     * @return True if this View is in edit mode, false otherwise.
15590     */
15591    public boolean isInEditMode() {
15592        return false;
15593    }
15594
15595    /**
15596     * If the View draws content inside its padding and enables fading edges,
15597     * it needs to support padding offsets. Padding offsets are added to the
15598     * fading edges to extend the length of the fade so that it covers pixels
15599     * drawn inside the padding.
15600     *
15601     * Subclasses of this class should override this method if they need
15602     * to draw content inside the padding.
15603     *
15604     * @return True if padding offset must be applied, false otherwise.
15605     *
15606     * @see #getLeftPaddingOffset()
15607     * @see #getRightPaddingOffset()
15608     * @see #getTopPaddingOffset()
15609     * @see #getBottomPaddingOffset()
15610     *
15611     * @since CURRENT
15612     */
15613    protected boolean isPaddingOffsetRequired() {
15614        return false;
15615    }
15616
15617    /**
15618     * Amount by which to extend the left fading region. Called only when
15619     * {@link #isPaddingOffsetRequired()} returns true.
15620     *
15621     * @return The left padding offset in pixels.
15622     *
15623     * @see #isPaddingOffsetRequired()
15624     *
15625     * @since CURRENT
15626     */
15627    protected int getLeftPaddingOffset() {
15628        return 0;
15629    }
15630
15631    /**
15632     * Amount by which to extend the right fading region. Called only when
15633     * {@link #isPaddingOffsetRequired()} returns true.
15634     *
15635     * @return The right padding offset in pixels.
15636     *
15637     * @see #isPaddingOffsetRequired()
15638     *
15639     * @since CURRENT
15640     */
15641    protected int getRightPaddingOffset() {
15642        return 0;
15643    }
15644
15645    /**
15646     * Amount by which to extend the top fading region. Called only when
15647     * {@link #isPaddingOffsetRequired()} returns true.
15648     *
15649     * @return The top padding offset in pixels.
15650     *
15651     * @see #isPaddingOffsetRequired()
15652     *
15653     * @since CURRENT
15654     */
15655    protected int getTopPaddingOffset() {
15656        return 0;
15657    }
15658
15659    /**
15660     * Amount by which to extend the bottom fading region. Called only when
15661     * {@link #isPaddingOffsetRequired()} returns true.
15662     *
15663     * @return The bottom padding offset in pixels.
15664     *
15665     * @see #isPaddingOffsetRequired()
15666     *
15667     * @since CURRENT
15668     */
15669    protected int getBottomPaddingOffset() {
15670        return 0;
15671    }
15672
15673    /**
15674     * @hide
15675     * @param offsetRequired
15676     */
15677    protected int getFadeTop(boolean offsetRequired) {
15678        int top = mPaddingTop;
15679        if (offsetRequired) top += getTopPaddingOffset();
15680        return top;
15681    }
15682
15683    /**
15684     * @hide
15685     * @param offsetRequired
15686     */
15687    protected int getFadeHeight(boolean offsetRequired) {
15688        int padding = mPaddingTop;
15689        if (offsetRequired) padding += getTopPaddingOffset();
15690        return mBottom - mTop - mPaddingBottom - padding;
15691    }
15692
15693    /**
15694     * <p>Indicates whether this view is attached to a hardware accelerated
15695     * window or not.</p>
15696     *
15697     * <p>Even if this method returns true, it does not mean that every call
15698     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15699     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15700     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15701     * window is hardware accelerated,
15702     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15703     * return false, and this method will return true.</p>
15704     *
15705     * @return True if the view is attached to a window and the window is
15706     *         hardware accelerated; false in any other case.
15707     */
15708    @ViewDebug.ExportedProperty(category = "drawing")
15709    public boolean isHardwareAccelerated() {
15710        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15711    }
15712
15713    /**
15714     * Sets a rectangular area on this view to which the view will be clipped
15715     * when it is drawn. Setting the value to null will remove the clip bounds
15716     * and the view will draw normally, using its full bounds.
15717     *
15718     * @param clipBounds The rectangular area, in the local coordinates of
15719     * this view, to which future drawing operations will be clipped.
15720     */
15721    public void setClipBounds(Rect clipBounds) {
15722        if (clipBounds == mClipBounds
15723                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15724            return;
15725        }
15726        if (clipBounds != null) {
15727            if (mClipBounds == null) {
15728                mClipBounds = new Rect(clipBounds);
15729            } else {
15730                mClipBounds.set(clipBounds);
15731            }
15732        } else {
15733            mClipBounds = null;
15734        }
15735        mRenderNode.setClipBounds(mClipBounds);
15736        invalidateViewProperty(false, false);
15737    }
15738
15739    /**
15740     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15741     *
15742     * @return A copy of the current clip bounds if clip bounds are set,
15743     * otherwise null.
15744     */
15745    public Rect getClipBounds() {
15746        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15747    }
15748
15749
15750    /**
15751     * Populates an output rectangle with the clip bounds of the view,
15752     * returning {@code true} if successful or {@code false} if the view's
15753     * clip bounds are {@code null}.
15754     *
15755     * @param outRect rectangle in which to place the clip bounds of the view
15756     * @return {@code true} if successful or {@code false} if the view's
15757     *         clip bounds are {@code null}
15758     */
15759    public boolean getClipBounds(Rect outRect) {
15760        if (mClipBounds != null) {
15761            outRect.set(mClipBounds);
15762            return true;
15763        }
15764        return false;
15765    }
15766
15767    /**
15768     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15769     * case of an active Animation being run on the view.
15770     */
15771    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15772            Animation a, boolean scalingRequired) {
15773        Transformation invalidationTransform;
15774        final int flags = parent.mGroupFlags;
15775        final boolean initialized = a.isInitialized();
15776        if (!initialized) {
15777            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15778            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15779            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15780            onAnimationStart();
15781        }
15782
15783        final Transformation t = parent.getChildTransformation();
15784        boolean more = a.getTransformation(drawingTime, t, 1f);
15785        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15786            if (parent.mInvalidationTransformation == null) {
15787                parent.mInvalidationTransformation = new Transformation();
15788            }
15789            invalidationTransform = parent.mInvalidationTransformation;
15790            a.getTransformation(drawingTime, invalidationTransform, 1f);
15791        } else {
15792            invalidationTransform = t;
15793        }
15794
15795        if (more) {
15796            if (!a.willChangeBounds()) {
15797                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15798                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15799                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15800                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15801                    // The child need to draw an animation, potentially offscreen, so
15802                    // make sure we do not cancel invalidate requests
15803                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15804                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15805                }
15806            } else {
15807                if (parent.mInvalidateRegion == null) {
15808                    parent.mInvalidateRegion = new RectF();
15809                }
15810                final RectF region = parent.mInvalidateRegion;
15811                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15812                        invalidationTransform);
15813
15814                // The child need to draw an animation, potentially offscreen, so
15815                // make sure we do not cancel invalidate requests
15816                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15817
15818                final int left = mLeft + (int) region.left;
15819                final int top = mTop + (int) region.top;
15820                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15821                        top + (int) (region.height() + .5f));
15822            }
15823        }
15824        return more;
15825    }
15826
15827    /**
15828     * This method is called by getDisplayList() when a display list is recorded for a View.
15829     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15830     */
15831    void setDisplayListProperties(RenderNode renderNode) {
15832        if (renderNode != null) {
15833            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15834            renderNode.setClipToBounds(mParent instanceof ViewGroup
15835                    && ((ViewGroup) mParent).getClipChildren());
15836
15837            float alpha = 1;
15838            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15839                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15840                ViewGroup parentVG = (ViewGroup) mParent;
15841                final Transformation t = parentVG.getChildTransformation();
15842                if (parentVG.getChildStaticTransformation(this, t)) {
15843                    final int transformType = t.getTransformationType();
15844                    if (transformType != Transformation.TYPE_IDENTITY) {
15845                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15846                            alpha = t.getAlpha();
15847                        }
15848                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15849                            renderNode.setStaticMatrix(t.getMatrix());
15850                        }
15851                    }
15852                }
15853            }
15854            if (mTransformationInfo != null) {
15855                alpha *= getFinalAlpha();
15856                if (alpha < 1) {
15857                    final int multipliedAlpha = (int) (255 * alpha);
15858                    if (onSetAlpha(multipliedAlpha)) {
15859                        alpha = 1;
15860                    }
15861                }
15862                renderNode.setAlpha(alpha);
15863            } else if (alpha < 1) {
15864                renderNode.setAlpha(alpha);
15865            }
15866        }
15867    }
15868
15869    /**
15870     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15871     *
15872     * This is where the View specializes rendering behavior based on layer type,
15873     * and hardware acceleration.
15874     */
15875    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15876        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15877        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15878         *
15879         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15880         * HW accelerated, it can't handle drawing RenderNodes.
15881         */
15882        boolean drawingWithRenderNode = mAttachInfo != null
15883                && mAttachInfo.mHardwareAccelerated
15884                && hardwareAcceleratedCanvas;
15885
15886        boolean more = false;
15887        final boolean childHasIdentityMatrix = hasIdentityMatrix();
15888        final int parentFlags = parent.mGroupFlags;
15889
15890        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15891            parent.getChildTransformation().clear();
15892            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15893        }
15894
15895        Transformation transformToApply = null;
15896        boolean concatMatrix = false;
15897        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15898        final Animation a = getAnimation();
15899        if (a != null) {
15900            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15901            concatMatrix = a.willChangeTransformationMatrix();
15902            if (concatMatrix) {
15903                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15904            }
15905            transformToApply = parent.getChildTransformation();
15906        } else {
15907            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15908                // No longer animating: clear out old animation matrix
15909                mRenderNode.setAnimationMatrix(null);
15910                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15911            }
15912            if (!drawingWithRenderNode
15913                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15914                final Transformation t = parent.getChildTransformation();
15915                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15916                if (hasTransform) {
15917                    final int transformType = t.getTransformationType();
15918                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15919                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15920                }
15921            }
15922        }
15923
15924        concatMatrix |= !childHasIdentityMatrix;
15925
15926        // Sets the flag as early as possible to allow draw() implementations
15927        // to call invalidate() successfully when doing animations
15928        mPrivateFlags |= PFLAG_DRAWN;
15929
15930        if (!concatMatrix &&
15931                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15932                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15933                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15934                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15935            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15936            return more;
15937        }
15938        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15939
15940        if (hardwareAcceleratedCanvas) {
15941            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15942            // retain the flag's value temporarily in the mRecreateDisplayList flag
15943            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15944            mPrivateFlags &= ~PFLAG_INVALIDATED;
15945        }
15946
15947        RenderNode renderNode = null;
15948        Bitmap cache = null;
15949        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15950        if (layerType == LAYER_TYPE_SOFTWARE
15951                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15952            // If not drawing with RenderNode, treat HW layers as SW
15953            layerType = LAYER_TYPE_SOFTWARE;
15954            buildDrawingCache(true);
15955            cache = getDrawingCache(true);
15956        }
15957
15958        if (drawingWithRenderNode) {
15959            // Delay getting the display list until animation-driven alpha values are
15960            // set up and possibly passed on to the view
15961            renderNode = updateDisplayListIfDirty();
15962            if (!renderNode.isValid()) {
15963                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15964                // to getDisplayList(), the display list will be marked invalid and we should not
15965                // try to use it again.
15966                renderNode = null;
15967                drawingWithRenderNode = false;
15968            }
15969        }
15970
15971        int sx = 0;
15972        int sy = 0;
15973        if (!drawingWithRenderNode) {
15974            computeScroll();
15975            sx = mScrollX;
15976            sy = mScrollY;
15977        }
15978
15979        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15980        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15981
15982        int restoreTo = -1;
15983        if (!drawingWithRenderNode || transformToApply != null) {
15984            restoreTo = canvas.save();
15985        }
15986        if (offsetForScroll) {
15987            canvas.translate(mLeft - sx, mTop - sy);
15988        } else {
15989            if (!drawingWithRenderNode) {
15990                canvas.translate(mLeft, mTop);
15991            }
15992            if (scalingRequired) {
15993                if (drawingWithRenderNode) {
15994                    // TODO: Might not need this if we put everything inside the DL
15995                    restoreTo = canvas.save();
15996                }
15997                // mAttachInfo cannot be null, otherwise scalingRequired == false
15998                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15999                canvas.scale(scale, scale);
16000            }
16001        }
16002
16003        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16004        if (transformToApply != null
16005                || alpha < 1
16006                || !hasIdentityMatrix()
16007                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16008            if (transformToApply != null || !childHasIdentityMatrix) {
16009                int transX = 0;
16010                int transY = 0;
16011
16012                if (offsetForScroll) {
16013                    transX = -sx;
16014                    transY = -sy;
16015                }
16016
16017                if (transformToApply != null) {
16018                    if (concatMatrix) {
16019                        if (drawingWithRenderNode) {
16020                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16021                        } else {
16022                            // Undo the scroll translation, apply the transformation matrix,
16023                            // then redo the scroll translate to get the correct result.
16024                            canvas.translate(-transX, -transY);
16025                            canvas.concat(transformToApply.getMatrix());
16026                            canvas.translate(transX, transY);
16027                        }
16028                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16029                    }
16030
16031                    float transformAlpha = transformToApply.getAlpha();
16032                    if (transformAlpha < 1) {
16033                        alpha *= transformAlpha;
16034                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16035                    }
16036                }
16037
16038                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16039                    canvas.translate(-transX, -transY);
16040                    canvas.concat(getMatrix());
16041                    canvas.translate(transX, transY);
16042                }
16043            }
16044
16045            // Deal with alpha if it is or used to be <1
16046            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16047                if (alpha < 1) {
16048                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16049                } else {
16050                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16051                }
16052                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16053                if (!drawingWithDrawingCache) {
16054                    final int multipliedAlpha = (int) (255 * alpha);
16055                    if (!onSetAlpha(multipliedAlpha)) {
16056                        if (drawingWithRenderNode) {
16057                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16058                        } else if (layerType == LAYER_TYPE_NONE) {
16059                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16060                                    multipliedAlpha);
16061                        }
16062                    } else {
16063                        // Alpha is handled by the child directly, clobber the layer's alpha
16064                        mPrivateFlags |= PFLAG_ALPHA_SET;
16065                    }
16066                }
16067            }
16068        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16069            onSetAlpha(255);
16070            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16071        }
16072
16073        if (!drawingWithRenderNode) {
16074            // apply clips directly, since RenderNode won't do it for this draw
16075            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16076                if (offsetForScroll) {
16077                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16078                } else {
16079                    if (!scalingRequired || cache == null) {
16080                        canvas.clipRect(0, 0, getWidth(), getHeight());
16081                    } else {
16082                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16083                    }
16084                }
16085            }
16086
16087            if (mClipBounds != null) {
16088                // clip bounds ignore scroll
16089                canvas.clipRect(mClipBounds);
16090            }
16091        }
16092
16093        if (!drawingWithDrawingCache) {
16094            if (drawingWithRenderNode) {
16095                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16096                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16097            } else {
16098                // Fast path for layouts with no backgrounds
16099                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16100                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16101                    dispatchDraw(canvas);
16102                } else {
16103                    draw(canvas);
16104                }
16105            }
16106        } else if (cache != null) {
16107            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16108            if (layerType == LAYER_TYPE_NONE) {
16109                // no layer paint, use temporary paint to draw bitmap
16110                Paint cachePaint = parent.mCachePaint;
16111                if (cachePaint == null) {
16112                    cachePaint = new Paint();
16113                    cachePaint.setDither(false);
16114                    parent.mCachePaint = cachePaint;
16115                }
16116                cachePaint.setAlpha((int) (alpha * 255));
16117                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16118            } else {
16119                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16120                int layerPaintAlpha = mLayerPaint.getAlpha();
16121                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16122                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16123                mLayerPaint.setAlpha(layerPaintAlpha);
16124            }
16125        }
16126
16127        if (restoreTo >= 0) {
16128            canvas.restoreToCount(restoreTo);
16129        }
16130
16131        if (a != null && !more) {
16132            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16133                onSetAlpha(255);
16134            }
16135            parent.finishAnimatingView(this, a);
16136        }
16137
16138        if (more && hardwareAcceleratedCanvas) {
16139            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16140                // alpha animations should cause the child to recreate its display list
16141                invalidate(true);
16142            }
16143        }
16144
16145        mRecreateDisplayList = false;
16146
16147        return more;
16148    }
16149
16150    /**
16151     * Manually render this view (and all of its children) to the given Canvas.
16152     * The view must have already done a full layout before this function is
16153     * called.  When implementing a view, implement
16154     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16155     * If you do need to override this method, call the superclass version.
16156     *
16157     * @param canvas The Canvas to which the View is rendered.
16158     */
16159    @CallSuper
16160    public void draw(Canvas canvas) {
16161        final int privateFlags = mPrivateFlags;
16162        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16163                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16164        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16165
16166        /*
16167         * Draw traversal performs several drawing steps which must be executed
16168         * in the appropriate order:
16169         *
16170         *      1. Draw the background
16171         *      2. If necessary, save the canvas' layers to prepare for fading
16172         *      3. Draw view's content
16173         *      4. Draw children
16174         *      5. If necessary, draw the fading edges and restore layers
16175         *      6. Draw decorations (scrollbars for instance)
16176         */
16177
16178        // Step 1, draw the background, if needed
16179        int saveCount;
16180
16181        if (!dirtyOpaque) {
16182            drawBackground(canvas);
16183        }
16184
16185        // skip step 2 & 5 if possible (common case)
16186        final int viewFlags = mViewFlags;
16187        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16188        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16189        if (!verticalEdges && !horizontalEdges) {
16190            // Step 3, draw the content
16191            if (!dirtyOpaque) onDraw(canvas);
16192
16193            // Step 4, draw the children
16194            dispatchDraw(canvas);
16195
16196            // Overlay is part of the content and draws beneath Foreground
16197            if (mOverlay != null && !mOverlay.isEmpty()) {
16198                mOverlay.getOverlayView().dispatchDraw(canvas);
16199            }
16200
16201            // Step 6, draw decorations (foreground, scrollbars)
16202            onDrawForeground(canvas);
16203
16204            // we're done...
16205            return;
16206        }
16207
16208        /*
16209         * Here we do the full fledged routine...
16210         * (this is an uncommon case where speed matters less,
16211         * this is why we repeat some of the tests that have been
16212         * done above)
16213         */
16214
16215        boolean drawTop = false;
16216        boolean drawBottom = false;
16217        boolean drawLeft = false;
16218        boolean drawRight = false;
16219
16220        float topFadeStrength = 0.0f;
16221        float bottomFadeStrength = 0.0f;
16222        float leftFadeStrength = 0.0f;
16223        float rightFadeStrength = 0.0f;
16224
16225        // Step 2, save the canvas' layers
16226        int paddingLeft = mPaddingLeft;
16227
16228        final boolean offsetRequired = isPaddingOffsetRequired();
16229        if (offsetRequired) {
16230            paddingLeft += getLeftPaddingOffset();
16231        }
16232
16233        int left = mScrollX + paddingLeft;
16234        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16235        int top = mScrollY + getFadeTop(offsetRequired);
16236        int bottom = top + getFadeHeight(offsetRequired);
16237
16238        if (offsetRequired) {
16239            right += getRightPaddingOffset();
16240            bottom += getBottomPaddingOffset();
16241        }
16242
16243        final ScrollabilityCache scrollabilityCache = mScrollCache;
16244        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16245        int length = (int) fadeHeight;
16246
16247        // clip the fade length if top and bottom fades overlap
16248        // overlapping fades produce odd-looking artifacts
16249        if (verticalEdges && (top + length > bottom - length)) {
16250            length = (bottom - top) / 2;
16251        }
16252
16253        // also clip horizontal fades if necessary
16254        if (horizontalEdges && (left + length > right - length)) {
16255            length = (right - left) / 2;
16256        }
16257
16258        if (verticalEdges) {
16259            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16260            drawTop = topFadeStrength * fadeHeight > 1.0f;
16261            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16262            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16263        }
16264
16265        if (horizontalEdges) {
16266            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16267            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16268            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16269            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16270        }
16271
16272        saveCount = canvas.getSaveCount();
16273
16274        int solidColor = getSolidColor();
16275        if (solidColor == 0) {
16276            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16277
16278            if (drawTop) {
16279                canvas.saveLayer(left, top, right, top + length, null, flags);
16280            }
16281
16282            if (drawBottom) {
16283                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16284            }
16285
16286            if (drawLeft) {
16287                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16288            }
16289
16290            if (drawRight) {
16291                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16292            }
16293        } else {
16294            scrollabilityCache.setFadeColor(solidColor);
16295        }
16296
16297        // Step 3, draw the content
16298        if (!dirtyOpaque) onDraw(canvas);
16299
16300        // Step 4, draw the children
16301        dispatchDraw(canvas);
16302
16303        // Step 5, draw the fade effect and restore layers
16304        final Paint p = scrollabilityCache.paint;
16305        final Matrix matrix = scrollabilityCache.matrix;
16306        final Shader fade = scrollabilityCache.shader;
16307
16308        if (drawTop) {
16309            matrix.setScale(1, fadeHeight * topFadeStrength);
16310            matrix.postTranslate(left, top);
16311            fade.setLocalMatrix(matrix);
16312            p.setShader(fade);
16313            canvas.drawRect(left, top, right, top + length, p);
16314        }
16315
16316        if (drawBottom) {
16317            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16318            matrix.postRotate(180);
16319            matrix.postTranslate(left, bottom);
16320            fade.setLocalMatrix(matrix);
16321            p.setShader(fade);
16322            canvas.drawRect(left, bottom - length, right, bottom, p);
16323        }
16324
16325        if (drawLeft) {
16326            matrix.setScale(1, fadeHeight * leftFadeStrength);
16327            matrix.postRotate(-90);
16328            matrix.postTranslate(left, top);
16329            fade.setLocalMatrix(matrix);
16330            p.setShader(fade);
16331            canvas.drawRect(left, top, left + length, bottom, p);
16332        }
16333
16334        if (drawRight) {
16335            matrix.setScale(1, fadeHeight * rightFadeStrength);
16336            matrix.postRotate(90);
16337            matrix.postTranslate(right, top);
16338            fade.setLocalMatrix(matrix);
16339            p.setShader(fade);
16340            canvas.drawRect(right - length, top, right, bottom, p);
16341        }
16342
16343        canvas.restoreToCount(saveCount);
16344
16345        // Overlay is part of the content and draws beneath Foreground
16346        if (mOverlay != null && !mOverlay.isEmpty()) {
16347            mOverlay.getOverlayView().dispatchDraw(canvas);
16348        }
16349
16350        // Step 6, draw decorations (foreground, scrollbars)
16351        onDrawForeground(canvas);
16352    }
16353
16354    /**
16355     * Draws the background onto the specified canvas.
16356     *
16357     * @param canvas Canvas on which to draw the background
16358     */
16359    private void drawBackground(Canvas canvas) {
16360        final Drawable background = mBackground;
16361        if (background == null) {
16362            return;
16363        }
16364
16365        setBackgroundBounds();
16366
16367        // Attempt to use a display list if requested.
16368        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16369                && mAttachInfo.mHardwareRenderer != null) {
16370            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16371
16372            final RenderNode renderNode = mBackgroundRenderNode;
16373            if (renderNode != null && renderNode.isValid()) {
16374                setBackgroundRenderNodeProperties(renderNode);
16375                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16376                return;
16377            }
16378        }
16379
16380        final int scrollX = mScrollX;
16381        final int scrollY = mScrollY;
16382        if ((scrollX | scrollY) == 0) {
16383            background.draw(canvas);
16384        } else {
16385            canvas.translate(scrollX, scrollY);
16386            background.draw(canvas);
16387            canvas.translate(-scrollX, -scrollY);
16388        }
16389    }
16390
16391    /**
16392     * Sets the correct background bounds and rebuilds the outline, if needed.
16393     * <p/>
16394     * This is called by LayoutLib.
16395     */
16396    void setBackgroundBounds() {
16397        if (mBackgroundSizeChanged && mBackground != null) {
16398            mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
16399            mBackgroundSizeChanged = false;
16400            rebuildOutline();
16401        }
16402    }
16403
16404    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16405        renderNode.setTranslationX(mScrollX);
16406        renderNode.setTranslationY(mScrollY);
16407    }
16408
16409    /**
16410     * Creates a new display list or updates the existing display list for the
16411     * specified Drawable.
16412     *
16413     * @param drawable Drawable for which to create a display list
16414     * @param renderNode Existing RenderNode, or {@code null}
16415     * @return A valid display list for the specified drawable
16416     */
16417    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16418        if (renderNode == null) {
16419            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16420        }
16421
16422        final Rect bounds = drawable.getBounds();
16423        final int width = bounds.width();
16424        final int height = bounds.height();
16425        final DisplayListCanvas canvas = renderNode.start(width, height);
16426
16427        // Reverse left/top translation done by drawable canvas, which will
16428        // instead be applied by rendernode's LTRB bounds below. This way, the
16429        // drawable's bounds match with its rendernode bounds and its content
16430        // will lie within those bounds in the rendernode tree.
16431        canvas.translate(-bounds.left, -bounds.top);
16432
16433        try {
16434            drawable.draw(canvas);
16435        } finally {
16436            renderNode.end(canvas);
16437        }
16438
16439        // Set up drawable properties that are view-independent.
16440        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16441        renderNode.setProjectBackwards(drawable.isProjected());
16442        renderNode.setProjectionReceiver(true);
16443        renderNode.setClipToBounds(false);
16444        return renderNode;
16445    }
16446
16447    /**
16448     * Returns the overlay for this view, creating it if it does not yet exist.
16449     * Adding drawables to the overlay will cause them to be displayed whenever
16450     * the view itself is redrawn. Objects in the overlay should be actively
16451     * managed: remove them when they should not be displayed anymore. The
16452     * overlay will always have the same size as its host view.
16453     *
16454     * <p>Note: Overlays do not currently work correctly with {@link
16455     * SurfaceView} or {@link TextureView}; contents in overlays for these
16456     * types of views may not display correctly.</p>
16457     *
16458     * @return The ViewOverlay object for this view.
16459     * @see ViewOverlay
16460     */
16461    public ViewOverlay getOverlay() {
16462        if (mOverlay == null) {
16463            mOverlay = new ViewOverlay(mContext, this);
16464        }
16465        return mOverlay;
16466    }
16467
16468    /**
16469     * Override this if your view is known to always be drawn on top of a solid color background,
16470     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16471     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16472     * should be set to 0xFF.
16473     *
16474     * @see #setVerticalFadingEdgeEnabled(boolean)
16475     * @see #setHorizontalFadingEdgeEnabled(boolean)
16476     *
16477     * @return The known solid color background for this view, or 0 if the color may vary
16478     */
16479    @ViewDebug.ExportedProperty(category = "drawing")
16480    @ColorInt
16481    public int getSolidColor() {
16482        return 0;
16483    }
16484
16485    /**
16486     * Build a human readable string representation of the specified view flags.
16487     *
16488     * @param flags the view flags to convert to a string
16489     * @return a String representing the supplied flags
16490     */
16491    private static String printFlags(int flags) {
16492        String output = "";
16493        int numFlags = 0;
16494        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16495            output += "TAKES_FOCUS";
16496            numFlags++;
16497        }
16498
16499        switch (flags & VISIBILITY_MASK) {
16500        case INVISIBLE:
16501            if (numFlags > 0) {
16502                output += " ";
16503            }
16504            output += "INVISIBLE";
16505            // USELESS HERE numFlags++;
16506            break;
16507        case GONE:
16508            if (numFlags > 0) {
16509                output += " ";
16510            }
16511            output += "GONE";
16512            // USELESS HERE numFlags++;
16513            break;
16514        default:
16515            break;
16516        }
16517        return output;
16518    }
16519
16520    /**
16521     * Build a human readable string representation of the specified private
16522     * view flags.
16523     *
16524     * @param privateFlags the private view flags to convert to a string
16525     * @return a String representing the supplied flags
16526     */
16527    private static String printPrivateFlags(int privateFlags) {
16528        String output = "";
16529        int numFlags = 0;
16530
16531        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16532            output += "WANTS_FOCUS";
16533            numFlags++;
16534        }
16535
16536        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16537            if (numFlags > 0) {
16538                output += " ";
16539            }
16540            output += "FOCUSED";
16541            numFlags++;
16542        }
16543
16544        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16545            if (numFlags > 0) {
16546                output += " ";
16547            }
16548            output += "SELECTED";
16549            numFlags++;
16550        }
16551
16552        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16553            if (numFlags > 0) {
16554                output += " ";
16555            }
16556            output += "IS_ROOT_NAMESPACE";
16557            numFlags++;
16558        }
16559
16560        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16561            if (numFlags > 0) {
16562                output += " ";
16563            }
16564            output += "HAS_BOUNDS";
16565            numFlags++;
16566        }
16567
16568        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16569            if (numFlags > 0) {
16570                output += " ";
16571            }
16572            output += "DRAWN";
16573            // USELESS HERE numFlags++;
16574        }
16575        return output;
16576    }
16577
16578    /**
16579     * <p>Indicates whether or not this view's layout will be requested during
16580     * the next hierarchy layout pass.</p>
16581     *
16582     * @return true if the layout will be forced during next layout pass
16583     */
16584    public boolean isLayoutRequested() {
16585        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16586    }
16587
16588    /**
16589     * Return true if o is a ViewGroup that is laying out using optical bounds.
16590     * @hide
16591     */
16592    public static boolean isLayoutModeOptical(Object o) {
16593        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16594    }
16595
16596    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16597        Insets parentInsets = mParent instanceof View ?
16598                ((View) mParent).getOpticalInsets() : Insets.NONE;
16599        Insets childInsets = getOpticalInsets();
16600        return setFrame(
16601                left   + parentInsets.left - childInsets.left,
16602                top    + parentInsets.top  - childInsets.top,
16603                right  + parentInsets.left + childInsets.right,
16604                bottom + parentInsets.top  + childInsets.bottom);
16605    }
16606
16607    /**
16608     * Assign a size and position to a view and all of its
16609     * descendants
16610     *
16611     * <p>This is the second phase of the layout mechanism.
16612     * (The first is measuring). In this phase, each parent calls
16613     * layout on all of its children to position them.
16614     * This is typically done using the child measurements
16615     * that were stored in the measure pass().</p>
16616     *
16617     * <p>Derived classes should not override this method.
16618     * Derived classes with children should override
16619     * onLayout. In that method, they should
16620     * call layout on each of their children.</p>
16621     *
16622     * @param l Left position, relative to parent
16623     * @param t Top position, relative to parent
16624     * @param r Right position, relative to parent
16625     * @param b Bottom position, relative to parent
16626     */
16627    @SuppressWarnings({"unchecked"})
16628    public void layout(int l, int t, int r, int b) {
16629        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16630            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16631            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16632        }
16633
16634        int oldL = mLeft;
16635        int oldT = mTop;
16636        int oldB = mBottom;
16637        int oldR = mRight;
16638
16639        boolean changed = isLayoutModeOptical(mParent) ?
16640                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16641
16642        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16643            onLayout(changed, l, t, r, b);
16644            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16645
16646            ListenerInfo li = mListenerInfo;
16647            if (li != null && li.mOnLayoutChangeListeners != null) {
16648                ArrayList<OnLayoutChangeListener> listenersCopy =
16649                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16650                int numListeners = listenersCopy.size();
16651                for (int i = 0; i < numListeners; ++i) {
16652                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16653                }
16654            }
16655        }
16656
16657        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16658        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16659    }
16660
16661    /**
16662     * Called from layout when this view should
16663     * assign a size and position to each of its children.
16664     *
16665     * Derived classes with children should override
16666     * this method and call layout on each of
16667     * their children.
16668     * @param changed This is a new size or position for this view
16669     * @param left Left position, relative to parent
16670     * @param top Top position, relative to parent
16671     * @param right Right position, relative to parent
16672     * @param bottom Bottom position, relative to parent
16673     */
16674    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16675    }
16676
16677    /**
16678     * Assign a size and position to this view.
16679     *
16680     * This is called from layout.
16681     *
16682     * @param left Left position, relative to parent
16683     * @param top Top position, relative to parent
16684     * @param right Right position, relative to parent
16685     * @param bottom Bottom position, relative to parent
16686     * @return true if the new size and position are different than the
16687     *         previous ones
16688     * {@hide}
16689     */
16690    protected boolean setFrame(int left, int top, int right, int bottom) {
16691        boolean changed = false;
16692
16693        if (DBG) {
16694            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16695                    + right + "," + bottom + ")");
16696        }
16697
16698        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16699            changed = true;
16700
16701            // Remember our drawn bit
16702            int drawn = mPrivateFlags & PFLAG_DRAWN;
16703
16704            int oldWidth = mRight - mLeft;
16705            int oldHeight = mBottom - mTop;
16706            int newWidth = right - left;
16707            int newHeight = bottom - top;
16708            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16709
16710            // Invalidate our old position
16711            invalidate(sizeChanged);
16712
16713            mLeft = left;
16714            mTop = top;
16715            mRight = right;
16716            mBottom = bottom;
16717            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16718
16719            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16720
16721
16722            if (sizeChanged) {
16723                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16724            }
16725
16726            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16727                // If we are visible, force the DRAWN bit to on so that
16728                // this invalidate will go through (at least to our parent).
16729                // This is because someone may have invalidated this view
16730                // before this call to setFrame came in, thereby clearing
16731                // the DRAWN bit.
16732                mPrivateFlags |= PFLAG_DRAWN;
16733                invalidate(sizeChanged);
16734                // parent display list may need to be recreated based on a change in the bounds
16735                // of any child
16736                invalidateParentCaches();
16737            }
16738
16739            // Reset drawn bit to original value (invalidate turns it off)
16740            mPrivateFlags |= drawn;
16741
16742            mBackgroundSizeChanged = true;
16743            if (mForegroundInfo != null) {
16744                mForegroundInfo.mBoundsChanged = true;
16745            }
16746
16747            notifySubtreeAccessibilityStateChangedIfNeeded();
16748        }
16749        return changed;
16750    }
16751
16752    /**
16753     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16754     * @hide
16755     */
16756    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16757        setFrame(left, top, right, bottom);
16758    }
16759
16760    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16761        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16762        if (mOverlay != null) {
16763            mOverlay.getOverlayView().setRight(newWidth);
16764            mOverlay.getOverlayView().setBottom(newHeight);
16765        }
16766        rebuildOutline();
16767    }
16768
16769    /**
16770     * Finalize inflating a view from XML.  This is called as the last phase
16771     * of inflation, after all child views have been added.
16772     *
16773     * <p>Even if the subclass overrides onFinishInflate, they should always be
16774     * sure to call the super method, so that we get called.
16775     */
16776    @CallSuper
16777    protected void onFinishInflate() {
16778    }
16779
16780    /**
16781     * Returns the resources associated with this view.
16782     *
16783     * @return Resources object.
16784     */
16785    public Resources getResources() {
16786        return mResources;
16787    }
16788
16789    /**
16790     * Invalidates the specified Drawable.
16791     *
16792     * @param drawable the drawable to invalidate
16793     */
16794    @Override
16795    public void invalidateDrawable(@NonNull Drawable drawable) {
16796        if (verifyDrawable(drawable)) {
16797            final Rect dirty = drawable.getDirtyBounds();
16798            final int scrollX = mScrollX;
16799            final int scrollY = mScrollY;
16800
16801            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16802                    dirty.right + scrollX, dirty.bottom + scrollY);
16803            rebuildOutline();
16804        }
16805    }
16806
16807    /**
16808     * Schedules an action on a drawable to occur at a specified time.
16809     *
16810     * @param who the recipient of the action
16811     * @param what the action to run on the drawable
16812     * @param when the time at which the action must occur. Uses the
16813     *        {@link SystemClock#uptimeMillis} timebase.
16814     */
16815    @Override
16816    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16817        if (verifyDrawable(who) && what != null) {
16818            final long delay = when - SystemClock.uptimeMillis();
16819            if (mAttachInfo != null) {
16820                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16821                        Choreographer.CALLBACK_ANIMATION, what, who,
16822                        Choreographer.subtractFrameDelay(delay));
16823            } else {
16824                ViewRootImpl.getRunQueue().postDelayed(what, delay);
16825            }
16826        }
16827    }
16828
16829    /**
16830     * Cancels a scheduled action on a drawable.
16831     *
16832     * @param who the recipient of the action
16833     * @param what the action to cancel
16834     */
16835    @Override
16836    public void unscheduleDrawable(Drawable who, Runnable what) {
16837        if (verifyDrawable(who) && what != null) {
16838            if (mAttachInfo != null) {
16839                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16840                        Choreographer.CALLBACK_ANIMATION, what, who);
16841            }
16842            ViewRootImpl.getRunQueue().removeCallbacks(what);
16843        }
16844    }
16845
16846    /**
16847     * Unschedule any events associated with the given Drawable.  This can be
16848     * used when selecting a new Drawable into a view, so that the previous
16849     * one is completely unscheduled.
16850     *
16851     * @param who The Drawable to unschedule.
16852     *
16853     * @see #drawableStateChanged
16854     */
16855    public void unscheduleDrawable(Drawable who) {
16856        if (mAttachInfo != null && who != null) {
16857            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16858                    Choreographer.CALLBACK_ANIMATION, null, who);
16859        }
16860    }
16861
16862    /**
16863     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16864     * that the View directionality can and will be resolved before its Drawables.
16865     *
16866     * Will call {@link View#onResolveDrawables} when resolution is done.
16867     *
16868     * @hide
16869     */
16870    protected void resolveDrawables() {
16871        // Drawables resolution may need to happen before resolving the layout direction (which is
16872        // done only during the measure() call).
16873        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16874        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16875        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16876        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16877        // direction to be resolved as its resolved value will be the same as its raw value.
16878        if (!isLayoutDirectionResolved() &&
16879                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16880            return;
16881        }
16882
16883        final int layoutDirection = isLayoutDirectionResolved() ?
16884                getLayoutDirection() : getRawLayoutDirection();
16885
16886        if (mBackground != null) {
16887            mBackground.setLayoutDirection(layoutDirection);
16888        }
16889        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16890            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16891        }
16892        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16893        onResolveDrawables(layoutDirection);
16894    }
16895
16896    boolean areDrawablesResolved() {
16897        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16898    }
16899
16900    /**
16901     * Called when layout direction has been resolved.
16902     *
16903     * The default implementation does nothing.
16904     *
16905     * @param layoutDirection The resolved layout direction.
16906     *
16907     * @see #LAYOUT_DIRECTION_LTR
16908     * @see #LAYOUT_DIRECTION_RTL
16909     *
16910     * @hide
16911     */
16912    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16913    }
16914
16915    /**
16916     * @hide
16917     */
16918    protected void resetResolvedDrawables() {
16919        resetResolvedDrawablesInternal();
16920    }
16921
16922    void resetResolvedDrawablesInternal() {
16923        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16924    }
16925
16926    /**
16927     * If your view subclass is displaying its own Drawable objects, it should
16928     * override this function and return true for any Drawable it is
16929     * displaying.  This allows animations for those drawables to be
16930     * scheduled.
16931     *
16932     * <p>Be sure to call through to the super class when overriding this
16933     * function.
16934     *
16935     * @param who The Drawable to verify.  Return true if it is one you are
16936     *            displaying, else return the result of calling through to the
16937     *            super class.
16938     *
16939     * @return boolean If true than the Drawable is being displayed in the
16940     *         view; else false and it is not allowed to animate.
16941     *
16942     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16943     * @see #drawableStateChanged()
16944     */
16945    @CallSuper
16946    protected boolean verifyDrawable(Drawable who) {
16947        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16948                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16949    }
16950
16951    /**
16952     * This function is called whenever the state of the view changes in such
16953     * a way that it impacts the state of drawables being shown.
16954     * <p>
16955     * If the View has a StateListAnimator, it will also be called to run necessary state
16956     * change animations.
16957     * <p>
16958     * Be sure to call through to the superclass when overriding this function.
16959     *
16960     * @see Drawable#setState(int[])
16961     */
16962    @CallSuper
16963    protected void drawableStateChanged() {
16964        final int[] state = getDrawableState();
16965
16966        final Drawable bg = mBackground;
16967        if (bg != null && bg.isStateful()) {
16968            bg.setState(state);
16969        }
16970
16971        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16972        if (fg != null && fg.isStateful()) {
16973            fg.setState(state);
16974        }
16975
16976        if (mScrollCache != null) {
16977            final Drawable scrollBar = mScrollCache.scrollBar;
16978            if (scrollBar != null && scrollBar.isStateful()) {
16979                scrollBar.setState(state);
16980            }
16981        }
16982
16983        if (mStateListAnimator != null) {
16984            mStateListAnimator.setState(state);
16985        }
16986    }
16987
16988    /**
16989     * This function is called whenever the view hotspot changes and needs to
16990     * be propagated to drawables or child views managed by the view.
16991     * <p>
16992     * Dispatching to child views is handled by
16993     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16994     * <p>
16995     * Be sure to call through to the superclass when overriding this function.
16996     *
16997     * @param x hotspot x coordinate
16998     * @param y hotspot y coordinate
16999     */
17000    @CallSuper
17001    public void drawableHotspotChanged(float x, float y) {
17002        if (mBackground != null) {
17003            mBackground.setHotspot(x, y);
17004        }
17005        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17006            mForegroundInfo.mDrawable.setHotspot(x, y);
17007        }
17008
17009        dispatchDrawableHotspotChanged(x, y);
17010    }
17011
17012    /**
17013     * Dispatches drawableHotspotChanged to all of this View's children.
17014     *
17015     * @param x hotspot x coordinate
17016     * @param y hotspot y coordinate
17017     * @see #drawableHotspotChanged(float, float)
17018     */
17019    public void dispatchDrawableHotspotChanged(float x, float y) {
17020    }
17021
17022    /**
17023     * Call this to force a view to update its drawable state. This will cause
17024     * drawableStateChanged to be called on this view. Views that are interested
17025     * in the new state should call getDrawableState.
17026     *
17027     * @see #drawableStateChanged
17028     * @see #getDrawableState
17029     */
17030    public void refreshDrawableState() {
17031        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17032        drawableStateChanged();
17033
17034        ViewParent parent = mParent;
17035        if (parent != null) {
17036            parent.childDrawableStateChanged(this);
17037        }
17038    }
17039
17040    /**
17041     * Return an array of resource IDs of the drawable states representing the
17042     * current state of the view.
17043     *
17044     * @return The current drawable state
17045     *
17046     * @see Drawable#setState(int[])
17047     * @see #drawableStateChanged()
17048     * @see #onCreateDrawableState(int)
17049     */
17050    public final int[] getDrawableState() {
17051        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17052            return mDrawableState;
17053        } else {
17054            mDrawableState = onCreateDrawableState(0);
17055            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17056            return mDrawableState;
17057        }
17058    }
17059
17060    /**
17061     * Generate the new {@link android.graphics.drawable.Drawable} state for
17062     * this view. This is called by the view
17063     * system when the cached Drawable state is determined to be invalid.  To
17064     * retrieve the current state, you should use {@link #getDrawableState}.
17065     *
17066     * @param extraSpace if non-zero, this is the number of extra entries you
17067     * would like in the returned array in which you can place your own
17068     * states.
17069     *
17070     * @return Returns an array holding the current {@link Drawable} state of
17071     * the view.
17072     *
17073     * @see #mergeDrawableStates(int[], int[])
17074     */
17075    protected int[] onCreateDrawableState(int extraSpace) {
17076        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17077                mParent instanceof View) {
17078            return ((View) mParent).onCreateDrawableState(extraSpace);
17079        }
17080
17081        int[] drawableState;
17082
17083        int privateFlags = mPrivateFlags;
17084
17085        int viewStateIndex = 0;
17086        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17087        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17088        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17089        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17090        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17091        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17092        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17093                HardwareRenderer.isAvailable()) {
17094            // This is set if HW acceleration is requested, even if the current
17095            // process doesn't allow it.  This is just to allow app preview
17096            // windows to better match their app.
17097            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17098        }
17099        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17100
17101        final int privateFlags2 = mPrivateFlags2;
17102        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17103            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17104        }
17105        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17106            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17107        }
17108
17109        drawableState = StateSet.get(viewStateIndex);
17110
17111        //noinspection ConstantIfStatement
17112        if (false) {
17113            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17114            Log.i("View", toString()
17115                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17116                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17117                    + " fo=" + hasFocus()
17118                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17119                    + " wf=" + hasWindowFocus()
17120                    + ": " + Arrays.toString(drawableState));
17121        }
17122
17123        if (extraSpace == 0) {
17124            return drawableState;
17125        }
17126
17127        final int[] fullState;
17128        if (drawableState != null) {
17129            fullState = new int[drawableState.length + extraSpace];
17130            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17131        } else {
17132            fullState = new int[extraSpace];
17133        }
17134
17135        return fullState;
17136    }
17137
17138    /**
17139     * Merge your own state values in <var>additionalState</var> into the base
17140     * state values <var>baseState</var> that were returned by
17141     * {@link #onCreateDrawableState(int)}.
17142     *
17143     * @param baseState The base state values returned by
17144     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17145     * own additional state values.
17146     *
17147     * @param additionalState The additional state values you would like
17148     * added to <var>baseState</var>; this array is not modified.
17149     *
17150     * @return As a convenience, the <var>baseState</var> array you originally
17151     * passed into the function is returned.
17152     *
17153     * @see #onCreateDrawableState(int)
17154     */
17155    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17156        final int N = baseState.length;
17157        int i = N - 1;
17158        while (i >= 0 && baseState[i] == 0) {
17159            i--;
17160        }
17161        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17162        return baseState;
17163    }
17164
17165    /**
17166     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17167     * on all Drawable objects associated with this view.
17168     * <p>
17169     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17170     * attached to this view.
17171     */
17172    @CallSuper
17173    public void jumpDrawablesToCurrentState() {
17174        if (mBackground != null) {
17175            mBackground.jumpToCurrentState();
17176        }
17177        if (mStateListAnimator != null) {
17178            mStateListAnimator.jumpToCurrentState();
17179        }
17180        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17181            mForegroundInfo.mDrawable.jumpToCurrentState();
17182        }
17183    }
17184
17185    /**
17186     * Sets the background color for this view.
17187     * @param color the color of the background
17188     */
17189    @RemotableViewMethod
17190    public void setBackgroundColor(@ColorInt int color) {
17191        if (mBackground instanceof ColorDrawable) {
17192            ((ColorDrawable) mBackground.mutate()).setColor(color);
17193            computeOpaqueFlags();
17194            mBackgroundResource = 0;
17195        } else {
17196            setBackground(new ColorDrawable(color));
17197        }
17198    }
17199
17200    /**
17201     * Set the background to a given resource. The resource should refer to
17202     * a Drawable object or 0 to remove the background.
17203     * @param resid The identifier of the resource.
17204     *
17205     * @attr ref android.R.styleable#View_background
17206     */
17207    @RemotableViewMethod
17208    public void setBackgroundResource(@DrawableRes int resid) {
17209        if (resid != 0 && resid == mBackgroundResource) {
17210            return;
17211        }
17212
17213        Drawable d = null;
17214        if (resid != 0) {
17215            d = mContext.getDrawable(resid);
17216        }
17217        setBackground(d);
17218
17219        mBackgroundResource = resid;
17220    }
17221
17222    /**
17223     * Set the background to a given Drawable, or remove the background. If the
17224     * background has padding, this View's padding is set to the background's
17225     * padding. However, when a background is removed, this View's padding isn't
17226     * touched. If setting the padding is desired, please use
17227     * {@link #setPadding(int, int, int, int)}.
17228     *
17229     * @param background The Drawable to use as the background, or null to remove the
17230     *        background
17231     */
17232    public void setBackground(Drawable background) {
17233        //noinspection deprecation
17234        setBackgroundDrawable(background);
17235    }
17236
17237    /**
17238     * @deprecated use {@link #setBackground(Drawable)} instead
17239     */
17240    @Deprecated
17241    public void setBackgroundDrawable(Drawable background) {
17242        computeOpaqueFlags();
17243
17244        if (background == mBackground) {
17245            return;
17246        }
17247
17248        boolean requestLayout = false;
17249
17250        mBackgroundResource = 0;
17251
17252        /*
17253         * Regardless of whether we're setting a new background or not, we want
17254         * to clear the previous drawable.
17255         */
17256        if (mBackground != null) {
17257            mBackground.setCallback(null);
17258            unscheduleDrawable(mBackground);
17259        }
17260
17261        if (background != null) {
17262            Rect padding = sThreadLocal.get();
17263            if (padding == null) {
17264                padding = new Rect();
17265                sThreadLocal.set(padding);
17266            }
17267            resetResolvedDrawablesInternal();
17268            background.setLayoutDirection(getLayoutDirection());
17269            if (background.getPadding(padding)) {
17270                resetResolvedPaddingInternal();
17271                switch (background.getLayoutDirection()) {
17272                    case LAYOUT_DIRECTION_RTL:
17273                        mUserPaddingLeftInitial = padding.right;
17274                        mUserPaddingRightInitial = padding.left;
17275                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17276                        break;
17277                    case LAYOUT_DIRECTION_LTR:
17278                    default:
17279                        mUserPaddingLeftInitial = padding.left;
17280                        mUserPaddingRightInitial = padding.right;
17281                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17282                }
17283                mLeftPaddingDefined = false;
17284                mRightPaddingDefined = false;
17285            }
17286
17287            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17288            // if it has a different minimum size, we should layout again
17289            if (mBackground == null
17290                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17291                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17292                requestLayout = true;
17293            }
17294
17295            background.setCallback(this);
17296            if (background.isStateful()) {
17297                background.setState(getDrawableState());
17298            }
17299            background.setVisible(getVisibility() == VISIBLE, false);
17300            mBackground = background;
17301
17302            applyBackgroundTint();
17303
17304            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17305                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17306                requestLayout = true;
17307            }
17308        } else {
17309            /* Remove the background */
17310            mBackground = null;
17311            if ((mViewFlags & WILL_NOT_DRAW) != 0
17312                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17313                mPrivateFlags |= PFLAG_SKIP_DRAW;
17314            }
17315
17316            /*
17317             * When the background is set, we try to apply its padding to this
17318             * View. When the background is removed, we don't touch this View's
17319             * padding. This is noted in the Javadocs. Hence, we don't need to
17320             * requestLayout(), the invalidate() below is sufficient.
17321             */
17322
17323            // The old background's minimum size could have affected this
17324            // View's layout, so let's requestLayout
17325            requestLayout = true;
17326        }
17327
17328        computeOpaqueFlags();
17329
17330        if (requestLayout) {
17331            requestLayout();
17332        }
17333
17334        mBackgroundSizeChanged = true;
17335        invalidate(true);
17336    }
17337
17338    /**
17339     * Gets the background drawable
17340     *
17341     * @return The drawable used as the background for this view, if any.
17342     *
17343     * @see #setBackground(Drawable)
17344     *
17345     * @attr ref android.R.styleable#View_background
17346     */
17347    public Drawable getBackground() {
17348        return mBackground;
17349    }
17350
17351    /**
17352     * Applies a tint to the background drawable. Does not modify the current tint
17353     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17354     * <p>
17355     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17356     * mutate the drawable and apply the specified tint and tint mode using
17357     * {@link Drawable#setTintList(ColorStateList)}.
17358     *
17359     * @param tint the tint to apply, may be {@code null} to clear tint
17360     *
17361     * @attr ref android.R.styleable#View_backgroundTint
17362     * @see #getBackgroundTintList()
17363     * @see Drawable#setTintList(ColorStateList)
17364     */
17365    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17366        if (mBackgroundTint == null) {
17367            mBackgroundTint = new TintInfo();
17368        }
17369        mBackgroundTint.mTintList = tint;
17370        mBackgroundTint.mHasTintList = true;
17371
17372        applyBackgroundTint();
17373    }
17374
17375    /**
17376     * Return the tint applied to the background drawable, if specified.
17377     *
17378     * @return the tint applied to the background drawable
17379     * @attr ref android.R.styleable#View_backgroundTint
17380     * @see #setBackgroundTintList(ColorStateList)
17381     */
17382    @Nullable
17383    public ColorStateList getBackgroundTintList() {
17384        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17385    }
17386
17387    /**
17388     * Specifies the blending mode used to apply the tint specified by
17389     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17390     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17391     *
17392     * @param tintMode the blending mode used to apply the tint, may be
17393     *                 {@code null} to clear tint
17394     * @attr ref android.R.styleable#View_backgroundTintMode
17395     * @see #getBackgroundTintMode()
17396     * @see Drawable#setTintMode(PorterDuff.Mode)
17397     */
17398    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17399        if (mBackgroundTint == null) {
17400            mBackgroundTint = new TintInfo();
17401        }
17402        mBackgroundTint.mTintMode = tintMode;
17403        mBackgroundTint.mHasTintMode = true;
17404
17405        applyBackgroundTint();
17406    }
17407
17408    /**
17409     * Return the blending mode used to apply the tint to the background
17410     * drawable, if specified.
17411     *
17412     * @return the blending mode used to apply the tint to the background
17413     *         drawable
17414     * @attr ref android.R.styleable#View_backgroundTintMode
17415     * @see #setBackgroundTintMode(PorterDuff.Mode)
17416     */
17417    @Nullable
17418    public PorterDuff.Mode getBackgroundTintMode() {
17419        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17420    }
17421
17422    private void applyBackgroundTint() {
17423        if (mBackground != null && mBackgroundTint != null) {
17424            final TintInfo tintInfo = mBackgroundTint;
17425            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17426                mBackground = mBackground.mutate();
17427
17428                if (tintInfo.mHasTintList) {
17429                    mBackground.setTintList(tintInfo.mTintList);
17430                }
17431
17432                if (tintInfo.mHasTintMode) {
17433                    mBackground.setTintMode(tintInfo.mTintMode);
17434                }
17435
17436                // The drawable (or one of its children) may not have been
17437                // stateful before applying the tint, so let's try again.
17438                if (mBackground.isStateful()) {
17439                    mBackground.setState(getDrawableState());
17440                }
17441            }
17442        }
17443    }
17444
17445    /**
17446     * Returns the drawable used as the foreground of this View. The
17447     * foreground drawable, if non-null, is always drawn on top of the view's content.
17448     *
17449     * @return a Drawable or null if no foreground was set
17450     *
17451     * @see #onDrawForeground(Canvas)
17452     */
17453    public Drawable getForeground() {
17454        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17455    }
17456
17457    /**
17458     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17459     *
17460     * @param foreground the Drawable to be drawn on top of the children
17461     *
17462     * @attr ref android.R.styleable#View_foreground
17463     */
17464    public void setForeground(Drawable foreground) {
17465        if (mForegroundInfo == null) {
17466            if (foreground == null) {
17467                // Nothing to do.
17468                return;
17469            }
17470            mForegroundInfo = new ForegroundInfo();
17471        }
17472
17473        if (foreground == mForegroundInfo.mDrawable) {
17474            // Nothing to do
17475            return;
17476        }
17477
17478        if (mForegroundInfo.mDrawable != null) {
17479            mForegroundInfo.mDrawable.setCallback(null);
17480            unscheduleDrawable(mForegroundInfo.mDrawable);
17481        }
17482
17483        mForegroundInfo.mDrawable = foreground;
17484        mForegroundInfo.mBoundsChanged = true;
17485        if (foreground != null) {
17486            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17487                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17488            }
17489            foreground.setCallback(this);
17490            foreground.setLayoutDirection(getLayoutDirection());
17491            if (foreground.isStateful()) {
17492                foreground.setState(getDrawableState());
17493            }
17494            applyForegroundTint();
17495        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17496            mPrivateFlags |= PFLAG_SKIP_DRAW;
17497        }
17498        requestLayout();
17499        invalidate();
17500    }
17501
17502    /**
17503     * Magic bit used to support features of framework-internal window decor implementation details.
17504     * This used to live exclusively in FrameLayout.
17505     *
17506     * @return true if the foreground should draw inside the padding region or false
17507     *         if it should draw inset by the view's padding
17508     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17509     */
17510    public boolean isForegroundInsidePadding() {
17511        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17512    }
17513
17514    /**
17515     * Describes how the foreground is positioned.
17516     *
17517     * @return foreground gravity.
17518     *
17519     * @see #setForegroundGravity(int)
17520     *
17521     * @attr ref android.R.styleable#View_foregroundGravity
17522     */
17523    public int getForegroundGravity() {
17524        return mForegroundInfo != null ? mForegroundInfo.mGravity
17525                : Gravity.START | Gravity.TOP;
17526    }
17527
17528    /**
17529     * Describes how the foreground is positioned. Defaults to START and TOP.
17530     *
17531     * @param gravity see {@link android.view.Gravity}
17532     *
17533     * @see #getForegroundGravity()
17534     *
17535     * @attr ref android.R.styleable#View_foregroundGravity
17536     */
17537    public void setForegroundGravity(int gravity) {
17538        if (mForegroundInfo == null) {
17539            mForegroundInfo = new ForegroundInfo();
17540        }
17541
17542        if (mForegroundInfo.mGravity != gravity) {
17543            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17544                gravity |= Gravity.START;
17545            }
17546
17547            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17548                gravity |= Gravity.TOP;
17549            }
17550
17551            mForegroundInfo.mGravity = gravity;
17552            requestLayout();
17553        }
17554    }
17555
17556    /**
17557     * Applies a tint to the foreground drawable. Does not modify the current tint
17558     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17559     * <p>
17560     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17561     * mutate the drawable and apply the specified tint and tint mode using
17562     * {@link Drawable#setTintList(ColorStateList)}.
17563     *
17564     * @param tint the tint to apply, may be {@code null} to clear tint
17565     *
17566     * @attr ref android.R.styleable#View_foregroundTint
17567     * @see #getForegroundTintList()
17568     * @see Drawable#setTintList(ColorStateList)
17569     */
17570    public void setForegroundTintList(@Nullable ColorStateList tint) {
17571        if (mForegroundInfo == null) {
17572            mForegroundInfo = new ForegroundInfo();
17573        }
17574        if (mForegroundInfo.mTintInfo == null) {
17575            mForegroundInfo.mTintInfo = new TintInfo();
17576        }
17577        mForegroundInfo.mTintInfo.mTintList = tint;
17578        mForegroundInfo.mTintInfo.mHasTintList = true;
17579
17580        applyForegroundTint();
17581    }
17582
17583    /**
17584     * Return the tint applied to the foreground drawable, if specified.
17585     *
17586     * @return the tint applied to the foreground drawable
17587     * @attr ref android.R.styleable#View_foregroundTint
17588     * @see #setForegroundTintList(ColorStateList)
17589     */
17590    @Nullable
17591    public ColorStateList getForegroundTintList() {
17592        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17593                ? mForegroundInfo.mTintInfo.mTintList : null;
17594    }
17595
17596    /**
17597     * Specifies the blending mode used to apply the tint specified by
17598     * {@link #setForegroundTintList(ColorStateList)}} to the background
17599     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17600     *
17601     * @param tintMode the blending mode used to apply the tint, may be
17602     *                 {@code null} to clear tint
17603     * @attr ref android.R.styleable#View_foregroundTintMode
17604     * @see #getForegroundTintMode()
17605     * @see Drawable#setTintMode(PorterDuff.Mode)
17606     */
17607    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17608        if (mForegroundInfo == null) {
17609            mForegroundInfo = new ForegroundInfo();
17610        }
17611        if (mForegroundInfo.mTintInfo == null) {
17612            mForegroundInfo.mTintInfo = new TintInfo();
17613        }
17614        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17615        mForegroundInfo.mTintInfo.mHasTintMode = true;
17616
17617        applyForegroundTint();
17618    }
17619
17620    /**
17621     * Return the blending mode used to apply the tint to the foreground
17622     * drawable, if specified.
17623     *
17624     * @return the blending mode used to apply the tint to the foreground
17625     *         drawable
17626     * @attr ref android.R.styleable#View_foregroundTintMode
17627     * @see #setForegroundTintMode(PorterDuff.Mode)
17628     */
17629    @Nullable
17630    public PorterDuff.Mode getForegroundTintMode() {
17631        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17632                ? mForegroundInfo.mTintInfo.mTintMode : null;
17633    }
17634
17635    private void applyForegroundTint() {
17636        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17637                && mForegroundInfo.mTintInfo != null) {
17638            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17639            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17640                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17641
17642                if (tintInfo.mHasTintList) {
17643                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17644                }
17645
17646                if (tintInfo.mHasTintMode) {
17647                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17648                }
17649
17650                // The drawable (or one of its children) may not have been
17651                // stateful before applying the tint, so let's try again.
17652                if (mForegroundInfo.mDrawable.isStateful()) {
17653                    mForegroundInfo.mDrawable.setState(getDrawableState());
17654                }
17655            }
17656        }
17657    }
17658
17659    /**
17660     * Draw any foreground content for this view.
17661     *
17662     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17663     * drawable or other view-specific decorations. The foreground is drawn on top of the
17664     * primary view content.</p>
17665     *
17666     * @param canvas canvas to draw into
17667     */
17668    public void onDrawForeground(Canvas canvas) {
17669        onDrawScrollIndicators(canvas);
17670        onDrawScrollBars(canvas);
17671
17672        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17673        if (foreground != null) {
17674            if (mForegroundInfo.mBoundsChanged) {
17675                mForegroundInfo.mBoundsChanged = false;
17676                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17677                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17678
17679                if (mForegroundInfo.mInsidePadding) {
17680                    selfBounds.set(0, 0, getWidth(), getHeight());
17681                } else {
17682                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17683                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17684                }
17685
17686                final int ld = getLayoutDirection();
17687                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17688                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17689                foreground.setBounds(overlayBounds);
17690            }
17691
17692            foreground.draw(canvas);
17693        }
17694    }
17695
17696    /**
17697     * Sets the padding. The view may add on the space required to display
17698     * the scrollbars, depending on the style and visibility of the scrollbars.
17699     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17700     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17701     * from the values set in this call.
17702     *
17703     * @attr ref android.R.styleable#View_padding
17704     * @attr ref android.R.styleable#View_paddingBottom
17705     * @attr ref android.R.styleable#View_paddingLeft
17706     * @attr ref android.R.styleable#View_paddingRight
17707     * @attr ref android.R.styleable#View_paddingTop
17708     * @param left the left padding in pixels
17709     * @param top the top padding in pixels
17710     * @param right the right padding in pixels
17711     * @param bottom the bottom padding in pixels
17712     */
17713    public void setPadding(int left, int top, int right, int bottom) {
17714        resetResolvedPaddingInternal();
17715
17716        mUserPaddingStart = UNDEFINED_PADDING;
17717        mUserPaddingEnd = UNDEFINED_PADDING;
17718
17719        mUserPaddingLeftInitial = left;
17720        mUserPaddingRightInitial = right;
17721
17722        mLeftPaddingDefined = true;
17723        mRightPaddingDefined = true;
17724
17725        internalSetPadding(left, top, right, bottom);
17726    }
17727
17728    /**
17729     * @hide
17730     */
17731    protected void internalSetPadding(int left, int top, int right, int bottom) {
17732        mUserPaddingLeft = left;
17733        mUserPaddingRight = right;
17734        mUserPaddingBottom = bottom;
17735
17736        final int viewFlags = mViewFlags;
17737        boolean changed = false;
17738
17739        // Common case is there are no scroll bars.
17740        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17741            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17742                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17743                        ? 0 : getVerticalScrollbarWidth();
17744                switch (mVerticalScrollbarPosition) {
17745                    case SCROLLBAR_POSITION_DEFAULT:
17746                        if (isLayoutRtl()) {
17747                            left += offset;
17748                        } else {
17749                            right += offset;
17750                        }
17751                        break;
17752                    case SCROLLBAR_POSITION_RIGHT:
17753                        right += offset;
17754                        break;
17755                    case SCROLLBAR_POSITION_LEFT:
17756                        left += offset;
17757                        break;
17758                }
17759            }
17760            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17761                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17762                        ? 0 : getHorizontalScrollbarHeight();
17763            }
17764        }
17765
17766        if (mPaddingLeft != left) {
17767            changed = true;
17768            mPaddingLeft = left;
17769        }
17770        if (mPaddingTop != top) {
17771            changed = true;
17772            mPaddingTop = top;
17773        }
17774        if (mPaddingRight != right) {
17775            changed = true;
17776            mPaddingRight = right;
17777        }
17778        if (mPaddingBottom != bottom) {
17779            changed = true;
17780            mPaddingBottom = bottom;
17781        }
17782
17783        if (changed) {
17784            requestLayout();
17785            invalidateOutline();
17786        }
17787    }
17788
17789    /**
17790     * Sets the relative padding. The view may add on the space required to display
17791     * the scrollbars, depending on the style and visibility of the scrollbars.
17792     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17793     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17794     * from the values set in this call.
17795     *
17796     * @attr ref android.R.styleable#View_padding
17797     * @attr ref android.R.styleable#View_paddingBottom
17798     * @attr ref android.R.styleable#View_paddingStart
17799     * @attr ref android.R.styleable#View_paddingEnd
17800     * @attr ref android.R.styleable#View_paddingTop
17801     * @param start the start padding in pixels
17802     * @param top the top padding in pixels
17803     * @param end the end padding in pixels
17804     * @param bottom the bottom padding in pixels
17805     */
17806    public void setPaddingRelative(int start, int top, int end, int bottom) {
17807        resetResolvedPaddingInternal();
17808
17809        mUserPaddingStart = start;
17810        mUserPaddingEnd = end;
17811        mLeftPaddingDefined = true;
17812        mRightPaddingDefined = true;
17813
17814        switch(getLayoutDirection()) {
17815            case LAYOUT_DIRECTION_RTL:
17816                mUserPaddingLeftInitial = end;
17817                mUserPaddingRightInitial = start;
17818                internalSetPadding(end, top, start, bottom);
17819                break;
17820            case LAYOUT_DIRECTION_LTR:
17821            default:
17822                mUserPaddingLeftInitial = start;
17823                mUserPaddingRightInitial = end;
17824                internalSetPadding(start, top, end, bottom);
17825        }
17826    }
17827
17828    /**
17829     * Returns the top padding of this view.
17830     *
17831     * @return the top padding in pixels
17832     */
17833    public int getPaddingTop() {
17834        return mPaddingTop;
17835    }
17836
17837    /**
17838     * Returns the bottom padding of this view. If there are inset and enabled
17839     * scrollbars, this value may include the space required to display the
17840     * scrollbars as well.
17841     *
17842     * @return the bottom padding in pixels
17843     */
17844    public int getPaddingBottom() {
17845        return mPaddingBottom;
17846    }
17847
17848    /**
17849     * Returns the left padding of this view. If there are inset and enabled
17850     * scrollbars, this value may include the space required to display the
17851     * scrollbars as well.
17852     *
17853     * @return the left padding in pixels
17854     */
17855    public int getPaddingLeft() {
17856        if (!isPaddingResolved()) {
17857            resolvePadding();
17858        }
17859        return mPaddingLeft;
17860    }
17861
17862    /**
17863     * Returns the start padding of this view depending on its resolved layout direction.
17864     * If there are inset and enabled scrollbars, this value may include the space
17865     * required to display the scrollbars as well.
17866     *
17867     * @return the start padding in pixels
17868     */
17869    public int getPaddingStart() {
17870        if (!isPaddingResolved()) {
17871            resolvePadding();
17872        }
17873        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17874                mPaddingRight : mPaddingLeft;
17875    }
17876
17877    /**
17878     * Returns the right padding of this view. If there are inset and enabled
17879     * scrollbars, this value may include the space required to display the
17880     * scrollbars as well.
17881     *
17882     * @return the right padding in pixels
17883     */
17884    public int getPaddingRight() {
17885        if (!isPaddingResolved()) {
17886            resolvePadding();
17887        }
17888        return mPaddingRight;
17889    }
17890
17891    /**
17892     * Returns the end padding of this view depending on its resolved layout direction.
17893     * If there are inset and enabled scrollbars, this value may include the space
17894     * required to display the scrollbars as well.
17895     *
17896     * @return the end padding in pixels
17897     */
17898    public int getPaddingEnd() {
17899        if (!isPaddingResolved()) {
17900            resolvePadding();
17901        }
17902        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17903                mPaddingLeft : mPaddingRight;
17904    }
17905
17906    /**
17907     * Return if the padding has been set through relative values
17908     * {@link #setPaddingRelative(int, int, int, int)} or through
17909     * @attr ref android.R.styleable#View_paddingStart or
17910     * @attr ref android.R.styleable#View_paddingEnd
17911     *
17912     * @return true if the padding is relative or false if it is not.
17913     */
17914    public boolean isPaddingRelative() {
17915        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17916    }
17917
17918    Insets computeOpticalInsets() {
17919        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17920    }
17921
17922    /**
17923     * @hide
17924     */
17925    public void resetPaddingToInitialValues() {
17926        if (isRtlCompatibilityMode()) {
17927            mPaddingLeft = mUserPaddingLeftInitial;
17928            mPaddingRight = mUserPaddingRightInitial;
17929            return;
17930        }
17931        if (isLayoutRtl()) {
17932            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17933            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17934        } else {
17935            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17936            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17937        }
17938    }
17939
17940    /**
17941     * @hide
17942     */
17943    public Insets getOpticalInsets() {
17944        if (mLayoutInsets == null) {
17945            mLayoutInsets = computeOpticalInsets();
17946        }
17947        return mLayoutInsets;
17948    }
17949
17950    /**
17951     * Set this view's optical insets.
17952     *
17953     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17954     * property. Views that compute their own optical insets should call it as part of measurement.
17955     * This method does not request layout. If you are setting optical insets outside of
17956     * measure/layout itself you will want to call requestLayout() yourself.
17957     * </p>
17958     * @hide
17959     */
17960    public void setOpticalInsets(Insets insets) {
17961        mLayoutInsets = insets;
17962    }
17963
17964    /**
17965     * Changes the selection state of this view. A view can be selected or not.
17966     * Note that selection is not the same as focus. Views are typically
17967     * selected in the context of an AdapterView like ListView or GridView;
17968     * the selected view is the view that is highlighted.
17969     *
17970     * @param selected true if the view must be selected, false otherwise
17971     */
17972    public void setSelected(boolean selected) {
17973        //noinspection DoubleNegation
17974        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17975            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17976            if (!selected) resetPressedState();
17977            invalidate(true);
17978            refreshDrawableState();
17979            dispatchSetSelected(selected);
17980            if (selected) {
17981                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17982            } else {
17983                notifyViewAccessibilityStateChangedIfNeeded(
17984                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17985            }
17986        }
17987    }
17988
17989    /**
17990     * Dispatch setSelected to all of this View's children.
17991     *
17992     * @see #setSelected(boolean)
17993     *
17994     * @param selected The new selected state
17995     */
17996    protected void dispatchSetSelected(boolean selected) {
17997    }
17998
17999    /**
18000     * Indicates the selection state of this view.
18001     *
18002     * @return true if the view is selected, false otherwise
18003     */
18004    @ViewDebug.ExportedProperty
18005    public boolean isSelected() {
18006        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18007    }
18008
18009    /**
18010     * Changes the activated state of this view. A view can be activated or not.
18011     * Note that activation is not the same as selection.  Selection is
18012     * a transient property, representing the view (hierarchy) the user is
18013     * currently interacting with.  Activation is a longer-term state that the
18014     * user can move views in and out of.  For example, in a list view with
18015     * single or multiple selection enabled, the views in the current selection
18016     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18017     * here.)  The activated state is propagated down to children of the view it
18018     * is set on.
18019     *
18020     * @param activated true if the view must be activated, false otherwise
18021     */
18022    public void setActivated(boolean activated) {
18023        //noinspection DoubleNegation
18024        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18025            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18026            invalidate(true);
18027            refreshDrawableState();
18028            dispatchSetActivated(activated);
18029        }
18030    }
18031
18032    /**
18033     * Dispatch setActivated to all of this View's children.
18034     *
18035     * @see #setActivated(boolean)
18036     *
18037     * @param activated The new activated state
18038     */
18039    protected void dispatchSetActivated(boolean activated) {
18040    }
18041
18042    /**
18043     * Indicates the activation state of this view.
18044     *
18045     * @return true if the view is activated, false otherwise
18046     */
18047    @ViewDebug.ExportedProperty
18048    public boolean isActivated() {
18049        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18050    }
18051
18052    /**
18053     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18054     * observer can be used to get notifications when global events, like
18055     * layout, happen.
18056     *
18057     * The returned ViewTreeObserver observer is not guaranteed to remain
18058     * valid for the lifetime of this View. If the caller of this method keeps
18059     * a long-lived reference to ViewTreeObserver, it should always check for
18060     * the return value of {@link ViewTreeObserver#isAlive()}.
18061     *
18062     * @return The ViewTreeObserver for this view's hierarchy.
18063     */
18064    public ViewTreeObserver getViewTreeObserver() {
18065        if (mAttachInfo != null) {
18066            return mAttachInfo.mTreeObserver;
18067        }
18068        if (mFloatingTreeObserver == null) {
18069            mFloatingTreeObserver = new ViewTreeObserver();
18070        }
18071        return mFloatingTreeObserver;
18072    }
18073
18074    /**
18075     * <p>Finds the topmost view in the current view hierarchy.</p>
18076     *
18077     * @return the topmost view containing this view
18078     */
18079    public View getRootView() {
18080        if (mAttachInfo != null) {
18081            final View v = mAttachInfo.mRootView;
18082            if (v != null) {
18083                return v;
18084            }
18085        }
18086
18087        View parent = this;
18088
18089        while (parent.mParent != null && parent.mParent instanceof View) {
18090            parent = (View) parent.mParent;
18091        }
18092
18093        return parent;
18094    }
18095
18096    /**
18097     * Transforms a motion event from view-local coordinates to on-screen
18098     * coordinates.
18099     *
18100     * @param ev the view-local motion event
18101     * @return false if the transformation could not be applied
18102     * @hide
18103     */
18104    public boolean toGlobalMotionEvent(MotionEvent ev) {
18105        final AttachInfo info = mAttachInfo;
18106        if (info == null) {
18107            return false;
18108        }
18109
18110        final Matrix m = info.mTmpMatrix;
18111        m.set(Matrix.IDENTITY_MATRIX);
18112        transformMatrixToGlobal(m);
18113        ev.transform(m);
18114        return true;
18115    }
18116
18117    /**
18118     * Transforms a motion event from on-screen coordinates to view-local
18119     * coordinates.
18120     *
18121     * @param ev the on-screen motion event
18122     * @return false if the transformation could not be applied
18123     * @hide
18124     */
18125    public boolean toLocalMotionEvent(MotionEvent ev) {
18126        final AttachInfo info = mAttachInfo;
18127        if (info == null) {
18128            return false;
18129        }
18130
18131        final Matrix m = info.mTmpMatrix;
18132        m.set(Matrix.IDENTITY_MATRIX);
18133        transformMatrixToLocal(m);
18134        ev.transform(m);
18135        return true;
18136    }
18137
18138    /**
18139     * Modifies the input matrix such that it maps view-local coordinates to
18140     * on-screen coordinates.
18141     *
18142     * @param m input matrix to modify
18143     * @hide
18144     */
18145    public void transformMatrixToGlobal(Matrix m) {
18146        final ViewParent parent = mParent;
18147        if (parent instanceof View) {
18148            final View vp = (View) parent;
18149            vp.transformMatrixToGlobal(m);
18150            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18151        } else if (parent instanceof ViewRootImpl) {
18152            final ViewRootImpl vr = (ViewRootImpl) parent;
18153            vr.transformMatrixToGlobal(m);
18154            m.preTranslate(0, -vr.mCurScrollY);
18155        }
18156
18157        m.preTranslate(mLeft, mTop);
18158
18159        if (!hasIdentityMatrix()) {
18160            m.preConcat(getMatrix());
18161        }
18162    }
18163
18164    /**
18165     * Modifies the input matrix such that it maps on-screen coordinates to
18166     * view-local coordinates.
18167     *
18168     * @param m input matrix to modify
18169     * @hide
18170     */
18171    public void transformMatrixToLocal(Matrix m) {
18172        final ViewParent parent = mParent;
18173        if (parent instanceof View) {
18174            final View vp = (View) parent;
18175            vp.transformMatrixToLocal(m);
18176            m.postTranslate(vp.mScrollX, vp.mScrollY);
18177        } else if (parent instanceof ViewRootImpl) {
18178            final ViewRootImpl vr = (ViewRootImpl) parent;
18179            vr.transformMatrixToLocal(m);
18180            m.postTranslate(0, vr.mCurScrollY);
18181        }
18182
18183        m.postTranslate(-mLeft, -mTop);
18184
18185        if (!hasIdentityMatrix()) {
18186            m.postConcat(getInverseMatrix());
18187        }
18188    }
18189
18190    /**
18191     * @hide
18192     */
18193    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18194            @ViewDebug.IntToString(from = 0, to = "x"),
18195            @ViewDebug.IntToString(from = 1, to = "y")
18196    })
18197    public int[] getLocationOnScreen() {
18198        int[] location = new int[2];
18199        getLocationOnScreen(location);
18200        return location;
18201    }
18202
18203    /**
18204     * <p>Computes the coordinates of this view on the screen. The argument
18205     * must be an array of two integers. After the method returns, the array
18206     * contains the x and y location in that order.</p>
18207     *
18208     * @param location an array of two integers in which to hold the coordinates
18209     */
18210    public void getLocationOnScreen(@Size(2) int[] location) {
18211        getLocationInWindow(location);
18212
18213        final AttachInfo info = mAttachInfo;
18214        if (info != null) {
18215            location[0] += info.mWindowLeft;
18216            location[1] += info.mWindowTop;
18217        }
18218    }
18219
18220    /**
18221     * <p>Computes the coordinates of this view in its window. The argument
18222     * must be an array of two integers. After the method returns, the array
18223     * contains the x and y location in that order.</p>
18224     *
18225     * @param location an array of two integers in which to hold the coordinates
18226     */
18227    public void getLocationInWindow(@Size(2) int[] location) {
18228        if (location == null || location.length < 2) {
18229            throw new IllegalArgumentException("location must be an array of two integers");
18230        }
18231
18232        if (mAttachInfo == null) {
18233            // When the view is not attached to a window, this method does not make sense
18234            location[0] = location[1] = 0;
18235            return;
18236        }
18237
18238        float[] position = mAttachInfo.mTmpTransformLocation;
18239        position[0] = position[1] = 0.0f;
18240
18241        if (!hasIdentityMatrix()) {
18242            getMatrix().mapPoints(position);
18243        }
18244
18245        position[0] += mLeft;
18246        position[1] += mTop;
18247
18248        ViewParent viewParent = mParent;
18249        while (viewParent instanceof View) {
18250            final View view = (View) viewParent;
18251
18252            position[0] -= view.mScrollX;
18253            position[1] -= view.mScrollY;
18254
18255            if (!view.hasIdentityMatrix()) {
18256                view.getMatrix().mapPoints(position);
18257            }
18258
18259            position[0] += view.mLeft;
18260            position[1] += view.mTop;
18261
18262            viewParent = view.mParent;
18263         }
18264
18265        if (viewParent instanceof ViewRootImpl) {
18266            // *cough*
18267            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18268            position[1] -= vr.mCurScrollY;
18269        }
18270
18271        location[0] = (int) (position[0] + 0.5f);
18272        location[1] = (int) (position[1] + 0.5f);
18273    }
18274
18275    /**
18276     * {@hide}
18277     * @param id the id of the view to be found
18278     * @return the view of the specified id, null if cannot be found
18279     */
18280    protected View findViewTraversal(@IdRes int id) {
18281        if (id == mID) {
18282            return this;
18283        }
18284        return null;
18285    }
18286
18287    /**
18288     * {@hide}
18289     * @param tag the tag of the view to be found
18290     * @return the view of specified tag, null if cannot be found
18291     */
18292    protected View findViewWithTagTraversal(Object tag) {
18293        if (tag != null && tag.equals(mTag)) {
18294            return this;
18295        }
18296        return null;
18297    }
18298
18299    /**
18300     * {@hide}
18301     * @param predicate The predicate to evaluate.
18302     * @param childToSkip If not null, ignores this child during the recursive traversal.
18303     * @return The first view that matches the predicate or null.
18304     */
18305    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18306        if (predicate.apply(this)) {
18307            return this;
18308        }
18309        return null;
18310    }
18311
18312    /**
18313     * Look for a child view with the given id.  If this view has the given
18314     * id, return this view.
18315     *
18316     * @param id The id to search for.
18317     * @return The view that has the given id in the hierarchy or null
18318     */
18319    @Nullable
18320    public final View findViewById(@IdRes int id) {
18321        if (id < 0) {
18322            return null;
18323        }
18324        return findViewTraversal(id);
18325    }
18326
18327    /**
18328     * Finds a view by its unuque and stable accessibility id.
18329     *
18330     * @param accessibilityId The searched accessibility id.
18331     * @return The found view.
18332     */
18333    final View findViewByAccessibilityId(int accessibilityId) {
18334        if (accessibilityId < 0) {
18335            return null;
18336        }
18337        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18338        if (view != null) {
18339            return view.includeForAccessibility() ? view : null;
18340        }
18341        return null;
18342    }
18343
18344    /**
18345     * Performs the traversal to find a view by its unuque and stable accessibility id.
18346     *
18347     * <strong>Note:</strong>This method does not stop at the root namespace
18348     * boundary since the user can touch the screen at an arbitrary location
18349     * potentially crossing the root namespace bounday which will send an
18350     * accessibility event to accessibility services and they should be able
18351     * to obtain the event source. Also accessibility ids are guaranteed to be
18352     * unique in the window.
18353     *
18354     * @param accessibilityId The accessibility id.
18355     * @return The found view.
18356     *
18357     * @hide
18358     */
18359    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18360        if (getAccessibilityViewId() == accessibilityId) {
18361            return this;
18362        }
18363        return null;
18364    }
18365
18366    /**
18367     * Look for a child view with the given tag.  If this view has the given
18368     * tag, return this view.
18369     *
18370     * @param tag The tag to search for, using "tag.equals(getTag())".
18371     * @return The View that has the given tag in the hierarchy or null
18372     */
18373    public final View findViewWithTag(Object tag) {
18374        if (tag == null) {
18375            return null;
18376        }
18377        return findViewWithTagTraversal(tag);
18378    }
18379
18380    /**
18381     * {@hide}
18382     * Look for a child view that matches the specified predicate.
18383     * If this view matches the predicate, return this view.
18384     *
18385     * @param predicate The predicate to evaluate.
18386     * @return The first view that matches the predicate or null.
18387     */
18388    public final View findViewByPredicate(Predicate<View> predicate) {
18389        return findViewByPredicateTraversal(predicate, null);
18390    }
18391
18392    /**
18393     * {@hide}
18394     * Look for a child view that matches the specified predicate,
18395     * starting with the specified view and its descendents and then
18396     * recusively searching the ancestors and siblings of that view
18397     * until this view is reached.
18398     *
18399     * This method is useful in cases where the predicate does not match
18400     * a single unique view (perhaps multiple views use the same id)
18401     * and we are trying to find the view that is "closest" in scope to the
18402     * starting view.
18403     *
18404     * @param start The view to start from.
18405     * @param predicate The predicate to evaluate.
18406     * @return The first view that matches the predicate or null.
18407     */
18408    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18409        View childToSkip = null;
18410        for (;;) {
18411            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18412            if (view != null || start == this) {
18413                return view;
18414            }
18415
18416            ViewParent parent = start.getParent();
18417            if (parent == null || !(parent instanceof View)) {
18418                return null;
18419            }
18420
18421            childToSkip = start;
18422            start = (View) parent;
18423        }
18424    }
18425
18426    /**
18427     * Sets the identifier for this view. The identifier does not have to be
18428     * unique in this view's hierarchy. The identifier should be a positive
18429     * number.
18430     *
18431     * @see #NO_ID
18432     * @see #getId()
18433     * @see #findViewById(int)
18434     *
18435     * @param id a number used to identify the view
18436     *
18437     * @attr ref android.R.styleable#View_id
18438     */
18439    public void setId(@IdRes int id) {
18440        mID = id;
18441        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18442            mID = generateViewId();
18443        }
18444    }
18445
18446    /**
18447     * {@hide}
18448     *
18449     * @param isRoot true if the view belongs to the root namespace, false
18450     *        otherwise
18451     */
18452    public void setIsRootNamespace(boolean isRoot) {
18453        if (isRoot) {
18454            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18455        } else {
18456            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18457        }
18458    }
18459
18460    /**
18461     * {@hide}
18462     *
18463     * @return true if the view belongs to the root namespace, false otherwise
18464     */
18465    public boolean isRootNamespace() {
18466        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18467    }
18468
18469    /**
18470     * Returns this view's identifier.
18471     *
18472     * @return a positive integer used to identify the view or {@link #NO_ID}
18473     *         if the view has no ID
18474     *
18475     * @see #setId(int)
18476     * @see #findViewById(int)
18477     * @attr ref android.R.styleable#View_id
18478     */
18479    @IdRes
18480    @ViewDebug.CapturedViewProperty
18481    public int getId() {
18482        return mID;
18483    }
18484
18485    /**
18486     * Returns this view's tag.
18487     *
18488     * @return the Object stored in this view as a tag, or {@code null} if not
18489     *         set
18490     *
18491     * @see #setTag(Object)
18492     * @see #getTag(int)
18493     */
18494    @ViewDebug.ExportedProperty
18495    public Object getTag() {
18496        return mTag;
18497    }
18498
18499    /**
18500     * Sets the tag associated with this view. A tag can be used to mark
18501     * a view in its hierarchy and does not have to be unique within the
18502     * hierarchy. Tags can also be used to store data within a view without
18503     * resorting to another data structure.
18504     *
18505     * @param tag an Object to tag the view with
18506     *
18507     * @see #getTag()
18508     * @see #setTag(int, Object)
18509     */
18510    public void setTag(final Object tag) {
18511        mTag = tag;
18512    }
18513
18514    /**
18515     * Returns the tag associated with this view and the specified key.
18516     *
18517     * @param key The key identifying the tag
18518     *
18519     * @return the Object stored in this view as a tag, or {@code null} if not
18520     *         set
18521     *
18522     * @see #setTag(int, Object)
18523     * @see #getTag()
18524     */
18525    public Object getTag(int key) {
18526        if (mKeyedTags != null) return mKeyedTags.get(key);
18527        return null;
18528    }
18529
18530    /**
18531     * Sets a tag associated with this view and a key. A tag can be used
18532     * to mark a view in its hierarchy and does not have to be unique within
18533     * the hierarchy. Tags can also be used to store data within a view
18534     * without resorting to another data structure.
18535     *
18536     * The specified key should be an id declared in the resources of the
18537     * application to ensure it is unique (see the <a
18538     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18539     * Keys identified as belonging to
18540     * the Android framework or not associated with any package will cause
18541     * an {@link IllegalArgumentException} to be thrown.
18542     *
18543     * @param key The key identifying the tag
18544     * @param tag An Object to tag the view with
18545     *
18546     * @throws IllegalArgumentException If they specified key is not valid
18547     *
18548     * @see #setTag(Object)
18549     * @see #getTag(int)
18550     */
18551    public void setTag(int key, final Object tag) {
18552        // If the package id is 0x00 or 0x01, it's either an undefined package
18553        // or a framework id
18554        if ((key >>> 24) < 2) {
18555            throw new IllegalArgumentException("The key must be an application-specific "
18556                    + "resource id.");
18557        }
18558
18559        setKeyedTag(key, tag);
18560    }
18561
18562    /**
18563     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18564     * framework id.
18565     *
18566     * @hide
18567     */
18568    public void setTagInternal(int key, Object tag) {
18569        if ((key >>> 24) != 0x1) {
18570            throw new IllegalArgumentException("The key must be a framework-specific "
18571                    + "resource id.");
18572        }
18573
18574        setKeyedTag(key, tag);
18575    }
18576
18577    private void setKeyedTag(int key, Object tag) {
18578        if (mKeyedTags == null) {
18579            mKeyedTags = new SparseArray<Object>(2);
18580        }
18581
18582        mKeyedTags.put(key, tag);
18583    }
18584
18585    /**
18586     * Prints information about this view in the log output, with the tag
18587     * {@link #VIEW_LOG_TAG}.
18588     *
18589     * @hide
18590     */
18591    public void debug() {
18592        debug(0);
18593    }
18594
18595    /**
18596     * Prints information about this view in the log output, with the tag
18597     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18598     * indentation defined by the <code>depth</code>.
18599     *
18600     * @param depth the indentation level
18601     *
18602     * @hide
18603     */
18604    protected void debug(int depth) {
18605        String output = debugIndent(depth - 1);
18606
18607        output += "+ " + this;
18608        int id = getId();
18609        if (id != -1) {
18610            output += " (id=" + id + ")";
18611        }
18612        Object tag = getTag();
18613        if (tag != null) {
18614            output += " (tag=" + tag + ")";
18615        }
18616        Log.d(VIEW_LOG_TAG, output);
18617
18618        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18619            output = debugIndent(depth) + " FOCUSED";
18620            Log.d(VIEW_LOG_TAG, output);
18621        }
18622
18623        output = debugIndent(depth);
18624        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18625                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18626                + "} ";
18627        Log.d(VIEW_LOG_TAG, output);
18628
18629        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18630                || mPaddingBottom != 0) {
18631            output = debugIndent(depth);
18632            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18633                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18634            Log.d(VIEW_LOG_TAG, output);
18635        }
18636
18637        output = debugIndent(depth);
18638        output += "mMeasureWidth=" + mMeasuredWidth +
18639                " mMeasureHeight=" + mMeasuredHeight;
18640        Log.d(VIEW_LOG_TAG, output);
18641
18642        output = debugIndent(depth);
18643        if (mLayoutParams == null) {
18644            output += "BAD! no layout params";
18645        } else {
18646            output = mLayoutParams.debug(output);
18647        }
18648        Log.d(VIEW_LOG_TAG, output);
18649
18650        output = debugIndent(depth);
18651        output += "flags={";
18652        output += View.printFlags(mViewFlags);
18653        output += "}";
18654        Log.d(VIEW_LOG_TAG, output);
18655
18656        output = debugIndent(depth);
18657        output += "privateFlags={";
18658        output += View.printPrivateFlags(mPrivateFlags);
18659        output += "}";
18660        Log.d(VIEW_LOG_TAG, output);
18661    }
18662
18663    /**
18664     * Creates a string of whitespaces used for indentation.
18665     *
18666     * @param depth the indentation level
18667     * @return a String containing (depth * 2 + 3) * 2 white spaces
18668     *
18669     * @hide
18670     */
18671    protected static String debugIndent(int depth) {
18672        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18673        for (int i = 0; i < (depth * 2) + 3; i++) {
18674            spaces.append(' ').append(' ');
18675        }
18676        return spaces.toString();
18677    }
18678
18679    /**
18680     * <p>Return the offset of the widget's text baseline from the widget's top
18681     * boundary. If this widget does not support baseline alignment, this
18682     * method returns -1. </p>
18683     *
18684     * @return the offset of the baseline within the widget's bounds or -1
18685     *         if baseline alignment is not supported
18686     */
18687    @ViewDebug.ExportedProperty(category = "layout")
18688    public int getBaseline() {
18689        return -1;
18690    }
18691
18692    /**
18693     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18694     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18695     * a layout pass.
18696     *
18697     * @return whether the view hierarchy is currently undergoing a layout pass
18698     */
18699    public boolean isInLayout() {
18700        ViewRootImpl viewRoot = getViewRootImpl();
18701        return (viewRoot != null && viewRoot.isInLayout());
18702    }
18703
18704    /**
18705     * Call this when something has changed which has invalidated the
18706     * layout of this view. This will schedule a layout pass of the view
18707     * tree. This should not be called while the view hierarchy is currently in a layout
18708     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18709     * end of the current layout pass (and then layout will run again) or after the current
18710     * frame is drawn and the next layout occurs.
18711     *
18712     * <p>Subclasses which override this method should call the superclass method to
18713     * handle possible request-during-layout errors correctly.</p>
18714     */
18715    @CallSuper
18716    public void requestLayout() {
18717        if (mMeasureCache != null) mMeasureCache.clear();
18718
18719        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18720            // Only trigger request-during-layout logic if this is the view requesting it,
18721            // not the views in its parent hierarchy
18722            ViewRootImpl viewRoot = getViewRootImpl();
18723            if (viewRoot != null && viewRoot.isInLayout()) {
18724                if (!viewRoot.requestLayoutDuringLayout(this)) {
18725                    return;
18726                }
18727            }
18728            mAttachInfo.mViewRequestingLayout = this;
18729        }
18730
18731        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18732        mPrivateFlags |= PFLAG_INVALIDATED;
18733
18734        if (mParent != null && !mParent.isLayoutRequested()) {
18735            mParent.requestLayout();
18736        }
18737        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18738            mAttachInfo.mViewRequestingLayout = null;
18739        }
18740    }
18741
18742    /**
18743     * Forces this view to be laid out during the next layout pass.
18744     * This method does not call requestLayout() or forceLayout()
18745     * on the parent.
18746     */
18747    public void forceLayout() {
18748        if (mMeasureCache != null) mMeasureCache.clear();
18749
18750        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18751        mPrivateFlags |= PFLAG_INVALIDATED;
18752    }
18753
18754    /**
18755     * <p>
18756     * This is called to find out how big a view should be. The parent
18757     * supplies constraint information in the width and height parameters.
18758     * </p>
18759     *
18760     * <p>
18761     * The actual measurement work of a view is performed in
18762     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18763     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18764     * </p>
18765     *
18766     *
18767     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18768     *        parent
18769     * @param heightMeasureSpec Vertical space requirements as imposed by the
18770     *        parent
18771     *
18772     * @see #onMeasure(int, int)
18773     */
18774    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18775        boolean optical = isLayoutModeOptical(this);
18776        if (optical != isLayoutModeOptical(mParent)) {
18777            Insets insets = getOpticalInsets();
18778            int oWidth  = insets.left + insets.right;
18779            int oHeight = insets.top  + insets.bottom;
18780            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18781            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18782        }
18783
18784        // Suppress sign extension for the low bytes
18785        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18786        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18787
18788        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
18789                widthMeasureSpec != mOldWidthMeasureSpec ||
18790                heightMeasureSpec != mOldHeightMeasureSpec) {
18791
18792            // first clears the measured dimension flag
18793            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18794
18795            resolveRtlPropertiesIfNeeded();
18796
18797            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
18798                    mMeasureCache.indexOfKey(key);
18799            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18800                // measure ourselves, this should set the measured dimension flag back
18801                onMeasure(widthMeasureSpec, heightMeasureSpec);
18802                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18803            } else {
18804                long value = mMeasureCache.valueAt(cacheIndex);
18805                // Casting a long to int drops the high 32 bits, no mask needed
18806                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18807                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18808            }
18809
18810            // flag not set, setMeasuredDimension() was not invoked, we raise
18811            // an exception to warn the developer
18812            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18813                throw new IllegalStateException("View with id " + getId() + ": "
18814                        + getClass().getName() + "#onMeasure() did not set the"
18815                        + " measured dimension by calling"
18816                        + " setMeasuredDimension()");
18817            }
18818
18819            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18820        }
18821
18822        mOldWidthMeasureSpec = widthMeasureSpec;
18823        mOldHeightMeasureSpec = heightMeasureSpec;
18824
18825        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18826                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18827    }
18828
18829    /**
18830     * <p>
18831     * Measure the view and its content to determine the measured width and the
18832     * measured height. This method is invoked by {@link #measure(int, int)} and
18833     * should be overridden by subclasses to provide accurate and efficient
18834     * measurement of their contents.
18835     * </p>
18836     *
18837     * <p>
18838     * <strong>CONTRACT:</strong> When overriding this method, you
18839     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18840     * measured width and height of this view. Failure to do so will trigger an
18841     * <code>IllegalStateException</code>, thrown by
18842     * {@link #measure(int, int)}. Calling the superclass'
18843     * {@link #onMeasure(int, int)} is a valid use.
18844     * </p>
18845     *
18846     * <p>
18847     * The base class implementation of measure defaults to the background size,
18848     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18849     * override {@link #onMeasure(int, int)} to provide better measurements of
18850     * their content.
18851     * </p>
18852     *
18853     * <p>
18854     * If this method is overridden, it is the subclass's responsibility to make
18855     * sure the measured height and width are at least the view's minimum height
18856     * and width ({@link #getSuggestedMinimumHeight()} and
18857     * {@link #getSuggestedMinimumWidth()}).
18858     * </p>
18859     *
18860     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18861     *                         The requirements are encoded with
18862     *                         {@link android.view.View.MeasureSpec}.
18863     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18864     *                         The requirements are encoded with
18865     *                         {@link android.view.View.MeasureSpec}.
18866     *
18867     * @see #getMeasuredWidth()
18868     * @see #getMeasuredHeight()
18869     * @see #setMeasuredDimension(int, int)
18870     * @see #getSuggestedMinimumHeight()
18871     * @see #getSuggestedMinimumWidth()
18872     * @see android.view.View.MeasureSpec#getMode(int)
18873     * @see android.view.View.MeasureSpec#getSize(int)
18874     */
18875    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18876        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18877                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18878    }
18879
18880    /**
18881     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18882     * measured width and measured height. Failing to do so will trigger an
18883     * exception at measurement time.</p>
18884     *
18885     * @param measuredWidth The measured width of this view.  May be a complex
18886     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18887     * {@link #MEASURED_STATE_TOO_SMALL}.
18888     * @param measuredHeight The measured height of this view.  May be a complex
18889     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18890     * {@link #MEASURED_STATE_TOO_SMALL}.
18891     */
18892    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18893        boolean optical = isLayoutModeOptical(this);
18894        if (optical != isLayoutModeOptical(mParent)) {
18895            Insets insets = getOpticalInsets();
18896            int opticalWidth  = insets.left + insets.right;
18897            int opticalHeight = insets.top  + insets.bottom;
18898
18899            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18900            measuredHeight += optical ? opticalHeight : -opticalHeight;
18901        }
18902        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18903    }
18904
18905    /**
18906     * Sets the measured dimension without extra processing for things like optical bounds.
18907     * Useful for reapplying consistent values that have already been cooked with adjustments
18908     * for optical bounds, etc. such as those from the measurement cache.
18909     *
18910     * @param measuredWidth The measured width of this view.  May be a complex
18911     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18912     * {@link #MEASURED_STATE_TOO_SMALL}.
18913     * @param measuredHeight The measured height of this view.  May be a complex
18914     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18915     * {@link #MEASURED_STATE_TOO_SMALL}.
18916     */
18917    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18918        mMeasuredWidth = measuredWidth;
18919        mMeasuredHeight = measuredHeight;
18920
18921        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18922    }
18923
18924    /**
18925     * Merge two states as returned by {@link #getMeasuredState()}.
18926     * @param curState The current state as returned from a view or the result
18927     * of combining multiple views.
18928     * @param newState The new view state to combine.
18929     * @return Returns a new integer reflecting the combination of the two
18930     * states.
18931     */
18932    public static int combineMeasuredStates(int curState, int newState) {
18933        return curState | newState;
18934    }
18935
18936    /**
18937     * Version of {@link #resolveSizeAndState(int, int, int)}
18938     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18939     */
18940    public static int resolveSize(int size, int measureSpec) {
18941        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18942    }
18943
18944    /**
18945     * Utility to reconcile a desired size and state, with constraints imposed
18946     * by a MeasureSpec. Will take the desired size, unless a different size
18947     * is imposed by the constraints. The returned value is a compound integer,
18948     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18949     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18950     * resulting size is smaller than the size the view wants to be.
18951     *
18952     * @param size How big the view wants to be.
18953     * @param measureSpec Constraints imposed by the parent.
18954     * @param childMeasuredState Size information bit mask for the view's
18955     *                           children.
18956     * @return Size information bit mask as defined by
18957     *         {@link #MEASURED_SIZE_MASK} and
18958     *         {@link #MEASURED_STATE_TOO_SMALL}.
18959     */
18960    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18961        final int specMode = MeasureSpec.getMode(measureSpec);
18962        final int specSize = MeasureSpec.getSize(measureSpec);
18963        final int result;
18964        switch (specMode) {
18965            case MeasureSpec.AT_MOST:
18966                if (specSize < size) {
18967                    result = specSize | MEASURED_STATE_TOO_SMALL;
18968                } else {
18969                    result = size;
18970                }
18971                break;
18972            case MeasureSpec.EXACTLY:
18973                result = specSize;
18974                break;
18975            case MeasureSpec.UNSPECIFIED:
18976            default:
18977                result = size;
18978        }
18979        return result | (childMeasuredState & MEASURED_STATE_MASK);
18980    }
18981
18982    /**
18983     * Utility to return a default size. Uses the supplied size if the
18984     * MeasureSpec imposed no constraints. Will get larger if allowed
18985     * by the MeasureSpec.
18986     *
18987     * @param size Default size for this view
18988     * @param measureSpec Constraints imposed by the parent
18989     * @return The size this view should be.
18990     */
18991    public static int getDefaultSize(int size, int measureSpec) {
18992        int result = size;
18993        int specMode = MeasureSpec.getMode(measureSpec);
18994        int specSize = MeasureSpec.getSize(measureSpec);
18995
18996        switch (specMode) {
18997        case MeasureSpec.UNSPECIFIED:
18998            result = size;
18999            break;
19000        case MeasureSpec.AT_MOST:
19001        case MeasureSpec.EXACTLY:
19002            result = specSize;
19003            break;
19004        }
19005        return result;
19006    }
19007
19008    /**
19009     * Returns the suggested minimum height that the view should use. This
19010     * returns the maximum of the view's minimum height
19011     * and the background's minimum height
19012     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19013     * <p>
19014     * When being used in {@link #onMeasure(int, int)}, the caller should still
19015     * ensure the returned height is within the requirements of the parent.
19016     *
19017     * @return The suggested minimum height of the view.
19018     */
19019    protected int getSuggestedMinimumHeight() {
19020        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19021
19022    }
19023
19024    /**
19025     * Returns the suggested minimum width that the view should use. This
19026     * returns the maximum of the view's minimum width
19027     * and the background's minimum width
19028     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19029     * <p>
19030     * When being used in {@link #onMeasure(int, int)}, the caller should still
19031     * ensure the returned width is within the requirements of the parent.
19032     *
19033     * @return The suggested minimum width of the view.
19034     */
19035    protected int getSuggestedMinimumWidth() {
19036        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19037    }
19038
19039    /**
19040     * Returns the minimum height of the view.
19041     *
19042     * @return the minimum height the view will try to be.
19043     *
19044     * @see #setMinimumHeight(int)
19045     *
19046     * @attr ref android.R.styleable#View_minHeight
19047     */
19048    public int getMinimumHeight() {
19049        return mMinHeight;
19050    }
19051
19052    /**
19053     * Sets the minimum height of the view. It is not guaranteed the view will
19054     * be able to achieve this minimum height (for example, if its parent layout
19055     * constrains it with less available height).
19056     *
19057     * @param minHeight The minimum height the view will try to be.
19058     *
19059     * @see #getMinimumHeight()
19060     *
19061     * @attr ref android.R.styleable#View_minHeight
19062     */
19063    public void setMinimumHeight(int minHeight) {
19064        mMinHeight = minHeight;
19065        requestLayout();
19066    }
19067
19068    /**
19069     * Returns the minimum width of the view.
19070     *
19071     * @return the minimum width the view will try to be.
19072     *
19073     * @see #setMinimumWidth(int)
19074     *
19075     * @attr ref android.R.styleable#View_minWidth
19076     */
19077    public int getMinimumWidth() {
19078        return mMinWidth;
19079    }
19080
19081    /**
19082     * Sets the minimum width of the view. It is not guaranteed the view will
19083     * be able to achieve this minimum width (for example, if its parent layout
19084     * constrains it with less available width).
19085     *
19086     * @param minWidth The minimum width the view will try to be.
19087     *
19088     * @see #getMinimumWidth()
19089     *
19090     * @attr ref android.R.styleable#View_minWidth
19091     */
19092    public void setMinimumWidth(int minWidth) {
19093        mMinWidth = minWidth;
19094        requestLayout();
19095
19096    }
19097
19098    /**
19099     * Get the animation currently associated with this view.
19100     *
19101     * @return The animation that is currently playing or
19102     *         scheduled to play for this view.
19103     */
19104    public Animation getAnimation() {
19105        return mCurrentAnimation;
19106    }
19107
19108    /**
19109     * Start the specified animation now.
19110     *
19111     * @param animation the animation to start now
19112     */
19113    public void startAnimation(Animation animation) {
19114        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19115        setAnimation(animation);
19116        invalidateParentCaches();
19117        invalidate(true);
19118    }
19119
19120    /**
19121     * Cancels any animations for this view.
19122     */
19123    public void clearAnimation() {
19124        if (mCurrentAnimation != null) {
19125            mCurrentAnimation.detach();
19126        }
19127        mCurrentAnimation = null;
19128        invalidateParentIfNeeded();
19129    }
19130
19131    /**
19132     * Sets the next animation to play for this view.
19133     * If you want the animation to play immediately, use
19134     * {@link #startAnimation(android.view.animation.Animation)} instead.
19135     * This method provides allows fine-grained
19136     * control over the start time and invalidation, but you
19137     * must make sure that 1) the animation has a start time set, and
19138     * 2) the view's parent (which controls animations on its children)
19139     * will be invalidated when the animation is supposed to
19140     * start.
19141     *
19142     * @param animation The next animation, or null.
19143     */
19144    public void setAnimation(Animation animation) {
19145        mCurrentAnimation = animation;
19146
19147        if (animation != null) {
19148            // If the screen is off assume the animation start time is now instead of
19149            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19150            // would cause the animation to start when the screen turns back on
19151            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19152                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19153                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19154            }
19155            animation.reset();
19156        }
19157    }
19158
19159    /**
19160     * Invoked by a parent ViewGroup to notify the start of the animation
19161     * currently associated with this view. If you override this method,
19162     * always call super.onAnimationStart();
19163     *
19164     * @see #setAnimation(android.view.animation.Animation)
19165     * @see #getAnimation()
19166     */
19167    @CallSuper
19168    protected void onAnimationStart() {
19169        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19170    }
19171
19172    /**
19173     * Invoked by a parent ViewGroup to notify the end of the animation
19174     * currently associated with this view. If you override this method,
19175     * always call super.onAnimationEnd();
19176     *
19177     * @see #setAnimation(android.view.animation.Animation)
19178     * @see #getAnimation()
19179     */
19180    @CallSuper
19181    protected void onAnimationEnd() {
19182        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19183    }
19184
19185    /**
19186     * Invoked if there is a Transform that involves alpha. Subclass that can
19187     * draw themselves with the specified alpha should return true, and then
19188     * respect that alpha when their onDraw() is called. If this returns false
19189     * then the view may be redirected to draw into an offscreen buffer to
19190     * fulfill the request, which will look fine, but may be slower than if the
19191     * subclass handles it internally. The default implementation returns false.
19192     *
19193     * @param alpha The alpha (0..255) to apply to the view's drawing
19194     * @return true if the view can draw with the specified alpha.
19195     */
19196    protected boolean onSetAlpha(int alpha) {
19197        return false;
19198    }
19199
19200    /**
19201     * This is used by the RootView to perform an optimization when
19202     * the view hierarchy contains one or several SurfaceView.
19203     * SurfaceView is always considered transparent, but its children are not,
19204     * therefore all View objects remove themselves from the global transparent
19205     * region (passed as a parameter to this function).
19206     *
19207     * @param region The transparent region for this ViewAncestor (window).
19208     *
19209     * @return Returns true if the effective visibility of the view at this
19210     * point is opaque, regardless of the transparent region; returns false
19211     * if it is possible for underlying windows to be seen behind the view.
19212     *
19213     * {@hide}
19214     */
19215    public boolean gatherTransparentRegion(Region region) {
19216        final AttachInfo attachInfo = mAttachInfo;
19217        if (region != null && attachInfo != null) {
19218            final int pflags = mPrivateFlags;
19219            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19220                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19221                // remove it from the transparent region.
19222                final int[] location = attachInfo.mTransparentLocation;
19223                getLocationInWindow(location);
19224                region.op(location[0], location[1], location[0] + mRight - mLeft,
19225                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19226            } else {
19227                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19228                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19229                    // the background drawable's non-transparent parts from this transparent region.
19230                    applyDrawableToTransparentRegion(mBackground, region);
19231                }
19232                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19233                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19234                    // Similarly, we remove the foreground drawable's non-transparent parts.
19235                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19236                }
19237            }
19238        }
19239        return true;
19240    }
19241
19242    /**
19243     * Play a sound effect for this view.
19244     *
19245     * <p>The framework will play sound effects for some built in actions, such as
19246     * clicking, but you may wish to play these effects in your widget,
19247     * for instance, for internal navigation.
19248     *
19249     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19250     * {@link #isSoundEffectsEnabled()} is true.
19251     *
19252     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19253     */
19254    public void playSoundEffect(int soundConstant) {
19255        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19256            return;
19257        }
19258        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19259    }
19260
19261    /**
19262     * BZZZTT!!1!
19263     *
19264     * <p>Provide haptic feedback to the user for this view.
19265     *
19266     * <p>The framework will provide haptic feedback for some built in actions,
19267     * such as long presses, but you may wish to provide feedback for your
19268     * own widget.
19269     *
19270     * <p>The feedback will only be performed if
19271     * {@link #isHapticFeedbackEnabled()} is true.
19272     *
19273     * @param feedbackConstant One of the constants defined in
19274     * {@link HapticFeedbackConstants}
19275     */
19276    public boolean performHapticFeedback(int feedbackConstant) {
19277        return performHapticFeedback(feedbackConstant, 0);
19278    }
19279
19280    /**
19281     * BZZZTT!!1!
19282     *
19283     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19284     *
19285     * @param feedbackConstant One of the constants defined in
19286     * {@link HapticFeedbackConstants}
19287     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19288     */
19289    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19290        if (mAttachInfo == null) {
19291            return false;
19292        }
19293        //noinspection SimplifiableIfStatement
19294        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19295                && !isHapticFeedbackEnabled()) {
19296            return false;
19297        }
19298        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19299                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19300    }
19301
19302    /**
19303     * Request that the visibility of the status bar or other screen/window
19304     * decorations be changed.
19305     *
19306     * <p>This method is used to put the over device UI into temporary modes
19307     * where the user's attention is focused more on the application content,
19308     * by dimming or hiding surrounding system affordances.  This is typically
19309     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19310     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19311     * to be placed behind the action bar (and with these flags other system
19312     * affordances) so that smooth transitions between hiding and showing them
19313     * can be done.
19314     *
19315     * <p>Two representative examples of the use of system UI visibility is
19316     * implementing a content browsing application (like a magazine reader)
19317     * and a video playing application.
19318     *
19319     * <p>The first code shows a typical implementation of a View in a content
19320     * browsing application.  In this implementation, the application goes
19321     * into a content-oriented mode by hiding the status bar and action bar,
19322     * and putting the navigation elements into lights out mode.  The user can
19323     * then interact with content while in this mode.  Such an application should
19324     * provide an easy way for the user to toggle out of the mode (such as to
19325     * check information in the status bar or access notifications).  In the
19326     * implementation here, this is done simply by tapping on the content.
19327     *
19328     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19329     *      content}
19330     *
19331     * <p>This second code sample shows a typical implementation of a View
19332     * in a video playing application.  In this situation, while the video is
19333     * playing the application would like to go into a complete full-screen mode,
19334     * to use as much of the display as possible for the video.  When in this state
19335     * the user can not interact with the application; the system intercepts
19336     * touching on the screen to pop the UI out of full screen mode.  See
19337     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19338     *
19339     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19340     *      content}
19341     *
19342     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19343     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19344     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19345     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19346     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19347     */
19348    public void setSystemUiVisibility(int visibility) {
19349        if (visibility != mSystemUiVisibility) {
19350            mSystemUiVisibility = visibility;
19351            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19352                mParent.recomputeViewAttributes(this);
19353            }
19354        }
19355    }
19356
19357    /**
19358     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19359     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19360     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19361     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19362     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19363     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19364     */
19365    public int getSystemUiVisibility() {
19366        return mSystemUiVisibility;
19367    }
19368
19369    /**
19370     * Returns the current system UI visibility that is currently set for
19371     * the entire window.  This is the combination of the
19372     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19373     * views in the window.
19374     */
19375    public int getWindowSystemUiVisibility() {
19376        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19377    }
19378
19379    /**
19380     * Override to find out when the window's requested system UI visibility
19381     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19382     * This is different from the callbacks received through
19383     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19384     * in that this is only telling you about the local request of the window,
19385     * not the actual values applied by the system.
19386     */
19387    public void onWindowSystemUiVisibilityChanged(int visible) {
19388    }
19389
19390    /**
19391     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19392     * the view hierarchy.
19393     */
19394    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19395        onWindowSystemUiVisibilityChanged(visible);
19396    }
19397
19398    /**
19399     * Set a listener to receive callbacks when the visibility of the system bar changes.
19400     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19401     */
19402    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19403        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19404        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19405            mParent.recomputeViewAttributes(this);
19406        }
19407    }
19408
19409    /**
19410     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19411     * the view hierarchy.
19412     */
19413    public void dispatchSystemUiVisibilityChanged(int visibility) {
19414        ListenerInfo li = mListenerInfo;
19415        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19416            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19417                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19418        }
19419    }
19420
19421    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19422        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19423        if (val != mSystemUiVisibility) {
19424            setSystemUiVisibility(val);
19425            return true;
19426        }
19427        return false;
19428    }
19429
19430    /** @hide */
19431    public void setDisabledSystemUiVisibility(int flags) {
19432        if (mAttachInfo != null) {
19433            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19434                mAttachInfo.mDisabledSystemUiVisibility = flags;
19435                if (mParent != null) {
19436                    mParent.recomputeViewAttributes(this);
19437                }
19438            }
19439        }
19440    }
19441
19442    /**
19443     * Creates an image that the system displays during the drag and drop
19444     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19445     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19446     * appearance as the given View. The default also positions the center of the drag shadow
19447     * directly under the touch point. If no View is provided (the constructor with no parameters
19448     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19449     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19450     * default is an invisible drag shadow.
19451     * <p>
19452     * You are not required to use the View you provide to the constructor as the basis of the
19453     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19454     * anything you want as the drag shadow.
19455     * </p>
19456     * <p>
19457     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19458     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19459     *  size and position of the drag shadow. It uses this data to construct a
19460     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19461     *  so that your application can draw the shadow image in the Canvas.
19462     * </p>
19463     *
19464     * <div class="special reference">
19465     * <h3>Developer Guides</h3>
19466     * <p>For a guide to implementing drag and drop features, read the
19467     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19468     * </div>
19469     */
19470    public static class DragShadowBuilder {
19471        private final WeakReference<View> mView;
19472
19473        /**
19474         * Constructs a shadow image builder based on a View. By default, the resulting drag
19475         * shadow will have the same appearance and dimensions as the View, with the touch point
19476         * over the center of the View.
19477         * @param view A View. Any View in scope can be used.
19478         */
19479        public DragShadowBuilder(View view) {
19480            mView = new WeakReference<View>(view);
19481        }
19482
19483        /**
19484         * Construct a shadow builder object with no associated View.  This
19485         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19486         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19487         * to supply the drag shadow's dimensions and appearance without
19488         * reference to any View object. If they are not overridden, then the result is an
19489         * invisible drag shadow.
19490         */
19491        public DragShadowBuilder() {
19492            mView = new WeakReference<View>(null);
19493        }
19494
19495        /**
19496         * Returns the View object that had been passed to the
19497         * {@link #View.DragShadowBuilder(View)}
19498         * constructor.  If that View parameter was {@code null} or if the
19499         * {@link #View.DragShadowBuilder()}
19500         * constructor was used to instantiate the builder object, this method will return
19501         * null.
19502         *
19503         * @return The View object associate with this builder object.
19504         */
19505        @SuppressWarnings({"JavadocReference"})
19506        final public View getView() {
19507            return mView.get();
19508        }
19509
19510        /**
19511         * Provides the metrics for the shadow image. These include the dimensions of
19512         * the shadow image, and the point within that shadow that should
19513         * be centered under the touch location while dragging.
19514         * <p>
19515         * The default implementation sets the dimensions of the shadow to be the
19516         * same as the dimensions of the View itself and centers the shadow under
19517         * the touch point.
19518         * </p>
19519         *
19520         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19521         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19522         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19523         * image.
19524         *
19525         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19526         * shadow image that should be underneath the touch point during the drag and drop
19527         * operation. Your application must set {@link android.graphics.Point#x} to the
19528         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19529         */
19530        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19531            final View view = mView.get();
19532            if (view != null) {
19533                shadowSize.set(view.getWidth(), view.getHeight());
19534                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19535            } else {
19536                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19537            }
19538        }
19539
19540        /**
19541         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19542         * based on the dimensions it received from the
19543         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19544         *
19545         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19546         */
19547        public void onDrawShadow(Canvas canvas) {
19548            final View view = mView.get();
19549            if (view != null) {
19550                view.draw(canvas);
19551            } else {
19552                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19553            }
19554        }
19555    }
19556
19557    /**
19558     * Starts a drag and drop operation. When your application calls this method, it passes a
19559     * {@link android.view.View.DragShadowBuilder} object to the system. The
19560     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19561     * to get metrics for the drag shadow, and then calls the object's
19562     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19563     * <p>
19564     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19565     *  drag events to all the View objects in your application that are currently visible. It does
19566     *  this either by calling the View object's drag listener (an implementation of
19567     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19568     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19569     *  Both are passed a {@link android.view.DragEvent} object that has a
19570     *  {@link android.view.DragEvent#getAction()} value of
19571     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19572     * </p>
19573     * <p>
19574     * Your application can invoke startDrag() on any attached View object. The View object does not
19575     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19576     * be related to the View the user selected for dragging.
19577     * </p>
19578     * @param data A {@link android.content.ClipData} object pointing to the data to be
19579     * transferred by the drag and drop operation.
19580     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19581     * drag shadow.
19582     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19583     * drop operation. This Object is put into every DragEvent object sent by the system during the
19584     * current drag.
19585     * <p>
19586     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19587     * to the target Views. For example, it can contain flags that differentiate between a
19588     * a copy operation and a move operation.
19589     * </p>
19590     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19591     * so the parameter should be set to 0.
19592     * @return {@code true} if the method completes successfully, or
19593     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19594     * do a drag, and so no drag operation is in progress.
19595     */
19596    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19597            Object myLocalState, int flags) {
19598        if (ViewDebug.DEBUG_DRAG) {
19599            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19600        }
19601        boolean okay = false;
19602
19603        Point shadowSize = new Point();
19604        Point shadowTouchPoint = new Point();
19605        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19606
19607        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19608                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19609            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19610        }
19611
19612        if (ViewDebug.DEBUG_DRAG) {
19613            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19614                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19615        }
19616        Surface surface = new Surface();
19617        try {
19618            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19619                    flags, shadowSize.x, shadowSize.y, surface);
19620            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19621                    + " surface=" + surface);
19622            if (token != null) {
19623                Canvas canvas = surface.lockCanvas(null);
19624                try {
19625                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19626                    shadowBuilder.onDrawShadow(canvas);
19627                } finally {
19628                    surface.unlockCanvasAndPost(canvas);
19629                }
19630
19631                final ViewRootImpl root = getViewRootImpl();
19632
19633                // Cache the local state object for delivery with DragEvents
19634                root.setLocalDragState(myLocalState);
19635
19636                // repurpose 'shadowSize' for the last touch point
19637                root.getLastTouchPoint(shadowSize);
19638
19639                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19640                        shadowSize.x, shadowSize.y,
19641                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19642                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19643
19644                // Off and running!  Release our local surface instance; the drag
19645                // shadow surface is now managed by the system process.
19646                surface.release();
19647            }
19648        } catch (Exception e) {
19649            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19650            surface.destroy();
19651        }
19652
19653        return okay;
19654    }
19655
19656    /**
19657     * Handles drag events sent by the system following a call to
19658     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19659     *<p>
19660     * When the system calls this method, it passes a
19661     * {@link android.view.DragEvent} object. A call to
19662     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19663     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19664     * operation.
19665     * @param event The {@link android.view.DragEvent} sent by the system.
19666     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19667     * in DragEvent, indicating the type of drag event represented by this object.
19668     * @return {@code true} if the method was successful, otherwise {@code false}.
19669     * <p>
19670     *  The method should return {@code true} in response to an action type of
19671     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19672     *  operation.
19673     * </p>
19674     * <p>
19675     *  The method should also return {@code true} in response to an action type of
19676     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19677     *  {@code false} if it didn't.
19678     * </p>
19679     */
19680    public boolean onDragEvent(DragEvent event) {
19681        return false;
19682    }
19683
19684    /**
19685     * Detects if this View is enabled and has a drag event listener.
19686     * If both are true, then it calls the drag event listener with the
19687     * {@link android.view.DragEvent} it received. If the drag event listener returns
19688     * {@code true}, then dispatchDragEvent() returns {@code true}.
19689     * <p>
19690     * For all other cases, the method calls the
19691     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19692     * method and returns its result.
19693     * </p>
19694     * <p>
19695     * This ensures that a drag event is always consumed, even if the View does not have a drag
19696     * event listener. However, if the View has a listener and the listener returns true, then
19697     * onDragEvent() is not called.
19698     * </p>
19699     */
19700    public boolean dispatchDragEvent(DragEvent event) {
19701        ListenerInfo li = mListenerInfo;
19702        //noinspection SimplifiableIfStatement
19703        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19704                && li.mOnDragListener.onDrag(this, event)) {
19705            return true;
19706        }
19707        return onDragEvent(event);
19708    }
19709
19710    boolean canAcceptDrag() {
19711        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19712    }
19713
19714    /**
19715     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19716     * it is ever exposed at all.
19717     * @hide
19718     */
19719    public void onCloseSystemDialogs(String reason) {
19720    }
19721
19722    /**
19723     * Given a Drawable whose bounds have been set to draw into this view,
19724     * update a Region being computed for
19725     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19726     * that any non-transparent parts of the Drawable are removed from the
19727     * given transparent region.
19728     *
19729     * @param dr The Drawable whose transparency is to be applied to the region.
19730     * @param region A Region holding the current transparency information,
19731     * where any parts of the region that are set are considered to be
19732     * transparent.  On return, this region will be modified to have the
19733     * transparency information reduced by the corresponding parts of the
19734     * Drawable that are not transparent.
19735     * {@hide}
19736     */
19737    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19738        if (DBG) {
19739            Log.i("View", "Getting transparent region for: " + this);
19740        }
19741        final Region r = dr.getTransparentRegion();
19742        final Rect db = dr.getBounds();
19743        final AttachInfo attachInfo = mAttachInfo;
19744        if (r != null && attachInfo != null) {
19745            final int w = getRight()-getLeft();
19746            final int h = getBottom()-getTop();
19747            if (db.left > 0) {
19748                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19749                r.op(0, 0, db.left, h, Region.Op.UNION);
19750            }
19751            if (db.right < w) {
19752                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19753                r.op(db.right, 0, w, h, Region.Op.UNION);
19754            }
19755            if (db.top > 0) {
19756                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19757                r.op(0, 0, w, db.top, Region.Op.UNION);
19758            }
19759            if (db.bottom < h) {
19760                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19761                r.op(0, db.bottom, w, h, Region.Op.UNION);
19762            }
19763            final int[] location = attachInfo.mTransparentLocation;
19764            getLocationInWindow(location);
19765            r.translate(location[0], location[1]);
19766            region.op(r, Region.Op.INTERSECT);
19767        } else {
19768            region.op(db, Region.Op.DIFFERENCE);
19769        }
19770    }
19771
19772    private void checkForLongClick(int delayOffset) {
19773        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19774            mHasPerformedLongPress = false;
19775
19776            if (mPendingCheckForLongPress == null) {
19777                mPendingCheckForLongPress = new CheckForLongPress();
19778            }
19779            mPendingCheckForLongPress.rememberWindowAttachCount();
19780            postDelayed(mPendingCheckForLongPress,
19781                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19782        }
19783    }
19784
19785    /**
19786     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19787     * LayoutInflater} class, which provides a full range of options for view inflation.
19788     *
19789     * @param context The Context object for your activity or application.
19790     * @param resource The resource ID to inflate
19791     * @param root A view group that will be the parent.  Used to properly inflate the
19792     * layout_* parameters.
19793     * @see LayoutInflater
19794     */
19795    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19796        LayoutInflater factory = LayoutInflater.from(context);
19797        return factory.inflate(resource, root);
19798    }
19799
19800    /**
19801     * Scroll the view with standard behavior for scrolling beyond the normal
19802     * content boundaries. Views that call this method should override
19803     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19804     * results of an over-scroll operation.
19805     *
19806     * Views can use this method to handle any touch or fling-based scrolling.
19807     *
19808     * @param deltaX Change in X in pixels
19809     * @param deltaY Change in Y in pixels
19810     * @param scrollX Current X scroll value in pixels before applying deltaX
19811     * @param scrollY Current Y scroll value in pixels before applying deltaY
19812     * @param scrollRangeX Maximum content scroll range along the X axis
19813     * @param scrollRangeY Maximum content scroll range along the Y axis
19814     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19815     *          along the X axis.
19816     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19817     *          along the Y axis.
19818     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19819     * @return true if scrolling was clamped to an over-scroll boundary along either
19820     *          axis, false otherwise.
19821     */
19822    @SuppressWarnings({"UnusedParameters"})
19823    protected boolean overScrollBy(int deltaX, int deltaY,
19824            int scrollX, int scrollY,
19825            int scrollRangeX, int scrollRangeY,
19826            int maxOverScrollX, int maxOverScrollY,
19827            boolean isTouchEvent) {
19828        final int overScrollMode = mOverScrollMode;
19829        final boolean canScrollHorizontal =
19830                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19831        final boolean canScrollVertical =
19832                computeVerticalScrollRange() > computeVerticalScrollExtent();
19833        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19834                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19835        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19836                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19837
19838        int newScrollX = scrollX + deltaX;
19839        if (!overScrollHorizontal) {
19840            maxOverScrollX = 0;
19841        }
19842
19843        int newScrollY = scrollY + deltaY;
19844        if (!overScrollVertical) {
19845            maxOverScrollY = 0;
19846        }
19847
19848        // Clamp values if at the limits and record
19849        final int left = -maxOverScrollX;
19850        final int right = maxOverScrollX + scrollRangeX;
19851        final int top = -maxOverScrollY;
19852        final int bottom = maxOverScrollY + scrollRangeY;
19853
19854        boolean clampedX = false;
19855        if (newScrollX > right) {
19856            newScrollX = right;
19857            clampedX = true;
19858        } else if (newScrollX < left) {
19859            newScrollX = left;
19860            clampedX = true;
19861        }
19862
19863        boolean clampedY = false;
19864        if (newScrollY > bottom) {
19865            newScrollY = bottom;
19866            clampedY = true;
19867        } else if (newScrollY < top) {
19868            newScrollY = top;
19869            clampedY = true;
19870        }
19871
19872        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19873
19874        return clampedX || clampedY;
19875    }
19876
19877    /**
19878     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19879     * respond to the results of an over-scroll operation.
19880     *
19881     * @param scrollX New X scroll value in pixels
19882     * @param scrollY New Y scroll value in pixels
19883     * @param clampedX True if scrollX was clamped to an over-scroll boundary
19884     * @param clampedY True if scrollY was clamped to an over-scroll boundary
19885     */
19886    protected void onOverScrolled(int scrollX, int scrollY,
19887            boolean clampedX, boolean clampedY) {
19888        // Intentionally empty.
19889    }
19890
19891    /**
19892     * Returns the over-scroll mode for this view. The result will be
19893     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19894     * (allow over-scrolling only if the view content is larger than the container),
19895     * or {@link #OVER_SCROLL_NEVER}.
19896     *
19897     * @return This view's over-scroll mode.
19898     */
19899    public int getOverScrollMode() {
19900        return mOverScrollMode;
19901    }
19902
19903    /**
19904     * Set the over-scroll mode for this view. Valid over-scroll modes are
19905     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19906     * (allow over-scrolling only if the view content is larger than the container),
19907     * or {@link #OVER_SCROLL_NEVER}.
19908     *
19909     * Setting the over-scroll mode of a view will have an effect only if the
19910     * view is capable of scrolling.
19911     *
19912     * @param overScrollMode The new over-scroll mode for this view.
19913     */
19914    public void setOverScrollMode(int overScrollMode) {
19915        if (overScrollMode != OVER_SCROLL_ALWAYS &&
19916                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19917                overScrollMode != OVER_SCROLL_NEVER) {
19918            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19919        }
19920        mOverScrollMode = overScrollMode;
19921    }
19922
19923    /**
19924     * Enable or disable nested scrolling for this view.
19925     *
19926     * <p>If this property is set to true the view will be permitted to initiate nested
19927     * scrolling operations with a compatible parent view in the current hierarchy. If this
19928     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19929     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19930     * the nested scroll.</p>
19931     *
19932     * @param enabled true to enable nested scrolling, false to disable
19933     *
19934     * @see #isNestedScrollingEnabled()
19935     */
19936    public void setNestedScrollingEnabled(boolean enabled) {
19937        if (enabled) {
19938            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19939        } else {
19940            stopNestedScroll();
19941            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19942        }
19943    }
19944
19945    /**
19946     * Returns true if nested scrolling is enabled for this view.
19947     *
19948     * <p>If nested scrolling is enabled and this View class implementation supports it,
19949     * this view will act as a nested scrolling child view when applicable, forwarding data
19950     * about the scroll operation in progress to a compatible and cooperating nested scrolling
19951     * parent.</p>
19952     *
19953     * @return true if nested scrolling is enabled
19954     *
19955     * @see #setNestedScrollingEnabled(boolean)
19956     */
19957    public boolean isNestedScrollingEnabled() {
19958        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19959                PFLAG3_NESTED_SCROLLING_ENABLED;
19960    }
19961
19962    /**
19963     * Begin a nestable scroll operation along the given axes.
19964     *
19965     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19966     *
19967     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19968     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19969     * In the case of touch scrolling the nested scroll will be terminated automatically in
19970     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19971     * In the event of programmatic scrolling the caller must explicitly call
19972     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19973     *
19974     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19975     * If it returns false the caller may ignore the rest of this contract until the next scroll.
19976     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19977     *
19978     * <p>At each incremental step of the scroll the caller should invoke
19979     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19980     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19981     * parent at least partially consumed the scroll and the caller should adjust the amount it
19982     * scrolls by.</p>
19983     *
19984     * <p>After applying the remainder of the scroll delta the caller should invoke
19985     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19986     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19987     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19988     * </p>
19989     *
19990     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19991     *             {@link #SCROLL_AXIS_VERTICAL}.
19992     * @return true if a cooperative parent was found and nested scrolling has been enabled for
19993     *         the current gesture.
19994     *
19995     * @see #stopNestedScroll()
19996     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19997     * @see #dispatchNestedScroll(int, int, int, int, int[])
19998     */
19999    public boolean startNestedScroll(int axes) {
20000        if (hasNestedScrollingParent()) {
20001            // Already in progress
20002            return true;
20003        }
20004        if (isNestedScrollingEnabled()) {
20005            ViewParent p = getParent();
20006            View child = this;
20007            while (p != null) {
20008                try {
20009                    if (p.onStartNestedScroll(child, this, axes)) {
20010                        mNestedScrollingParent = p;
20011                        p.onNestedScrollAccepted(child, this, axes);
20012                        return true;
20013                    }
20014                } catch (AbstractMethodError e) {
20015                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20016                            "method onStartNestedScroll", e);
20017                    // Allow the search upward to continue
20018                }
20019                if (p instanceof View) {
20020                    child = (View) p;
20021                }
20022                p = p.getParent();
20023            }
20024        }
20025        return false;
20026    }
20027
20028    /**
20029     * Stop a nested scroll in progress.
20030     *
20031     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20032     *
20033     * @see #startNestedScroll(int)
20034     */
20035    public void stopNestedScroll() {
20036        if (mNestedScrollingParent != null) {
20037            mNestedScrollingParent.onStopNestedScroll(this);
20038            mNestedScrollingParent = null;
20039        }
20040    }
20041
20042    /**
20043     * Returns true if this view has a nested scrolling parent.
20044     *
20045     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20046     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20047     *
20048     * @return whether this view has a nested scrolling parent
20049     */
20050    public boolean hasNestedScrollingParent() {
20051        return mNestedScrollingParent != null;
20052    }
20053
20054    /**
20055     * Dispatch one step of a nested scroll in progress.
20056     *
20057     * <p>Implementations of views that support nested scrolling should call this to report
20058     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20059     * is not currently in progress or nested scrolling is not
20060     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20061     *
20062     * <p>Compatible View implementations should also call
20063     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20064     * consuming a component of the scroll event themselves.</p>
20065     *
20066     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20067     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20068     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20069     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20070     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20071     *                       in local view coordinates of this view from before this operation
20072     *                       to after it completes. View implementations may use this to adjust
20073     *                       expected input coordinate tracking.
20074     * @return true if the event was dispatched, false if it could not be dispatched.
20075     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20076     */
20077    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20078            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20079        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20080            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20081                int startX = 0;
20082                int startY = 0;
20083                if (offsetInWindow != null) {
20084                    getLocationInWindow(offsetInWindow);
20085                    startX = offsetInWindow[0];
20086                    startY = offsetInWindow[1];
20087                }
20088
20089                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20090                        dxUnconsumed, dyUnconsumed);
20091
20092                if (offsetInWindow != null) {
20093                    getLocationInWindow(offsetInWindow);
20094                    offsetInWindow[0] -= startX;
20095                    offsetInWindow[1] -= startY;
20096                }
20097                return true;
20098            } else if (offsetInWindow != null) {
20099                // No motion, no dispatch. Keep offsetInWindow up to date.
20100                offsetInWindow[0] = 0;
20101                offsetInWindow[1] = 0;
20102            }
20103        }
20104        return false;
20105    }
20106
20107    /**
20108     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20109     *
20110     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20111     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20112     * scrolling operation to consume some or all of the scroll operation before the child view
20113     * consumes it.</p>
20114     *
20115     * @param dx Horizontal scroll distance in pixels
20116     * @param dy Vertical scroll distance in pixels
20117     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20118     *                 and consumed[1] the consumed dy.
20119     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20120     *                       in local view coordinates of this view from before this operation
20121     *                       to after it completes. View implementations may use this to adjust
20122     *                       expected input coordinate tracking.
20123     * @return true if the parent consumed some or all of the scroll delta
20124     * @see #dispatchNestedScroll(int, int, int, int, int[])
20125     */
20126    public boolean dispatchNestedPreScroll(int dx, int dy,
20127            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20128        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20129            if (dx != 0 || dy != 0) {
20130                int startX = 0;
20131                int startY = 0;
20132                if (offsetInWindow != null) {
20133                    getLocationInWindow(offsetInWindow);
20134                    startX = offsetInWindow[0];
20135                    startY = offsetInWindow[1];
20136                }
20137
20138                if (consumed == null) {
20139                    if (mTempNestedScrollConsumed == null) {
20140                        mTempNestedScrollConsumed = new int[2];
20141                    }
20142                    consumed = mTempNestedScrollConsumed;
20143                }
20144                consumed[0] = 0;
20145                consumed[1] = 0;
20146                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20147
20148                if (offsetInWindow != null) {
20149                    getLocationInWindow(offsetInWindow);
20150                    offsetInWindow[0] -= startX;
20151                    offsetInWindow[1] -= startY;
20152                }
20153                return consumed[0] != 0 || consumed[1] != 0;
20154            } else if (offsetInWindow != null) {
20155                offsetInWindow[0] = 0;
20156                offsetInWindow[1] = 0;
20157            }
20158        }
20159        return false;
20160    }
20161
20162    /**
20163     * Dispatch a fling to a nested scrolling parent.
20164     *
20165     * <p>This method should be used to indicate that a nested scrolling child has detected
20166     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20167     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20168     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20169     * along a scrollable axis.</p>
20170     *
20171     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20172     * its own content, it can use this method to delegate the fling to its nested scrolling
20173     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20174     *
20175     * @param velocityX Horizontal fling velocity in pixels per second
20176     * @param velocityY Vertical fling velocity in pixels per second
20177     * @param consumed true if the child consumed the fling, false otherwise
20178     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20179     */
20180    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20181        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20182            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20183        }
20184        return false;
20185    }
20186
20187    /**
20188     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20189     *
20190     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20191     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20192     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20193     * before the child view consumes it. If this method returns <code>true</code>, a nested
20194     * parent view consumed the fling and this view should not scroll as a result.</p>
20195     *
20196     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20197     * the fling at a time. If a parent view consumed the fling this method will return false.
20198     * Custom view implementations should account for this in two ways:</p>
20199     *
20200     * <ul>
20201     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20202     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20203     *     position regardless.</li>
20204     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20205     *     even to settle back to a valid idle position.</li>
20206     * </ul>
20207     *
20208     * <p>Views should also not offer fling velocities to nested parent views along an axis
20209     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20210     * should not offer a horizontal fling velocity to its parents since scrolling along that
20211     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20212     *
20213     * @param velocityX Horizontal fling velocity in pixels per second
20214     * @param velocityY Vertical fling velocity in pixels per second
20215     * @return true if a nested scrolling parent consumed the fling
20216     */
20217    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20218        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20219            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20220        }
20221        return false;
20222    }
20223
20224    /**
20225     * Gets a scale factor that determines the distance the view should scroll
20226     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20227     * @return The vertical scroll scale factor.
20228     * @hide
20229     */
20230    protected float getVerticalScrollFactor() {
20231        if (mVerticalScrollFactor == 0) {
20232            TypedValue outValue = new TypedValue();
20233            if (!mContext.getTheme().resolveAttribute(
20234                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20235                throw new IllegalStateException(
20236                        "Expected theme to define listPreferredItemHeight.");
20237            }
20238            mVerticalScrollFactor = outValue.getDimension(
20239                    mContext.getResources().getDisplayMetrics());
20240        }
20241        return mVerticalScrollFactor;
20242    }
20243
20244    /**
20245     * Gets a scale factor that determines the distance the view should scroll
20246     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20247     * @return The horizontal scroll scale factor.
20248     * @hide
20249     */
20250    protected float getHorizontalScrollFactor() {
20251        // TODO: Should use something else.
20252        return getVerticalScrollFactor();
20253    }
20254
20255    /**
20256     * Return the value specifying the text direction or policy that was set with
20257     * {@link #setTextDirection(int)}.
20258     *
20259     * @return the defined text direction. It can be one of:
20260     *
20261     * {@link #TEXT_DIRECTION_INHERIT},
20262     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20263     * {@link #TEXT_DIRECTION_ANY_RTL},
20264     * {@link #TEXT_DIRECTION_LTR},
20265     * {@link #TEXT_DIRECTION_RTL},
20266     * {@link #TEXT_DIRECTION_LOCALE},
20267     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20268     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20269     *
20270     * @attr ref android.R.styleable#View_textDirection
20271     *
20272     * @hide
20273     */
20274    @ViewDebug.ExportedProperty(category = "text", mapping = {
20275            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20276            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20277            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20278            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20279            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20280            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20281            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20282            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20283    })
20284    public int getRawTextDirection() {
20285        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20286    }
20287
20288    /**
20289     * Set the text direction.
20290     *
20291     * @param textDirection the direction to set. Should be one of:
20292     *
20293     * {@link #TEXT_DIRECTION_INHERIT},
20294     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20295     * {@link #TEXT_DIRECTION_ANY_RTL},
20296     * {@link #TEXT_DIRECTION_LTR},
20297     * {@link #TEXT_DIRECTION_RTL},
20298     * {@link #TEXT_DIRECTION_LOCALE}
20299     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20300     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20301     *
20302     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20303     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20304     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20305     *
20306     * @attr ref android.R.styleable#View_textDirection
20307     */
20308    public void setTextDirection(int textDirection) {
20309        if (getRawTextDirection() != textDirection) {
20310            // Reset the current text direction and the resolved one
20311            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20312            resetResolvedTextDirection();
20313            // Set the new text direction
20314            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20315            // Do resolution
20316            resolveTextDirection();
20317            // Notify change
20318            onRtlPropertiesChanged(getLayoutDirection());
20319            // Refresh
20320            requestLayout();
20321            invalidate(true);
20322        }
20323    }
20324
20325    /**
20326     * Return the resolved text direction.
20327     *
20328     * @return the resolved text direction. Returns one of:
20329     *
20330     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20331     * {@link #TEXT_DIRECTION_ANY_RTL},
20332     * {@link #TEXT_DIRECTION_LTR},
20333     * {@link #TEXT_DIRECTION_RTL},
20334     * {@link #TEXT_DIRECTION_LOCALE},
20335     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20336     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20337     *
20338     * @attr ref android.R.styleable#View_textDirection
20339     */
20340    @ViewDebug.ExportedProperty(category = "text", mapping = {
20341            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20342            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20343            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20344            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20345            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20346            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20347            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20348            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20349    })
20350    public int getTextDirection() {
20351        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20352    }
20353
20354    /**
20355     * Resolve the text direction.
20356     *
20357     * @return true if resolution has been done, false otherwise.
20358     *
20359     * @hide
20360     */
20361    public boolean resolveTextDirection() {
20362        // Reset any previous text direction resolution
20363        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20364
20365        if (hasRtlSupport()) {
20366            // Set resolved text direction flag depending on text direction flag
20367            final int textDirection = getRawTextDirection();
20368            switch(textDirection) {
20369                case TEXT_DIRECTION_INHERIT:
20370                    if (!canResolveTextDirection()) {
20371                        // We cannot do the resolution if there is no parent, so use the default one
20372                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20373                        // Resolution will need to happen again later
20374                        return false;
20375                    }
20376
20377                    // Parent has not yet resolved, so we still return the default
20378                    try {
20379                        if (!mParent.isTextDirectionResolved()) {
20380                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20381                            // Resolution will need to happen again later
20382                            return false;
20383                        }
20384                    } catch (AbstractMethodError e) {
20385                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20386                                " does not fully implement ViewParent", e);
20387                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20388                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20389                        return true;
20390                    }
20391
20392                    // Set current resolved direction to the same value as the parent's one
20393                    int parentResolvedDirection;
20394                    try {
20395                        parentResolvedDirection = mParent.getTextDirection();
20396                    } catch (AbstractMethodError e) {
20397                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20398                                " does not fully implement ViewParent", e);
20399                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20400                    }
20401                    switch (parentResolvedDirection) {
20402                        case TEXT_DIRECTION_FIRST_STRONG:
20403                        case TEXT_DIRECTION_ANY_RTL:
20404                        case TEXT_DIRECTION_LTR:
20405                        case TEXT_DIRECTION_RTL:
20406                        case TEXT_DIRECTION_LOCALE:
20407                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20408                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20409                            mPrivateFlags2 |=
20410                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20411                            break;
20412                        default:
20413                            // Default resolved direction is "first strong" heuristic
20414                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20415                    }
20416                    break;
20417                case TEXT_DIRECTION_FIRST_STRONG:
20418                case TEXT_DIRECTION_ANY_RTL:
20419                case TEXT_DIRECTION_LTR:
20420                case TEXT_DIRECTION_RTL:
20421                case TEXT_DIRECTION_LOCALE:
20422                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20423                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20424                    // Resolved direction is the same as text direction
20425                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20426                    break;
20427                default:
20428                    // Default resolved direction is "first strong" heuristic
20429                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20430            }
20431        } else {
20432            // Default resolved direction is "first strong" heuristic
20433            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20434        }
20435
20436        // Set to resolved
20437        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20438        return true;
20439    }
20440
20441    /**
20442     * Check if text direction resolution can be done.
20443     *
20444     * @return true if text direction resolution can be done otherwise return false.
20445     */
20446    public boolean canResolveTextDirection() {
20447        switch (getRawTextDirection()) {
20448            case TEXT_DIRECTION_INHERIT:
20449                if (mParent != null) {
20450                    try {
20451                        return mParent.canResolveTextDirection();
20452                    } catch (AbstractMethodError e) {
20453                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20454                                " does not fully implement ViewParent", e);
20455                    }
20456                }
20457                return false;
20458
20459            default:
20460                return true;
20461        }
20462    }
20463
20464    /**
20465     * Reset resolved text direction. Text direction will be resolved during a call to
20466     * {@link #onMeasure(int, int)}.
20467     *
20468     * @hide
20469     */
20470    public void resetResolvedTextDirection() {
20471        // Reset any previous text direction resolution
20472        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20473        // Set to default value
20474        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20475    }
20476
20477    /**
20478     * @return true if text direction is inherited.
20479     *
20480     * @hide
20481     */
20482    public boolean isTextDirectionInherited() {
20483        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20484    }
20485
20486    /**
20487     * @return true if text direction is resolved.
20488     */
20489    public boolean isTextDirectionResolved() {
20490        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20491    }
20492
20493    /**
20494     * Return the value specifying the text alignment or policy that was set with
20495     * {@link #setTextAlignment(int)}.
20496     *
20497     * @return the defined text alignment. It can be one of:
20498     *
20499     * {@link #TEXT_ALIGNMENT_INHERIT},
20500     * {@link #TEXT_ALIGNMENT_GRAVITY},
20501     * {@link #TEXT_ALIGNMENT_CENTER},
20502     * {@link #TEXT_ALIGNMENT_TEXT_START},
20503     * {@link #TEXT_ALIGNMENT_TEXT_END},
20504     * {@link #TEXT_ALIGNMENT_VIEW_START},
20505     * {@link #TEXT_ALIGNMENT_VIEW_END}
20506     *
20507     * @attr ref android.R.styleable#View_textAlignment
20508     *
20509     * @hide
20510     */
20511    @ViewDebug.ExportedProperty(category = "text", mapping = {
20512            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20513            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20514            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20515            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20516            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20517            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20518            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20519    })
20520    @TextAlignment
20521    public int getRawTextAlignment() {
20522        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20523    }
20524
20525    /**
20526     * Set the text alignment.
20527     *
20528     * @param textAlignment The text alignment to set. Should be one of
20529     *
20530     * {@link #TEXT_ALIGNMENT_INHERIT},
20531     * {@link #TEXT_ALIGNMENT_GRAVITY},
20532     * {@link #TEXT_ALIGNMENT_CENTER},
20533     * {@link #TEXT_ALIGNMENT_TEXT_START},
20534     * {@link #TEXT_ALIGNMENT_TEXT_END},
20535     * {@link #TEXT_ALIGNMENT_VIEW_START},
20536     * {@link #TEXT_ALIGNMENT_VIEW_END}
20537     *
20538     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20539     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20540     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20541     *
20542     * @attr ref android.R.styleable#View_textAlignment
20543     */
20544    public void setTextAlignment(@TextAlignment int textAlignment) {
20545        if (textAlignment != getRawTextAlignment()) {
20546            // Reset the current and resolved text alignment
20547            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20548            resetResolvedTextAlignment();
20549            // Set the new text alignment
20550            mPrivateFlags2 |=
20551                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20552            // Do resolution
20553            resolveTextAlignment();
20554            // Notify change
20555            onRtlPropertiesChanged(getLayoutDirection());
20556            // Refresh
20557            requestLayout();
20558            invalidate(true);
20559        }
20560    }
20561
20562    /**
20563     * Return the resolved text alignment.
20564     *
20565     * @return the resolved text alignment. Returns one of:
20566     *
20567     * {@link #TEXT_ALIGNMENT_GRAVITY},
20568     * {@link #TEXT_ALIGNMENT_CENTER},
20569     * {@link #TEXT_ALIGNMENT_TEXT_START},
20570     * {@link #TEXT_ALIGNMENT_TEXT_END},
20571     * {@link #TEXT_ALIGNMENT_VIEW_START},
20572     * {@link #TEXT_ALIGNMENT_VIEW_END}
20573     *
20574     * @attr ref android.R.styleable#View_textAlignment
20575     */
20576    @ViewDebug.ExportedProperty(category = "text", mapping = {
20577            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20578            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20579            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20580            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20581            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20582            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20583            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20584    })
20585    @TextAlignment
20586    public int getTextAlignment() {
20587        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20588                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20589    }
20590
20591    /**
20592     * Resolve the text alignment.
20593     *
20594     * @return true if resolution has been done, false otherwise.
20595     *
20596     * @hide
20597     */
20598    public boolean resolveTextAlignment() {
20599        // Reset any previous text alignment resolution
20600        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20601
20602        if (hasRtlSupport()) {
20603            // Set resolved text alignment flag depending on text alignment flag
20604            final int textAlignment = getRawTextAlignment();
20605            switch (textAlignment) {
20606                case TEXT_ALIGNMENT_INHERIT:
20607                    // Check if we can resolve the text alignment
20608                    if (!canResolveTextAlignment()) {
20609                        // We cannot do the resolution if there is no parent so use the default
20610                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20611                        // Resolution will need to happen again later
20612                        return false;
20613                    }
20614
20615                    // Parent has not yet resolved, so we still return the default
20616                    try {
20617                        if (!mParent.isTextAlignmentResolved()) {
20618                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20619                            // Resolution will need to happen again later
20620                            return false;
20621                        }
20622                    } catch (AbstractMethodError e) {
20623                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20624                                " does not fully implement ViewParent", e);
20625                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20626                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20627                        return true;
20628                    }
20629
20630                    int parentResolvedTextAlignment;
20631                    try {
20632                        parentResolvedTextAlignment = mParent.getTextAlignment();
20633                    } catch (AbstractMethodError e) {
20634                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20635                                " does not fully implement ViewParent", e);
20636                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20637                    }
20638                    switch (parentResolvedTextAlignment) {
20639                        case TEXT_ALIGNMENT_GRAVITY:
20640                        case TEXT_ALIGNMENT_TEXT_START:
20641                        case TEXT_ALIGNMENT_TEXT_END:
20642                        case TEXT_ALIGNMENT_CENTER:
20643                        case TEXT_ALIGNMENT_VIEW_START:
20644                        case TEXT_ALIGNMENT_VIEW_END:
20645                            // Resolved text alignment is the same as the parent resolved
20646                            // text alignment
20647                            mPrivateFlags2 |=
20648                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20649                            break;
20650                        default:
20651                            // Use default resolved text alignment
20652                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20653                    }
20654                    break;
20655                case TEXT_ALIGNMENT_GRAVITY:
20656                case TEXT_ALIGNMENT_TEXT_START:
20657                case TEXT_ALIGNMENT_TEXT_END:
20658                case TEXT_ALIGNMENT_CENTER:
20659                case TEXT_ALIGNMENT_VIEW_START:
20660                case TEXT_ALIGNMENT_VIEW_END:
20661                    // Resolved text alignment is the same as text alignment
20662                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20663                    break;
20664                default:
20665                    // Use default resolved text alignment
20666                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20667            }
20668        } else {
20669            // Use default resolved text alignment
20670            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20671        }
20672
20673        // Set the resolved
20674        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20675        return true;
20676    }
20677
20678    /**
20679     * Check if text alignment resolution can be done.
20680     *
20681     * @return true if text alignment resolution can be done otherwise return false.
20682     */
20683    public boolean canResolveTextAlignment() {
20684        switch (getRawTextAlignment()) {
20685            case TEXT_DIRECTION_INHERIT:
20686                if (mParent != null) {
20687                    try {
20688                        return mParent.canResolveTextAlignment();
20689                    } catch (AbstractMethodError e) {
20690                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20691                                " does not fully implement ViewParent", e);
20692                    }
20693                }
20694                return false;
20695
20696            default:
20697                return true;
20698        }
20699    }
20700
20701    /**
20702     * Reset resolved text alignment. Text alignment will be resolved during a call to
20703     * {@link #onMeasure(int, int)}.
20704     *
20705     * @hide
20706     */
20707    public void resetResolvedTextAlignment() {
20708        // Reset any previous text alignment resolution
20709        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20710        // Set to default
20711        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20712    }
20713
20714    /**
20715     * @return true if text alignment is inherited.
20716     *
20717     * @hide
20718     */
20719    public boolean isTextAlignmentInherited() {
20720        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20721    }
20722
20723    /**
20724     * @return true if text alignment is resolved.
20725     */
20726    public boolean isTextAlignmentResolved() {
20727        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20728    }
20729
20730    /**
20731     * Generate a value suitable for use in {@link #setId(int)}.
20732     * This value will not collide with ID values generated at build time by aapt for R.id.
20733     *
20734     * @return a generated ID value
20735     */
20736    public static int generateViewId() {
20737        for (;;) {
20738            final int result = sNextGeneratedId.get();
20739            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20740            int newValue = result + 1;
20741            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20742            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20743                return result;
20744            }
20745        }
20746    }
20747
20748    /**
20749     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20750     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20751     *                           a normal View or a ViewGroup with
20752     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20753     * @hide
20754     */
20755    public void captureTransitioningViews(List<View> transitioningViews) {
20756        if (getVisibility() == View.VISIBLE) {
20757            transitioningViews.add(this);
20758        }
20759    }
20760
20761    /**
20762     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20763     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20764     * @hide
20765     */
20766    public void findNamedViews(Map<String, View> namedElements) {
20767        if (getVisibility() == VISIBLE || mGhostView != null) {
20768            String transitionName = getTransitionName();
20769            if (transitionName != null) {
20770                namedElements.put(transitionName, this);
20771            }
20772        }
20773    }
20774
20775    //
20776    // Properties
20777    //
20778    /**
20779     * A Property wrapper around the <code>alpha</code> functionality handled by the
20780     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20781     */
20782    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20783        @Override
20784        public void setValue(View object, float value) {
20785            object.setAlpha(value);
20786        }
20787
20788        @Override
20789        public Float get(View object) {
20790            return object.getAlpha();
20791        }
20792    };
20793
20794    /**
20795     * A Property wrapper around the <code>translationX</code> functionality handled by the
20796     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20797     */
20798    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20799        @Override
20800        public void setValue(View object, float value) {
20801            object.setTranslationX(value);
20802        }
20803
20804                @Override
20805        public Float get(View object) {
20806            return object.getTranslationX();
20807        }
20808    };
20809
20810    /**
20811     * A Property wrapper around the <code>translationY</code> functionality handled by the
20812     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20813     */
20814    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20815        @Override
20816        public void setValue(View object, float value) {
20817            object.setTranslationY(value);
20818        }
20819
20820        @Override
20821        public Float get(View object) {
20822            return object.getTranslationY();
20823        }
20824    };
20825
20826    /**
20827     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20828     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20829     */
20830    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20831        @Override
20832        public void setValue(View object, float value) {
20833            object.setTranslationZ(value);
20834        }
20835
20836        @Override
20837        public Float get(View object) {
20838            return object.getTranslationZ();
20839        }
20840    };
20841
20842    /**
20843     * A Property wrapper around the <code>x</code> functionality handled by the
20844     * {@link View#setX(float)} and {@link View#getX()} methods.
20845     */
20846    public static final Property<View, Float> X = new FloatProperty<View>("x") {
20847        @Override
20848        public void setValue(View object, float value) {
20849            object.setX(value);
20850        }
20851
20852        @Override
20853        public Float get(View object) {
20854            return object.getX();
20855        }
20856    };
20857
20858    /**
20859     * A Property wrapper around the <code>y</code> functionality handled by the
20860     * {@link View#setY(float)} and {@link View#getY()} methods.
20861     */
20862    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20863        @Override
20864        public void setValue(View object, float value) {
20865            object.setY(value);
20866        }
20867
20868        @Override
20869        public Float get(View object) {
20870            return object.getY();
20871        }
20872    };
20873
20874    /**
20875     * A Property wrapper around the <code>z</code> functionality handled by the
20876     * {@link View#setZ(float)} and {@link View#getZ()} methods.
20877     */
20878    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20879        @Override
20880        public void setValue(View object, float value) {
20881            object.setZ(value);
20882        }
20883
20884        @Override
20885        public Float get(View object) {
20886            return object.getZ();
20887        }
20888    };
20889
20890    /**
20891     * A Property wrapper around the <code>rotation</code> functionality handled by the
20892     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20893     */
20894    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20895        @Override
20896        public void setValue(View object, float value) {
20897            object.setRotation(value);
20898        }
20899
20900        @Override
20901        public Float get(View object) {
20902            return object.getRotation();
20903        }
20904    };
20905
20906    /**
20907     * A Property wrapper around the <code>rotationX</code> functionality handled by the
20908     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20909     */
20910    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20911        @Override
20912        public void setValue(View object, float value) {
20913            object.setRotationX(value);
20914        }
20915
20916        @Override
20917        public Float get(View object) {
20918            return object.getRotationX();
20919        }
20920    };
20921
20922    /**
20923     * A Property wrapper around the <code>rotationY</code> functionality handled by the
20924     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20925     */
20926    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20927        @Override
20928        public void setValue(View object, float value) {
20929            object.setRotationY(value);
20930        }
20931
20932        @Override
20933        public Float get(View object) {
20934            return object.getRotationY();
20935        }
20936    };
20937
20938    /**
20939     * A Property wrapper around the <code>scaleX</code> functionality handled by the
20940     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20941     */
20942    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20943        @Override
20944        public void setValue(View object, float value) {
20945            object.setScaleX(value);
20946        }
20947
20948        @Override
20949        public Float get(View object) {
20950            return object.getScaleX();
20951        }
20952    };
20953
20954    /**
20955     * A Property wrapper around the <code>scaleY</code> functionality handled by the
20956     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20957     */
20958    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20959        @Override
20960        public void setValue(View object, float value) {
20961            object.setScaleY(value);
20962        }
20963
20964        @Override
20965        public Float get(View object) {
20966            return object.getScaleY();
20967        }
20968    };
20969
20970    /**
20971     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20972     * Each MeasureSpec represents a requirement for either the width or the height.
20973     * A MeasureSpec is comprised of a size and a mode. There are three possible
20974     * modes:
20975     * <dl>
20976     * <dt>UNSPECIFIED</dt>
20977     * <dd>
20978     * The parent has not imposed any constraint on the child. It can be whatever size
20979     * it wants.
20980     * </dd>
20981     *
20982     * <dt>EXACTLY</dt>
20983     * <dd>
20984     * The parent has determined an exact size for the child. The child is going to be
20985     * given those bounds regardless of how big it wants to be.
20986     * </dd>
20987     *
20988     * <dt>AT_MOST</dt>
20989     * <dd>
20990     * The child can be as large as it wants up to the specified size.
20991     * </dd>
20992     * </dl>
20993     *
20994     * MeasureSpecs are implemented as ints to reduce object allocation. This class
20995     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20996     */
20997    public static class MeasureSpec {
20998        private static final int MODE_SHIFT = 30;
20999        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21000
21001        /**
21002         * Measure specification mode: The parent has not imposed any constraint
21003         * on the child. It can be whatever size it wants.
21004         */
21005        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21006
21007        /**
21008         * Measure specification mode: The parent has determined an exact size
21009         * for the child. The child is going to be given those bounds regardless
21010         * of how big it wants to be.
21011         */
21012        public static final int EXACTLY     = 1 << MODE_SHIFT;
21013
21014        /**
21015         * Measure specification mode: The child can be as large as it wants up
21016         * to the specified size.
21017         */
21018        public static final int AT_MOST     = 2 << MODE_SHIFT;
21019
21020        /**
21021         * Creates a measure specification based on the supplied size and mode.
21022         *
21023         * The mode must always be one of the following:
21024         * <ul>
21025         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21026         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21027         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21028         * </ul>
21029         *
21030         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21031         * implementation was such that the order of arguments did not matter
21032         * and overflow in either value could impact the resulting MeasureSpec.
21033         * {@link android.widget.RelativeLayout} was affected by this bug.
21034         * Apps targeting API levels greater than 17 will get the fixed, more strict
21035         * behavior.</p>
21036         *
21037         * @param size the size of the measure specification
21038         * @param mode the mode of the measure specification
21039         * @return the measure specification based on size and mode
21040         */
21041        public static int makeMeasureSpec(int size, int mode) {
21042            if (sUseBrokenMakeMeasureSpec) {
21043                return size + mode;
21044            } else {
21045                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21046            }
21047        }
21048
21049        /**
21050         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21051         * will automatically get a size of 0. Older apps expect this.
21052         *
21053         * @hide internal use only for compatibility with system widgets and older apps
21054         */
21055        public static int makeSafeMeasureSpec(int size, int mode) {
21056            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21057                return 0;
21058            }
21059            return makeMeasureSpec(size, mode);
21060        }
21061
21062        /**
21063         * Extracts the mode from the supplied measure specification.
21064         *
21065         * @param measureSpec the measure specification to extract the mode from
21066         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21067         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21068         *         {@link android.view.View.MeasureSpec#EXACTLY}
21069         */
21070        public static int getMode(int measureSpec) {
21071            return (measureSpec & MODE_MASK);
21072        }
21073
21074        /**
21075         * Extracts the size from the supplied measure specification.
21076         *
21077         * @param measureSpec the measure specification to extract the size from
21078         * @return the size in pixels defined in the supplied measure specification
21079         */
21080        public static int getSize(int measureSpec) {
21081            return (measureSpec & ~MODE_MASK);
21082        }
21083
21084        static int adjust(int measureSpec, int delta) {
21085            final int mode = getMode(measureSpec);
21086            int size = getSize(measureSpec);
21087            if (mode == UNSPECIFIED) {
21088                // No need to adjust size for UNSPECIFIED mode.
21089                return makeMeasureSpec(size, UNSPECIFIED);
21090            }
21091            size += delta;
21092            if (size < 0) {
21093                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21094                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21095                size = 0;
21096            }
21097            return makeMeasureSpec(size, mode);
21098        }
21099
21100        /**
21101         * Returns a String representation of the specified measure
21102         * specification.
21103         *
21104         * @param measureSpec the measure specification to convert to a String
21105         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21106         */
21107        public static String toString(int measureSpec) {
21108            int mode = getMode(measureSpec);
21109            int size = getSize(measureSpec);
21110
21111            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21112
21113            if (mode == UNSPECIFIED)
21114                sb.append("UNSPECIFIED ");
21115            else if (mode == EXACTLY)
21116                sb.append("EXACTLY ");
21117            else if (mode == AT_MOST)
21118                sb.append("AT_MOST ");
21119            else
21120                sb.append(mode).append(" ");
21121
21122            sb.append(size);
21123            return sb.toString();
21124        }
21125    }
21126
21127    private final class CheckForLongPress implements Runnable {
21128        private int mOriginalWindowAttachCount;
21129
21130        @Override
21131        public void run() {
21132            if (isPressed() && (mParent != null)
21133                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21134                if (performLongClick()) {
21135                    mHasPerformedLongPress = true;
21136                }
21137            }
21138        }
21139
21140        public void rememberWindowAttachCount() {
21141            mOriginalWindowAttachCount = mWindowAttachCount;
21142        }
21143    }
21144
21145    private final class CheckForTap implements Runnable {
21146        public float x;
21147        public float y;
21148
21149        @Override
21150        public void run() {
21151            mPrivateFlags &= ~PFLAG_PREPRESSED;
21152            setPressed(true, x, y);
21153            checkForLongClick(ViewConfiguration.getTapTimeout());
21154        }
21155    }
21156
21157    private final class PerformClick implements Runnable {
21158        @Override
21159        public void run() {
21160            performClick();
21161        }
21162    }
21163
21164    /**
21165     * This method returns a ViewPropertyAnimator object, which can be used to animate
21166     * specific properties on this View.
21167     *
21168     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21169     */
21170    public ViewPropertyAnimator animate() {
21171        if (mAnimator == null) {
21172            mAnimator = new ViewPropertyAnimator(this);
21173        }
21174        return mAnimator;
21175    }
21176
21177    /**
21178     * Sets the name of the View to be used to identify Views in Transitions.
21179     * Names should be unique in the View hierarchy.
21180     *
21181     * @param transitionName The name of the View to uniquely identify it for Transitions.
21182     */
21183    public final void setTransitionName(String transitionName) {
21184        mTransitionName = transitionName;
21185    }
21186
21187    /**
21188     * Returns the name of the View to be used to identify Views in Transitions.
21189     * Names should be unique in the View hierarchy.
21190     *
21191     * <p>This returns null if the View has not been given a name.</p>
21192     *
21193     * @return The name used of the View to be used to identify Views in Transitions or null
21194     * if no name has been given.
21195     */
21196    @ViewDebug.ExportedProperty
21197    public String getTransitionName() {
21198        return mTransitionName;
21199    }
21200
21201    /**
21202     * Interface definition for a callback to be invoked when a hardware key event is
21203     * dispatched to this view. The callback will be invoked before the key event is
21204     * given to the view. This is only useful for hardware keyboards; a software input
21205     * method has no obligation to trigger this listener.
21206     */
21207    public interface OnKeyListener {
21208        /**
21209         * Called when a hardware key is dispatched to a view. This allows listeners to
21210         * get a chance to respond before the target view.
21211         * <p>Key presses in software keyboards will generally NOT trigger this method,
21212         * although some may elect to do so in some situations. Do not assume a
21213         * software input method has to be key-based; even if it is, it may use key presses
21214         * in a different way than you expect, so there is no way to reliably catch soft
21215         * input key presses.
21216         *
21217         * @param v The view the key has been dispatched to.
21218         * @param keyCode The code for the physical key that was pressed
21219         * @param event The KeyEvent object containing full information about
21220         *        the event.
21221         * @return True if the listener has consumed the event, false otherwise.
21222         */
21223        boolean onKey(View v, int keyCode, KeyEvent event);
21224    }
21225
21226    /**
21227     * Interface definition for a callback to be invoked when a touch event is
21228     * dispatched to this view. The callback will be invoked before the touch
21229     * event is given to the view.
21230     */
21231    public interface OnTouchListener {
21232        /**
21233         * Called when a touch event is dispatched to a view. This allows listeners to
21234         * get a chance to respond before the target view.
21235         *
21236         * @param v The view the touch event has been dispatched to.
21237         * @param event The MotionEvent object containing full information about
21238         *        the event.
21239         * @return True if the listener has consumed the event, false otherwise.
21240         */
21241        boolean onTouch(View v, MotionEvent event);
21242    }
21243
21244    /**
21245     * Interface definition for a callback to be invoked when a hover event is
21246     * dispatched to this view. The callback will be invoked before the hover
21247     * event is given to the view.
21248     */
21249    public interface OnHoverListener {
21250        /**
21251         * Called when a hover event is dispatched to a view. This allows listeners to
21252         * get a chance to respond before the target view.
21253         *
21254         * @param v The view the hover event has been dispatched to.
21255         * @param event The MotionEvent object containing full information about
21256         *        the event.
21257         * @return True if the listener has consumed the event, false otherwise.
21258         */
21259        boolean onHover(View v, MotionEvent event);
21260    }
21261
21262    /**
21263     * Interface definition for a callback to be invoked when a generic motion event is
21264     * dispatched to this view. The callback will be invoked before the generic motion
21265     * event is given to the view.
21266     */
21267    public interface OnGenericMotionListener {
21268        /**
21269         * Called when a generic motion event is dispatched to a view. This allows listeners to
21270         * get a chance to respond before the target view.
21271         *
21272         * @param v The view the generic motion event has been dispatched to.
21273         * @param event The MotionEvent object containing full information about
21274         *        the event.
21275         * @return True if the listener has consumed the event, false otherwise.
21276         */
21277        boolean onGenericMotion(View v, MotionEvent event);
21278    }
21279
21280    /**
21281     * Interface definition for a callback to be invoked when a view has been clicked and held.
21282     */
21283    public interface OnLongClickListener {
21284        /**
21285         * Called when a view has been clicked and held.
21286         *
21287         * @param v The view that was clicked and held.
21288         *
21289         * @return true if the callback consumed the long click, false otherwise.
21290         */
21291        boolean onLongClick(View v);
21292    }
21293
21294    /**
21295     * Interface definition for a callback to be invoked when a drag is being dispatched
21296     * to this view.  The callback will be invoked before the hosting view's own
21297     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21298     * onDrag(event) behavior, it should return 'false' from this callback.
21299     *
21300     * <div class="special reference">
21301     * <h3>Developer Guides</h3>
21302     * <p>For a guide to implementing drag and drop features, read the
21303     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21304     * </div>
21305     */
21306    public interface OnDragListener {
21307        /**
21308         * Called when a drag event is dispatched to a view. This allows listeners
21309         * to get a chance to override base View behavior.
21310         *
21311         * @param v The View that received the drag event.
21312         * @param event The {@link android.view.DragEvent} object for the drag event.
21313         * @return {@code true} if the drag event was handled successfully, or {@code false}
21314         * if the drag event was not handled. Note that {@code false} will trigger the View
21315         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21316         */
21317        boolean onDrag(View v, DragEvent event);
21318    }
21319
21320    /**
21321     * Interface definition for a callback to be invoked when the focus state of
21322     * a view changed.
21323     */
21324    public interface OnFocusChangeListener {
21325        /**
21326         * Called when the focus state of a view has changed.
21327         *
21328         * @param v The view whose state has changed.
21329         * @param hasFocus The new focus state of v.
21330         */
21331        void onFocusChange(View v, boolean hasFocus);
21332    }
21333
21334    /**
21335     * Interface definition for a callback to be invoked when a view is clicked.
21336     */
21337    public interface OnClickListener {
21338        /**
21339         * Called when a view has been clicked.
21340         *
21341         * @param v The view that was clicked.
21342         */
21343        void onClick(View v);
21344    }
21345
21346    /**
21347     * Interface definition for a callback to be invoked when a view is context clicked.
21348     */
21349    public interface OnContextClickListener {
21350        /**
21351         * Called when a view is context clicked.
21352         *
21353         * @param v The view that has been context clicked.
21354         * @return true if the callback consumed the context click, false otherwise.
21355         */
21356        boolean onContextClick(View v);
21357    }
21358
21359    /**
21360     * Interface definition for a callback to be invoked when the context menu
21361     * for this view is being built.
21362     */
21363    public interface OnCreateContextMenuListener {
21364        /**
21365         * Called when the context menu for this view is being built. It is not
21366         * safe to hold onto the menu after this method returns.
21367         *
21368         * @param menu The context menu that is being built
21369         * @param v The view for which the context menu is being built
21370         * @param menuInfo Extra information about the item for which the
21371         *            context menu should be shown. This information will vary
21372         *            depending on the class of v.
21373         */
21374        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21375    }
21376
21377    /**
21378     * Interface definition for a callback to be invoked when the status bar changes
21379     * visibility.  This reports <strong>global</strong> changes to the system UI
21380     * state, not what the application is requesting.
21381     *
21382     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21383     */
21384    public interface OnSystemUiVisibilityChangeListener {
21385        /**
21386         * Called when the status bar changes visibility because of a call to
21387         * {@link View#setSystemUiVisibility(int)}.
21388         *
21389         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21390         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21391         * This tells you the <strong>global</strong> state of these UI visibility
21392         * flags, not what your app is currently applying.
21393         */
21394        public void onSystemUiVisibilityChange(int visibility);
21395    }
21396
21397    /**
21398     * Interface definition for a callback to be invoked when this view is attached
21399     * or detached from its window.
21400     */
21401    public interface OnAttachStateChangeListener {
21402        /**
21403         * Called when the view is attached to a window.
21404         * @param v The view that was attached
21405         */
21406        public void onViewAttachedToWindow(View v);
21407        /**
21408         * Called when the view is detached from a window.
21409         * @param v The view that was detached
21410         */
21411        public void onViewDetachedFromWindow(View v);
21412    }
21413
21414    /**
21415     * Listener for applying window insets on a view in a custom way.
21416     *
21417     * <p>Apps may choose to implement this interface if they want to apply custom policy
21418     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21419     * is set, its
21420     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21421     * method will be called instead of the View's own
21422     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21423     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21424     * the View's normal behavior as part of its own.</p>
21425     */
21426    public interface OnApplyWindowInsetsListener {
21427        /**
21428         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21429         * on a View, this listener method will be called instead of the view's own
21430         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21431         *
21432         * @param v The view applying window insets
21433         * @param insets The insets to apply
21434         * @return The insets supplied, minus any insets that were consumed
21435         */
21436        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21437    }
21438
21439    private final class UnsetPressedState implements Runnable {
21440        @Override
21441        public void run() {
21442            setPressed(false);
21443        }
21444    }
21445
21446    /**
21447     * Base class for derived classes that want to save and restore their own
21448     * state in {@link android.view.View#onSaveInstanceState()}.
21449     */
21450    public static class BaseSavedState extends AbsSavedState {
21451        String mStartActivityRequestWhoSaved;
21452
21453        /**
21454         * Constructor used when reading from a parcel. Reads the state of the superclass.
21455         *
21456         * @param source
21457         */
21458        public BaseSavedState(Parcel source) {
21459            super(source);
21460            mStartActivityRequestWhoSaved = source.readString();
21461        }
21462
21463        /**
21464         * Constructor called by derived classes when creating their SavedState objects
21465         *
21466         * @param superState The state of the superclass of this view
21467         */
21468        public BaseSavedState(Parcelable superState) {
21469            super(superState);
21470        }
21471
21472        @Override
21473        public void writeToParcel(Parcel out, int flags) {
21474            super.writeToParcel(out, flags);
21475            out.writeString(mStartActivityRequestWhoSaved);
21476        }
21477
21478        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21479                new Parcelable.Creator<BaseSavedState>() {
21480            public BaseSavedState createFromParcel(Parcel in) {
21481                return new BaseSavedState(in);
21482            }
21483
21484            public BaseSavedState[] newArray(int size) {
21485                return new BaseSavedState[size];
21486            }
21487        };
21488    }
21489
21490    /**
21491     * A set of information given to a view when it is attached to its parent
21492     * window.
21493     */
21494    final static class AttachInfo {
21495        interface Callbacks {
21496            void playSoundEffect(int effectId);
21497            boolean performHapticFeedback(int effectId, boolean always);
21498        }
21499
21500        /**
21501         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21502         * to a Handler. This class contains the target (View) to invalidate and
21503         * the coordinates of the dirty rectangle.
21504         *
21505         * For performance purposes, this class also implements a pool of up to
21506         * POOL_LIMIT objects that get reused. This reduces memory allocations
21507         * whenever possible.
21508         */
21509        static class InvalidateInfo {
21510            private static final int POOL_LIMIT = 10;
21511
21512            private static final SynchronizedPool<InvalidateInfo> sPool =
21513                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21514
21515            View target;
21516
21517            int left;
21518            int top;
21519            int right;
21520            int bottom;
21521
21522            public static InvalidateInfo obtain() {
21523                InvalidateInfo instance = sPool.acquire();
21524                return (instance != null) ? instance : new InvalidateInfo();
21525            }
21526
21527            public void recycle() {
21528                target = null;
21529                sPool.release(this);
21530            }
21531        }
21532
21533        final IWindowSession mSession;
21534
21535        final IWindow mWindow;
21536
21537        final IBinder mWindowToken;
21538
21539        final Display mDisplay;
21540
21541        final Callbacks mRootCallbacks;
21542
21543        IWindowId mIWindowId;
21544        WindowId mWindowId;
21545
21546        /**
21547         * The top view of the hierarchy.
21548         */
21549        View mRootView;
21550
21551        IBinder mPanelParentWindowToken;
21552
21553        boolean mHardwareAccelerated;
21554        boolean mHardwareAccelerationRequested;
21555        HardwareRenderer mHardwareRenderer;
21556        List<RenderNode> mPendingAnimatingRenderNodes;
21557
21558        /**
21559         * The state of the display to which the window is attached, as reported
21560         * by {@link Display#getState()}.  Note that the display state constants
21561         * declared by {@link Display} do not exactly line up with the screen state
21562         * constants declared by {@link View} (there are more display states than
21563         * screen states).
21564         */
21565        int mDisplayState = Display.STATE_UNKNOWN;
21566
21567        /**
21568         * Scale factor used by the compatibility mode
21569         */
21570        float mApplicationScale;
21571
21572        /**
21573         * Indicates whether the application is in compatibility mode
21574         */
21575        boolean mScalingRequired;
21576
21577        /**
21578         * Left position of this view's window
21579         */
21580        int mWindowLeft;
21581
21582        /**
21583         * Top position of this view's window
21584         */
21585        int mWindowTop;
21586
21587        /**
21588         * Indicates whether views need to use 32-bit drawing caches
21589         */
21590        boolean mUse32BitDrawingCache;
21591
21592        /**
21593         * For windows that are full-screen but using insets to layout inside
21594         * of the screen areas, these are the current insets to appear inside
21595         * the overscan area of the display.
21596         */
21597        final Rect mOverscanInsets = new Rect();
21598
21599        /**
21600         * For windows that are full-screen but using insets to layout inside
21601         * of the screen decorations, these are the current insets for the
21602         * content of the window.
21603         */
21604        final Rect mContentInsets = 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         * actual visible parts of the window.
21610         */
21611        final Rect mVisibleInsets = 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         * stable system windows.
21617         */
21618        final Rect mStableInsets = new Rect();
21619
21620        /**
21621         * For windows that include areas that are not covered by real surface these are the outsets
21622         * for real surface.
21623         */
21624        final Rect mOutsets = new Rect();
21625
21626        /**
21627         * The internal insets given by this window.  This value is
21628         * supplied by the client (through
21629         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21630         * be given to the window manager when changed to be used in laying
21631         * out windows behind it.
21632         */
21633        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21634                = new ViewTreeObserver.InternalInsetsInfo();
21635
21636        /**
21637         * Set to true when mGivenInternalInsets is non-empty.
21638         */
21639        boolean mHasNonEmptyGivenInternalInsets;
21640
21641        /**
21642         * All views in the window's hierarchy that serve as scroll containers,
21643         * used to determine if the window can be resized or must be panned
21644         * to adjust for a soft input area.
21645         */
21646        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21647
21648        final KeyEvent.DispatcherState mKeyDispatchState
21649                = new KeyEvent.DispatcherState();
21650
21651        /**
21652         * Indicates whether the view's window currently has the focus.
21653         */
21654        boolean mHasWindowFocus;
21655
21656        /**
21657         * The current visibility of the window.
21658         */
21659        int mWindowVisibility;
21660
21661        /**
21662         * Indicates the time at which drawing started to occur.
21663         */
21664        long mDrawingTime;
21665
21666        /**
21667         * Indicates whether or not ignoring the DIRTY_MASK flags.
21668         */
21669        boolean mIgnoreDirtyState;
21670
21671        /**
21672         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21673         * to avoid clearing that flag prematurely.
21674         */
21675        boolean mSetIgnoreDirtyState = false;
21676
21677        /**
21678         * Indicates whether the view's window is currently in touch mode.
21679         */
21680        boolean mInTouchMode;
21681
21682        /**
21683         * Indicates whether the view has requested unbuffered input dispatching for the current
21684         * event stream.
21685         */
21686        boolean mUnbufferedDispatchRequested;
21687
21688        /**
21689         * Indicates that ViewAncestor should trigger a global layout change
21690         * the next time it performs a traversal
21691         */
21692        boolean mRecomputeGlobalAttributes;
21693
21694        /**
21695         * Always report new attributes at next traversal.
21696         */
21697        boolean mForceReportNewAttributes;
21698
21699        /**
21700         * Set during a traveral if any views want to keep the screen on.
21701         */
21702        boolean mKeepScreenOn;
21703
21704        /**
21705         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21706         */
21707        int mSystemUiVisibility;
21708
21709        /**
21710         * Hack to force certain system UI visibility flags to be cleared.
21711         */
21712        int mDisabledSystemUiVisibility;
21713
21714        /**
21715         * Last global system UI visibility reported by the window manager.
21716         */
21717        int mGlobalSystemUiVisibility;
21718
21719        /**
21720         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21721         * attached.
21722         */
21723        boolean mHasSystemUiListeners;
21724
21725        /**
21726         * Set if the window has requested to extend into the overscan region
21727         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21728         */
21729        boolean mOverscanRequested;
21730
21731        /**
21732         * Set if the visibility of any views has changed.
21733         */
21734        boolean mViewVisibilityChanged;
21735
21736        /**
21737         * Set to true if a view has been scrolled.
21738         */
21739        boolean mViewScrollChanged;
21740
21741        /**
21742         * Set to true if high contrast mode enabled
21743         */
21744        boolean mHighContrastText;
21745
21746        /**
21747         * Global to the view hierarchy used as a temporary for dealing with
21748         * x/y points in the transparent region computations.
21749         */
21750        final int[] mTransparentLocation = new int[2];
21751
21752        /**
21753         * Global to the view hierarchy used as a temporary for dealing with
21754         * x/y points in the ViewGroup.invalidateChild implementation.
21755         */
21756        final int[] mInvalidateChildLocation = new int[2];
21757
21758        /**
21759         * Global to the view hierarchy used as a temporary for dealng with
21760         * computing absolute on-screen location.
21761         */
21762        final int[] mTmpLocation = new int[2];
21763
21764        /**
21765         * Global to the view hierarchy used as a temporary for dealing with
21766         * x/y location when view is transformed.
21767         */
21768        final float[] mTmpTransformLocation = new float[2];
21769
21770        /**
21771         * The view tree observer used to dispatch global events like
21772         * layout, pre-draw, touch mode change, etc.
21773         */
21774        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21775
21776        /**
21777         * A Canvas used by the view hierarchy to perform bitmap caching.
21778         */
21779        Canvas mCanvas;
21780
21781        /**
21782         * The view root impl.
21783         */
21784        final ViewRootImpl mViewRootImpl;
21785
21786        /**
21787         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21788         * handler can be used to pump events in the UI events queue.
21789         */
21790        final Handler mHandler;
21791
21792        /**
21793         * Temporary for use in computing invalidate rectangles while
21794         * calling up the hierarchy.
21795         */
21796        final Rect mTmpInvalRect = new Rect();
21797
21798        /**
21799         * Temporary for use in computing hit areas with transformed views
21800         */
21801        final RectF mTmpTransformRect = new RectF();
21802
21803        /**
21804         * Temporary for use in computing hit areas with transformed views
21805         */
21806        final RectF mTmpTransformRect1 = new RectF();
21807
21808        /**
21809         * Temporary list of rectanges.
21810         */
21811        final List<RectF> mTmpRectList = new ArrayList<>();
21812
21813        /**
21814         * Temporary for use in transforming invalidation rect
21815         */
21816        final Matrix mTmpMatrix = new Matrix();
21817
21818        /**
21819         * Temporary for use in transforming invalidation rect
21820         */
21821        final Transformation mTmpTransformation = new Transformation();
21822
21823        /**
21824         * Temporary for use in querying outlines from OutlineProviders
21825         */
21826        final Outline mTmpOutline = new Outline();
21827
21828        /**
21829         * Temporary list for use in collecting focusable descendents of a view.
21830         */
21831        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21832
21833        /**
21834         * The id of the window for accessibility purposes.
21835         */
21836        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21837
21838        /**
21839         * Flags related to accessibility processing.
21840         *
21841         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21842         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21843         */
21844        int mAccessibilityFetchFlags;
21845
21846        /**
21847         * The drawable for highlighting accessibility focus.
21848         */
21849        Drawable mAccessibilityFocusDrawable;
21850
21851        /**
21852         * Show where the margins, bounds and layout bounds are for each view.
21853         */
21854        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21855
21856        /**
21857         * Point used to compute visible regions.
21858         */
21859        final Point mPoint = new Point();
21860
21861        /**
21862         * Used to track which View originated a requestLayout() call, used when
21863         * requestLayout() is called during layout.
21864         */
21865        View mViewRequestingLayout;
21866
21867        /**
21868         * Creates a new set of attachment information with the specified
21869         * events handler and thread.
21870         *
21871         * @param handler the events handler the view must use
21872         */
21873        AttachInfo(IWindowSession session, IWindow window, Display display,
21874                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21875            mSession = session;
21876            mWindow = window;
21877            mWindowToken = window.asBinder();
21878            mDisplay = display;
21879            mViewRootImpl = viewRootImpl;
21880            mHandler = handler;
21881            mRootCallbacks = effectPlayer;
21882        }
21883    }
21884
21885    /**
21886     * <p>ScrollabilityCache holds various fields used by a View when scrolling
21887     * is supported. This avoids keeping too many unused fields in most
21888     * instances of View.</p>
21889     */
21890    private static class ScrollabilityCache implements Runnable {
21891
21892        /**
21893         * Scrollbars are not visible
21894         */
21895        public static final int OFF = 0;
21896
21897        /**
21898         * Scrollbars are visible
21899         */
21900        public static final int ON = 1;
21901
21902        /**
21903         * Scrollbars are fading away
21904         */
21905        public static final int FADING = 2;
21906
21907        public boolean fadeScrollBars;
21908
21909        public int fadingEdgeLength;
21910        public int scrollBarDefaultDelayBeforeFade;
21911        public int scrollBarFadeDuration;
21912
21913        public int scrollBarSize;
21914        public ScrollBarDrawable scrollBar;
21915        public float[] interpolatorValues;
21916        public View host;
21917
21918        public final Paint paint;
21919        public final Matrix matrix;
21920        public Shader shader;
21921
21922        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21923
21924        private static final float[] OPAQUE = { 255 };
21925        private static final float[] TRANSPARENT = { 0.0f };
21926
21927        /**
21928         * When fading should start. This time moves into the future every time
21929         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21930         */
21931        public long fadeStartTime;
21932
21933
21934        /**
21935         * The current state of the scrollbars: ON, OFF, or FADING
21936         */
21937        public int state = OFF;
21938
21939        private int mLastColor;
21940
21941        public ScrollabilityCache(ViewConfiguration configuration, View host) {
21942            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21943            scrollBarSize = configuration.getScaledScrollBarSize();
21944            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21945            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21946
21947            paint = new Paint();
21948            matrix = new Matrix();
21949            // use use a height of 1, and then wack the matrix each time we
21950            // actually use it.
21951            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21952            paint.setShader(shader);
21953            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21954
21955            this.host = host;
21956        }
21957
21958        public void setFadeColor(int color) {
21959            if (color != mLastColor) {
21960                mLastColor = color;
21961
21962                if (color != 0) {
21963                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21964                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21965                    paint.setShader(shader);
21966                    // Restore the default transfer mode (src_over)
21967                    paint.setXfermode(null);
21968                } else {
21969                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21970                    paint.setShader(shader);
21971                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21972                }
21973            }
21974        }
21975
21976        public void run() {
21977            long now = AnimationUtils.currentAnimationTimeMillis();
21978            if (now >= fadeStartTime) {
21979
21980                // the animation fades the scrollbars out by changing
21981                // the opacity (alpha) from fully opaque to fully
21982                // transparent
21983                int nextFrame = (int) now;
21984                int framesCount = 0;
21985
21986                Interpolator interpolator = scrollBarInterpolator;
21987
21988                // Start opaque
21989                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21990
21991                // End transparent
21992                nextFrame += scrollBarFadeDuration;
21993                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21994
21995                state = FADING;
21996
21997                // Kick off the fade animation
21998                host.invalidate(true);
21999            }
22000        }
22001    }
22002
22003    /**
22004     * Resuable callback for sending
22005     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22006     */
22007    private class SendViewScrolledAccessibilityEvent implements Runnable {
22008        public volatile boolean mIsPending;
22009
22010        public void run() {
22011            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22012            mIsPending = false;
22013        }
22014    }
22015
22016    /**
22017     * <p>
22018     * This class represents a delegate that can be registered in a {@link View}
22019     * to enhance accessibility support via composition rather via inheritance.
22020     * It is specifically targeted to widget developers that extend basic View
22021     * classes i.e. classes in package android.view, that would like their
22022     * applications to be backwards compatible.
22023     * </p>
22024     * <div class="special reference">
22025     * <h3>Developer Guides</h3>
22026     * <p>For more information about making applications accessible, read the
22027     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22028     * developer guide.</p>
22029     * </div>
22030     * <p>
22031     * A scenario in which a developer would like to use an accessibility delegate
22032     * is overriding a method introduced in a later API version then the minimal API
22033     * version supported by the application. For example, the method
22034     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22035     * in API version 4 when the accessibility APIs were first introduced. If a
22036     * developer would like his application to run on API version 4 devices (assuming
22037     * all other APIs used by the application are version 4 or lower) and take advantage
22038     * of this method, instead of overriding the method which would break the application's
22039     * backwards compatibility, he can override the corresponding method in this
22040     * delegate and register the delegate in the target View if the API version of
22041     * the system is high enough i.e. the API version is same or higher to the API
22042     * version that introduced
22043     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22044     * </p>
22045     * <p>
22046     * Here is an example implementation:
22047     * </p>
22048     * <code><pre><p>
22049     * if (Build.VERSION.SDK_INT >= 14) {
22050     *     // If the API version is equal of higher than the version in
22051     *     // which onInitializeAccessibilityNodeInfo was introduced we
22052     *     // register a delegate with a customized implementation.
22053     *     View view = findViewById(R.id.view_id);
22054     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22055     *         public void onInitializeAccessibilityNodeInfo(View host,
22056     *                 AccessibilityNodeInfo info) {
22057     *             // Let the default implementation populate the info.
22058     *             super.onInitializeAccessibilityNodeInfo(host, info);
22059     *             // Set some other information.
22060     *             info.setEnabled(host.isEnabled());
22061     *         }
22062     *     });
22063     * }
22064     * </code></pre></p>
22065     * <p>
22066     * This delegate contains methods that correspond to the accessibility methods
22067     * in View. If a delegate has been specified the implementation in View hands
22068     * off handling to the corresponding method in this delegate. The default
22069     * implementation the delegate methods behaves exactly as the corresponding
22070     * method in View for the case of no accessibility delegate been set. Hence,
22071     * to customize the behavior of a View method, clients can override only the
22072     * corresponding delegate method without altering the behavior of the rest
22073     * accessibility related methods of the host view.
22074     * </p>
22075     */
22076    public static class AccessibilityDelegate {
22077
22078        /**
22079         * Sends an accessibility event of the given type. If accessibility is not
22080         * enabled this method has no effect.
22081         * <p>
22082         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22083         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22084         * been set.
22085         * </p>
22086         *
22087         * @param host The View hosting the delegate.
22088         * @param eventType The type of the event to send.
22089         *
22090         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22091         */
22092        public void sendAccessibilityEvent(View host, int eventType) {
22093            host.sendAccessibilityEventInternal(eventType);
22094        }
22095
22096        /**
22097         * Performs the specified accessibility action on the view. For
22098         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22099         * <p>
22100         * The default implementation behaves as
22101         * {@link View#performAccessibilityAction(int, Bundle)
22102         *  View#performAccessibilityAction(int, Bundle)} for the case of
22103         *  no accessibility delegate been set.
22104         * </p>
22105         *
22106         * @param action The action to perform.
22107         * @return Whether the action was performed.
22108         *
22109         * @see View#performAccessibilityAction(int, Bundle)
22110         *      View#performAccessibilityAction(int, Bundle)
22111         */
22112        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22113            return host.performAccessibilityActionInternal(action, args);
22114        }
22115
22116        /**
22117         * Sends an accessibility event. This method behaves exactly as
22118         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22119         * empty {@link AccessibilityEvent} and does not perform a check whether
22120         * accessibility is enabled.
22121         * <p>
22122         * The default implementation behaves as
22123         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22124         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22125         * the case of no accessibility delegate been set.
22126         * </p>
22127         *
22128         * @param host The View hosting the delegate.
22129         * @param event The event to send.
22130         *
22131         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22132         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22133         */
22134        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22135            host.sendAccessibilityEventUncheckedInternal(event);
22136        }
22137
22138        /**
22139         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22140         * to its children for adding their text content to the event.
22141         * <p>
22142         * The default implementation behaves as
22143         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22144         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22145         * the case of no accessibility delegate been set.
22146         * </p>
22147         *
22148         * @param host The View hosting the delegate.
22149         * @param event The event.
22150         * @return True if the event population was completed.
22151         *
22152         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22153         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22154         */
22155        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22156            return host.dispatchPopulateAccessibilityEventInternal(event);
22157        }
22158
22159        /**
22160         * Gives a chance to the host View to populate the accessibility event with its
22161         * text content.
22162         * <p>
22163         * The default implementation behaves as
22164         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22165         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22166         * the case of no accessibility delegate been set.
22167         * </p>
22168         *
22169         * @param host The View hosting the delegate.
22170         * @param event The accessibility event which to populate.
22171         *
22172         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22173         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22174         */
22175        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22176            host.onPopulateAccessibilityEventInternal(event);
22177        }
22178
22179        /**
22180         * Initializes an {@link AccessibilityEvent} with information about the
22181         * the host View which is the event source.
22182         * <p>
22183         * The default implementation behaves as
22184         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22185         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22186         * the case of no accessibility delegate been set.
22187         * </p>
22188         *
22189         * @param host The View hosting the delegate.
22190         * @param event The event to initialize.
22191         *
22192         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22193         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22194         */
22195        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22196            host.onInitializeAccessibilityEventInternal(event);
22197        }
22198
22199        /**
22200         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22201         * <p>
22202         * The default implementation behaves as
22203         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22204         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22205         * the case of no accessibility delegate been set.
22206         * </p>
22207         *
22208         * @param host The View hosting the delegate.
22209         * @param info The instance to initialize.
22210         *
22211         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22212         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22213         */
22214        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22215            host.onInitializeAccessibilityNodeInfoInternal(info);
22216        }
22217
22218        /**
22219         * Called when a child of the host View has requested sending an
22220         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22221         * to augment the event.
22222         * <p>
22223         * The default implementation behaves as
22224         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22225         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22226         * the case of no accessibility delegate been set.
22227         * </p>
22228         *
22229         * @param host The View hosting the delegate.
22230         * @param child The child which requests sending the event.
22231         * @param event The event to be sent.
22232         * @return True if the event should be sent
22233         *
22234         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22235         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22236         */
22237        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22238                AccessibilityEvent event) {
22239            return host.onRequestSendAccessibilityEventInternal(child, event);
22240        }
22241
22242        /**
22243         * Gets the provider for managing a virtual view hierarchy rooted at this View
22244         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22245         * that explore the window content.
22246         * <p>
22247         * The default implementation behaves as
22248         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22249         * the case of no accessibility delegate been set.
22250         * </p>
22251         *
22252         * @return The provider.
22253         *
22254         * @see AccessibilityNodeProvider
22255         */
22256        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22257            return null;
22258        }
22259
22260        /**
22261         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22262         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22263         * This method is responsible for obtaining an accessibility node info from a
22264         * pool of reusable instances and calling
22265         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22266         * view to initialize the former.
22267         * <p>
22268         * <strong>Note:</strong> The client is responsible for recycling the obtained
22269         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22270         * creation.
22271         * </p>
22272         * <p>
22273         * The default implementation behaves as
22274         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22275         * the case of no accessibility delegate been set.
22276         * </p>
22277         * @return A populated {@link AccessibilityNodeInfo}.
22278         *
22279         * @see AccessibilityNodeInfo
22280         *
22281         * @hide
22282         */
22283        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22284            return host.createAccessibilityNodeInfoInternal();
22285        }
22286    }
22287
22288    private class MatchIdPredicate implements Predicate<View> {
22289        public int mId;
22290
22291        @Override
22292        public boolean apply(View view) {
22293            return (view.mID == mId);
22294        }
22295    }
22296
22297    private class MatchLabelForPredicate implements Predicate<View> {
22298        private int mLabeledId;
22299
22300        @Override
22301        public boolean apply(View view) {
22302            return (view.mLabelForId == mLabeledId);
22303        }
22304    }
22305
22306    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22307        private int mChangeTypes = 0;
22308        private boolean mPosted;
22309        private boolean mPostedWithDelay;
22310        private long mLastEventTimeMillis;
22311
22312        @Override
22313        public void run() {
22314            mPosted = false;
22315            mPostedWithDelay = false;
22316            mLastEventTimeMillis = SystemClock.uptimeMillis();
22317            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22318                final AccessibilityEvent event = AccessibilityEvent.obtain();
22319                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22320                event.setContentChangeTypes(mChangeTypes);
22321                sendAccessibilityEventUnchecked(event);
22322            }
22323            mChangeTypes = 0;
22324        }
22325
22326        public void runOrPost(int changeType) {
22327            mChangeTypes |= changeType;
22328
22329            // If this is a live region or the child of a live region, collect
22330            // all events from this frame and send them on the next frame.
22331            if (inLiveRegion()) {
22332                // If we're already posted with a delay, remove that.
22333                if (mPostedWithDelay) {
22334                    removeCallbacks(this);
22335                    mPostedWithDelay = false;
22336                }
22337                // Only post if we're not already posted.
22338                if (!mPosted) {
22339                    post(this);
22340                    mPosted = true;
22341                }
22342                return;
22343            }
22344
22345            if (mPosted) {
22346                return;
22347            }
22348
22349            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22350            final long minEventIntevalMillis =
22351                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22352            if (timeSinceLastMillis >= minEventIntevalMillis) {
22353                removeCallbacks(this);
22354                run();
22355            } else {
22356                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22357                mPostedWithDelay = true;
22358            }
22359        }
22360    }
22361
22362    private boolean inLiveRegion() {
22363        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22364            return true;
22365        }
22366
22367        ViewParent parent = getParent();
22368        while (parent instanceof View) {
22369            if (((View) parent).getAccessibilityLiveRegion()
22370                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22371                return true;
22372            }
22373            parent = parent.getParent();
22374        }
22375
22376        return false;
22377    }
22378
22379    /**
22380     * Dump all private flags in readable format, useful for documentation and
22381     * sanity checking.
22382     */
22383    private static void dumpFlags() {
22384        final HashMap<String, String> found = Maps.newHashMap();
22385        try {
22386            for (Field field : View.class.getDeclaredFields()) {
22387                final int modifiers = field.getModifiers();
22388                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22389                    if (field.getType().equals(int.class)) {
22390                        final int value = field.getInt(null);
22391                        dumpFlag(found, field.getName(), value);
22392                    } else if (field.getType().equals(int[].class)) {
22393                        final int[] values = (int[]) field.get(null);
22394                        for (int i = 0; i < values.length; i++) {
22395                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22396                        }
22397                    }
22398                }
22399            }
22400        } catch (IllegalAccessException e) {
22401            throw new RuntimeException(e);
22402        }
22403
22404        final ArrayList<String> keys = Lists.newArrayList();
22405        keys.addAll(found.keySet());
22406        Collections.sort(keys);
22407        for (String key : keys) {
22408            Log.d(VIEW_LOG_TAG, found.get(key));
22409        }
22410    }
22411
22412    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22413        // Sort flags by prefix, then by bits, always keeping unique keys
22414        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22415        final int prefix = name.indexOf('_');
22416        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22417        final String output = bits + " " + name;
22418        found.put(key, output);
22419    }
22420
22421    /** {@hide} */
22422    public void encode(@NonNull ViewHierarchyEncoder stream) {
22423        stream.beginObject(this);
22424        encodeProperties(stream);
22425        stream.endObject();
22426    }
22427
22428    /** {@hide} */
22429    @CallSuper
22430    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22431        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22432        if (resolveId instanceof String) {
22433            stream.addProperty("id", (String) resolveId);
22434        } else {
22435            stream.addProperty("id", mID);
22436        }
22437
22438        stream.addProperty("misc:transformation.alpha",
22439                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22440        stream.addProperty("misc:transitionName", getTransitionName());
22441
22442        // layout
22443        stream.addProperty("layout:left", mLeft);
22444        stream.addProperty("layout:right", mRight);
22445        stream.addProperty("layout:top", mTop);
22446        stream.addProperty("layout:bottom", mBottom);
22447        stream.addProperty("layout:width", getWidth());
22448        stream.addProperty("layout:height", getHeight());
22449        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22450        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22451        stream.addProperty("layout:hasTransientState", hasTransientState());
22452        stream.addProperty("layout:baseline", getBaseline());
22453
22454        // layout params
22455        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22456        if (layoutParams != null) {
22457            stream.addPropertyKey("layoutParams");
22458            layoutParams.encode(stream);
22459        }
22460
22461        // scrolling
22462        stream.addProperty("scrolling:scrollX", mScrollX);
22463        stream.addProperty("scrolling:scrollY", mScrollY);
22464
22465        // padding
22466        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22467        stream.addProperty("padding:paddingRight", mPaddingRight);
22468        stream.addProperty("padding:paddingTop", mPaddingTop);
22469        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22470        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22471        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22472        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22473        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22474        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22475
22476        // measurement
22477        stream.addProperty("measurement:minHeight", mMinHeight);
22478        stream.addProperty("measurement:minWidth", mMinWidth);
22479        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22480        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22481
22482        // drawing
22483        stream.addProperty("drawing:elevation", getElevation());
22484        stream.addProperty("drawing:translationX", getTranslationX());
22485        stream.addProperty("drawing:translationY", getTranslationY());
22486        stream.addProperty("drawing:translationZ", getTranslationZ());
22487        stream.addProperty("drawing:rotation", getRotation());
22488        stream.addProperty("drawing:rotationX", getRotationX());
22489        stream.addProperty("drawing:rotationY", getRotationY());
22490        stream.addProperty("drawing:scaleX", getScaleX());
22491        stream.addProperty("drawing:scaleY", getScaleY());
22492        stream.addProperty("drawing:pivotX", getPivotX());
22493        stream.addProperty("drawing:pivotY", getPivotY());
22494        stream.addProperty("drawing:opaque", isOpaque());
22495        stream.addProperty("drawing:alpha", getAlpha());
22496        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22497        stream.addProperty("drawing:shadow", hasShadow());
22498        stream.addProperty("drawing:solidColor", getSolidColor());
22499        stream.addProperty("drawing:layerType", mLayerType);
22500        stream.addProperty("drawing:willNotDraw", willNotDraw());
22501        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22502        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22503        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22504        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22505
22506        // focus
22507        stream.addProperty("focus:hasFocus", hasFocus());
22508        stream.addProperty("focus:isFocused", isFocused());
22509        stream.addProperty("focus:isFocusable", isFocusable());
22510        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22511
22512        stream.addProperty("misc:clickable", isClickable());
22513        stream.addProperty("misc:pressed", isPressed());
22514        stream.addProperty("misc:selected", isSelected());
22515        stream.addProperty("misc:touchMode", isInTouchMode());
22516        stream.addProperty("misc:hovered", isHovered());
22517        stream.addProperty("misc:activated", isActivated());
22518
22519        stream.addProperty("misc:visibility", getVisibility());
22520        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22521        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22522
22523        stream.addProperty("misc:enabled", isEnabled());
22524        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22525        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22526
22527        // theme attributes
22528        Resources.Theme theme = getContext().getTheme();
22529        if (theme != null) {
22530            stream.addPropertyKey("theme");
22531            theme.encode(stream);
22532        }
22533
22534        // view attribute information
22535        int n = mAttributes != null ? mAttributes.length : 0;
22536        stream.addProperty("meta:__attrCount__", n/2);
22537        for (int i = 0; i < n; i += 2) {
22538            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22539        }
22540
22541        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22542
22543        // text
22544        stream.addProperty("text:textDirection", getTextDirection());
22545        stream.addProperty("text:textAlignment", getTextAlignment());
22546
22547        // accessibility
22548        CharSequence contentDescription = getContentDescription();
22549        stream.addProperty("accessibility:contentDescription",
22550                contentDescription == null ? "" : contentDescription.toString());
22551        stream.addProperty("accessibility:labelFor", getLabelFor());
22552        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22553    }
22554}
22555