View.java revision bbd8315daa82f9761c21d72ed22a3f001c28a6ca
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_SCROLL_INDICATOR_TOP
2359     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2360     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2361     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2362     *                     1             PFLAG3_SCROLL_INDICATOR_START
2363     *                    1              PFLAG3_SCROLL_INDICATOR_END
2364     *                   1               PFLAG3_ASSIST_BLOCKED
2365     * |-------|-------|-------|-------|
2366     */
2367
2368    /**
2369     * Flag indicating that view has a transform animation set on it. This is used to track whether
2370     * an animation is cleared between successive frames, in order to tell the associated
2371     * DisplayList to clear its animation matrix.
2372     */
2373    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2374
2375    /**
2376     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2377     * animation is cleared between successive frames, in order to tell the associated
2378     * DisplayList to restore its alpha value.
2379     */
2380    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2381
2382    /**
2383     * Flag indicating that the view has been through at least one layout since it
2384     * was last attached to a window.
2385     */
2386    static final int PFLAG3_IS_LAID_OUT = 0x4;
2387
2388    /**
2389     * Flag indicating that a call to measure() was skipped and should be done
2390     * instead when layout() is invoked.
2391     */
2392    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2393
2394    /**
2395     * Flag indicating that an overridden method correctly called down to
2396     * the superclass implementation as required by the API spec.
2397     */
2398    static final int PFLAG3_CALLED_SUPER = 0x10;
2399
2400    /**
2401     * Flag indicating that we're in the process of applying window insets.
2402     */
2403    static final int PFLAG3_APPLYING_INSETS = 0x20;
2404
2405    /**
2406     * Flag indicating that we're in the process of fitting system windows using the old method.
2407     */
2408    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2409
2410    /**
2411     * Flag indicating that nested scrolling is enabled for this view.
2412     * The view will optionally cooperate with views up its parent chain to allow for
2413     * integrated nested scrolling along the same axis.
2414     */
2415    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2416
2417    /**
2418     * Flag indicating that the bottom scroll indicator should be displayed
2419     * when this view can scroll up.
2420     */
2421    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2422
2423    /**
2424     * Flag indicating that the bottom scroll indicator should be displayed
2425     * when this view can scroll down.
2426     */
2427    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2428
2429    /**
2430     * Flag indicating that the left scroll indicator should be displayed
2431     * when this view can scroll left.
2432     */
2433    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2434
2435    /**
2436     * Flag indicating that the right scroll indicator should be displayed
2437     * when this view can scroll right.
2438     */
2439    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2440
2441    /**
2442     * Flag indicating that the start scroll indicator should be displayed
2443     * when this view can scroll in the start direction.
2444     */
2445    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2446
2447    /**
2448     * Flag indicating that the end scroll indicator should be displayed
2449     * when this view can scroll in the end direction.
2450     */
2451    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2452
2453    /* End of masks for mPrivateFlags3 */
2454
2455    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2456
2457    static final int SCROLL_INDICATORS_NONE = 0x0000;
2458
2459    /**
2460     * Mask for use with setFlags indicating bits used for indicating which
2461     * scroll indicators are enabled.
2462     */
2463    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2464            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2465            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2466            | PFLAG3_SCROLL_INDICATOR_END;
2467
2468    /**
2469     * Left-shift required to translate between public scroll indicator flags
2470     * and internal PFLAGS3 flags. When used as a right-shift, translates
2471     * PFLAGS3 flags to public flags.
2472     */
2473    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2474
2475    /** @hide */
2476    @Retention(RetentionPolicy.SOURCE)
2477    @IntDef(flag = true,
2478            value = {
2479                    SCROLL_INDICATOR_TOP,
2480                    SCROLL_INDICATOR_BOTTOM,
2481                    SCROLL_INDICATOR_LEFT,
2482                    SCROLL_INDICATOR_RIGHT,
2483                    SCROLL_INDICATOR_START,
2484                    SCROLL_INDICATOR_END,
2485            })
2486    public @interface ScrollIndicators {}
2487
2488    /**
2489     * Scroll indicator direction for the top edge of the view.
2490     *
2491     * @see #setScrollIndicators(int)
2492     * @see #setScrollIndicators(int, int)
2493     * @see #getScrollIndicators()
2494     */
2495    public static final int SCROLL_INDICATOR_TOP =
2496            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2497
2498    /**
2499     * Scroll indicator direction for the bottom edge of the view.
2500     *
2501     * @see #setScrollIndicators(int)
2502     * @see #setScrollIndicators(int, int)
2503     * @see #getScrollIndicators()
2504     */
2505    public static final int SCROLL_INDICATOR_BOTTOM =
2506            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2507
2508    /**
2509     * Scroll indicator direction for the left edge of the view.
2510     *
2511     * @see #setScrollIndicators(int)
2512     * @see #setScrollIndicators(int, int)
2513     * @see #getScrollIndicators()
2514     */
2515    public static final int SCROLL_INDICATOR_LEFT =
2516            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2517
2518    /**
2519     * Scroll indicator direction for the right edge of the view.
2520     *
2521     * @see #setScrollIndicators(int)
2522     * @see #setScrollIndicators(int, int)
2523     * @see #getScrollIndicators()
2524     */
2525    public static final int SCROLL_INDICATOR_RIGHT =
2526            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2527
2528    /**
2529     * Scroll indicator direction for the starting edge of the view.
2530     * <p>
2531     * Resolved according to the view's layout direction, see
2532     * {@link #getLayoutDirection()} for more information.
2533     *
2534     * @see #setScrollIndicators(int)
2535     * @see #setScrollIndicators(int, int)
2536     * @see #getScrollIndicators()
2537     */
2538    public static final int SCROLL_INDICATOR_START =
2539            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2540
2541    /**
2542     * Scroll indicator direction for the ending edge of the view.
2543     * <p>
2544     * Resolved according to the view's layout direction, see
2545     * {@link #getLayoutDirection()} for more information.
2546     *
2547     * @see #setScrollIndicators(int)
2548     * @see #setScrollIndicators(int, int)
2549     * @see #getScrollIndicators()
2550     */
2551    public static final int SCROLL_INDICATOR_END =
2552            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2553
2554    /**
2555     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2556     * into this view.<p>
2557     */
2558    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2559
2560    /**
2561     * Always allow a user to over-scroll this view, provided it is a
2562     * view that can scroll.
2563     *
2564     * @see #getOverScrollMode()
2565     * @see #setOverScrollMode(int)
2566     */
2567    public static final int OVER_SCROLL_ALWAYS = 0;
2568
2569    /**
2570     * Allow a user to over-scroll this view only if the content is large
2571     * enough to meaningfully scroll, provided it is a view that can scroll.
2572     *
2573     * @see #getOverScrollMode()
2574     * @see #setOverScrollMode(int)
2575     */
2576    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2577
2578    /**
2579     * Never allow a user to over-scroll this view.
2580     *
2581     * @see #getOverScrollMode()
2582     * @see #setOverScrollMode(int)
2583     */
2584    public static final int OVER_SCROLL_NEVER = 2;
2585
2586    /**
2587     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2588     * requested the system UI (status bar) to be visible (the default).
2589     *
2590     * @see #setSystemUiVisibility(int)
2591     */
2592    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2593
2594    /**
2595     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2596     * system UI to enter an unobtrusive "low profile" mode.
2597     *
2598     * <p>This is for use in games, book readers, video players, or any other
2599     * "immersive" application where the usual system chrome is deemed too distracting.
2600     *
2601     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2602     *
2603     * @see #setSystemUiVisibility(int)
2604     */
2605    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2606
2607    /**
2608     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2609     * system navigation be temporarily hidden.
2610     *
2611     * <p>This is an even less obtrusive state than that called for by
2612     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2613     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2614     * those to disappear. This is useful (in conjunction with the
2615     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2616     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2617     * window flags) for displaying content using every last pixel on the display.
2618     *
2619     * <p>There is a limitation: because navigation controls are so important, the least user
2620     * interaction will cause them to reappear immediately.  When this happens, both
2621     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2622     * so that both elements reappear at the same time.
2623     *
2624     * @see #setSystemUiVisibility(int)
2625     */
2626    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2627
2628    /**
2629     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2630     * into the normal fullscreen mode so that its content can take over the screen
2631     * while still allowing the user to interact with the application.
2632     *
2633     * <p>This has the same visual effect as
2634     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2635     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2636     * meaning that non-critical screen decorations (such as the status bar) will be
2637     * hidden while the user is in the View's window, focusing the experience on
2638     * that content.  Unlike the window flag, if you are using ActionBar in
2639     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2640     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2641     * hide the action bar.
2642     *
2643     * <p>This approach to going fullscreen is best used over the window flag when
2644     * it is a transient state -- that is, the application does this at certain
2645     * points in its user interaction where it wants to allow the user to focus
2646     * on content, but not as a continuous state.  For situations where the application
2647     * would like to simply stay full screen the entire time (such as a game that
2648     * wants to take over the screen), the
2649     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2650     * is usually a better approach.  The state set here will be removed by the system
2651     * in various situations (such as the user moving to another application) like
2652     * the other system UI states.
2653     *
2654     * <p>When using this flag, the application should provide some easy facility
2655     * for the user to go out of it.  A common example would be in an e-book
2656     * reader, where tapping on the screen brings back whatever screen and UI
2657     * decorations that had been hidden while the user was immersed in reading
2658     * the book.
2659     *
2660     * @see #setSystemUiVisibility(int)
2661     */
2662    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2663
2664    /**
2665     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2666     * flags, we would like a stable view of the content insets given to
2667     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2668     * will always represent the worst case that the application can expect
2669     * as a continuous state.  In the stock Android UI this is the space for
2670     * the system bar, nav bar, and status bar, but not more transient elements
2671     * such as an input method.
2672     *
2673     * The stable layout your UI sees is based on the system UI modes you can
2674     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2675     * then you will get a stable layout for changes of the
2676     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2677     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2678     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2679     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2680     * with a stable layout.  (Note that you should avoid using
2681     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2682     *
2683     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2684     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2685     * then a hidden status bar will be considered a "stable" state for purposes
2686     * here.  This allows your UI to continually hide the status bar, while still
2687     * using the system UI flags to hide the action bar while still retaining
2688     * a stable layout.  Note that changing the window fullscreen flag will never
2689     * provide a stable layout for a clean transition.
2690     *
2691     * <p>If you are using ActionBar in
2692     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2693     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2694     * insets it adds to those given to the application.
2695     */
2696    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2697
2698    /**
2699     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2700     * to be laid out as if it has requested
2701     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2702     * allows it to avoid artifacts when switching in and out of that mode, at
2703     * the expense that some of its user interface may be covered by screen
2704     * decorations when they are shown.  You can perform layout of your inner
2705     * UI elements to account for the navigation system UI through the
2706     * {@link #fitSystemWindows(Rect)} method.
2707     */
2708    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2709
2710    /**
2711     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2712     * to be laid out as if it has requested
2713     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2714     * allows it to avoid artifacts when switching in and out of that mode, at
2715     * the expense that some of its user interface may be covered by screen
2716     * decorations when they are shown.  You can perform layout of your inner
2717     * UI elements to account for non-fullscreen system UI through the
2718     * {@link #fitSystemWindows(Rect)} method.
2719     */
2720    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2721
2722    /**
2723     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2724     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2725     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2726     * user interaction.
2727     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2728     * has an effect when used in combination with that flag.</p>
2729     */
2730    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2731
2732    /**
2733     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2734     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2735     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2736     * experience while also hiding the system bars.  If this flag is not set,
2737     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2738     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2739     * if the user swipes from the top of the screen.
2740     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2741     * system gestures, such as swiping from the top of the screen.  These transient system bars
2742     * will overlay app’s content, may have some degree of transparency, and will automatically
2743     * hide after a short timeout.
2744     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2745     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2746     * with one or both of those flags.</p>
2747     */
2748    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2749
2750    /**
2751     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2752     * is compatible with light status bar backgrounds.
2753     *
2754     * <p>For this to take effect, the window must request
2755     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2756     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2757     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2758     *         FLAG_TRANSLUCENT_STATUS}.
2759     *
2760     * @see android.R.attr#windowLightStatusBar
2761     */
2762    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2763
2764    /**
2765     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2766     */
2767    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2768
2769    /**
2770     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2771     */
2772    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2773
2774    /**
2775     * @hide
2776     *
2777     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2778     * out of the public fields to keep the undefined bits out of the developer's way.
2779     *
2780     * Flag to make the status bar not expandable.  Unless you also
2781     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2782     */
2783    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2784
2785    /**
2786     * @hide
2787     *
2788     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2789     * out of the public fields to keep the undefined bits out of the developer's way.
2790     *
2791     * Flag to hide notification icons and scrolling ticker text.
2792     */
2793    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2794
2795    /**
2796     * @hide
2797     *
2798     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2799     * out of the public fields to keep the undefined bits out of the developer's way.
2800     *
2801     * Flag to disable incoming notification alerts.  This will not block
2802     * icons, but it will block sound, vibrating and other visual or aural notifications.
2803     */
2804    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2805
2806    /**
2807     * @hide
2808     *
2809     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2810     * out of the public fields to keep the undefined bits out of the developer's way.
2811     *
2812     * Flag to hide only the scrolling ticker.  Note that
2813     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2814     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2815     */
2816    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2817
2818    /**
2819     * @hide
2820     *
2821     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2822     * out of the public fields to keep the undefined bits out of the developer's way.
2823     *
2824     * Flag to hide the center system info area.
2825     */
2826    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2827
2828    /**
2829     * @hide
2830     *
2831     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2832     * out of the public fields to keep the undefined bits out of the developer's way.
2833     *
2834     * Flag to hide only the home button.  Don't use this
2835     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2836     */
2837    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
2838
2839    /**
2840     * @hide
2841     *
2842     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2843     * out of the public fields to keep the undefined bits out of the developer's way.
2844     *
2845     * Flag to hide only the back button. Don't use this
2846     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2847     */
2848    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2849
2850    /**
2851     * @hide
2852     *
2853     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2854     * out of the public fields to keep the undefined bits out of the developer's way.
2855     *
2856     * Flag to hide only the clock.  You might use this if your activity has
2857     * its own clock making the status bar's clock redundant.
2858     */
2859    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2860
2861    /**
2862     * @hide
2863     *
2864     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2865     * out of the public fields to keep the undefined bits out of the developer's way.
2866     *
2867     * Flag to hide only the recent apps button. Don't use this
2868     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2869     */
2870    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2871
2872    /**
2873     * @hide
2874     *
2875     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2876     * out of the public fields to keep the undefined bits out of the developer's way.
2877     *
2878     * Flag to disable the global search gesture. Don't use this
2879     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2880     */
2881    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2882
2883    /**
2884     * @hide
2885     *
2886     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2887     * out of the public fields to keep the undefined bits out of the developer's way.
2888     *
2889     * Flag to specify that the status bar is displayed in transient mode.
2890     */
2891    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2892
2893    /**
2894     * @hide
2895     *
2896     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2897     * out of the public fields to keep the undefined bits out of the developer's way.
2898     *
2899     * Flag to specify that the navigation bar is displayed in transient mode.
2900     */
2901    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2902
2903    /**
2904     * @hide
2905     *
2906     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2907     * out of the public fields to keep the undefined bits out of the developer's way.
2908     *
2909     * Flag to specify that the hidden status bar would like to be shown.
2910     */
2911    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2912
2913    /**
2914     * @hide
2915     *
2916     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2917     * out of the public fields to keep the undefined bits out of the developer's way.
2918     *
2919     * Flag to specify that the hidden navigation bar would like to be shown.
2920     */
2921    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
2922
2923    /**
2924     * @hide
2925     *
2926     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2927     * out of the public fields to keep the undefined bits out of the developer's way.
2928     *
2929     * Flag to specify that the status bar is displayed in translucent mode.
2930     */
2931    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
2932
2933    /**
2934     * @hide
2935     *
2936     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2937     * out of the public fields to keep the undefined bits out of the developer's way.
2938     *
2939     * Flag to specify that the navigation bar is displayed in translucent mode.
2940     */
2941    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
2942
2943    /**
2944     * @hide
2945     *
2946     * Whether Recents is visible or not.
2947     */
2948    public static final int RECENT_APPS_VISIBLE = 0x00004000;
2949
2950    /**
2951     * @hide
2952     *
2953     * Makes system ui transparent.
2954     */
2955    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
2956
2957    /**
2958     * @hide
2959     */
2960    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
2961
2962    /**
2963     * These are the system UI flags that can be cleared by events outside
2964     * of an application.  Currently this is just the ability to tap on the
2965     * screen while hiding the navigation bar to have it return.
2966     * @hide
2967     */
2968    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
2969            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2970            | SYSTEM_UI_FLAG_FULLSCREEN;
2971
2972    /**
2973     * Flags that can impact the layout in relation to system UI.
2974     */
2975    public static final int SYSTEM_UI_LAYOUT_FLAGS =
2976            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2977            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
2978
2979    /** @hide */
2980    @IntDef(flag = true,
2981            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
2982    @Retention(RetentionPolicy.SOURCE)
2983    public @interface FindViewFlags {}
2984
2985    /**
2986     * Find views that render the specified text.
2987     *
2988     * @see #findViewsWithText(ArrayList, CharSequence, int)
2989     */
2990    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2991
2992    /**
2993     * Find find views that contain the specified content description.
2994     *
2995     * @see #findViewsWithText(ArrayList, CharSequence, int)
2996     */
2997    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2998
2999    /**
3000     * Find views that contain {@link AccessibilityNodeProvider}. Such
3001     * a View is a root of virtual view hierarchy and may contain the searched
3002     * text. If this flag is set Views with providers are automatically
3003     * added and it is a responsibility of the client to call the APIs of
3004     * the provider to determine whether the virtual tree rooted at this View
3005     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3006     * representing the virtual views with this text.
3007     *
3008     * @see #findViewsWithText(ArrayList, CharSequence, int)
3009     *
3010     * @hide
3011     */
3012    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3013
3014    /**
3015     * The undefined cursor position.
3016     *
3017     * @hide
3018     */
3019    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3020
3021    /**
3022     * Indicates that the screen has changed state and is now off.
3023     *
3024     * @see #onScreenStateChanged(int)
3025     */
3026    public static final int SCREEN_STATE_OFF = 0x0;
3027
3028    /**
3029     * Indicates that the screen has changed state and is now on.
3030     *
3031     * @see #onScreenStateChanged(int)
3032     */
3033    public static final int SCREEN_STATE_ON = 0x1;
3034
3035    /**
3036     * Indicates no axis of view scrolling.
3037     */
3038    public static final int SCROLL_AXIS_NONE = 0;
3039
3040    /**
3041     * Indicates scrolling along the horizontal axis.
3042     */
3043    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3044
3045    /**
3046     * Indicates scrolling along the vertical axis.
3047     */
3048    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3049
3050    /**
3051     * Controls the over-scroll mode for this view.
3052     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3053     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3054     * and {@link #OVER_SCROLL_NEVER}.
3055     */
3056    private int mOverScrollMode;
3057
3058    /**
3059     * The parent this view is attached to.
3060     * {@hide}
3061     *
3062     * @see #getParent()
3063     */
3064    protected ViewParent mParent;
3065
3066    /**
3067     * {@hide}
3068     */
3069    AttachInfo mAttachInfo;
3070
3071    /**
3072     * {@hide}
3073     */
3074    @ViewDebug.ExportedProperty(flagMapping = {
3075        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3076                name = "FORCE_LAYOUT"),
3077        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3078                name = "LAYOUT_REQUIRED"),
3079        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3080            name = "DRAWING_CACHE_INVALID", outputIf = false),
3081        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3082        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3083        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3084        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3085    }, formatToHexString = true)
3086    int mPrivateFlags;
3087    int mPrivateFlags2;
3088    int mPrivateFlags3;
3089
3090    /**
3091     * This view's request for the visibility of the status bar.
3092     * @hide
3093     */
3094    @ViewDebug.ExportedProperty(flagMapping = {
3095        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3096                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3097                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3098        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3099                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3100                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3101        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3102                                equals = SYSTEM_UI_FLAG_VISIBLE,
3103                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3104    }, formatToHexString = true)
3105    int mSystemUiVisibility;
3106
3107    /**
3108     * Reference count for transient state.
3109     * @see #setHasTransientState(boolean)
3110     */
3111    int mTransientStateCount = 0;
3112
3113    /**
3114     * Count of how many windows this view has been attached to.
3115     */
3116    int mWindowAttachCount;
3117
3118    /**
3119     * The layout parameters associated with this view and used by the parent
3120     * {@link android.view.ViewGroup} to determine how this view should be
3121     * laid out.
3122     * {@hide}
3123     */
3124    protected ViewGroup.LayoutParams mLayoutParams;
3125
3126    /**
3127     * The view flags hold various views states.
3128     * {@hide}
3129     */
3130    @ViewDebug.ExportedProperty(formatToHexString = true)
3131    int mViewFlags;
3132
3133    static class TransformationInfo {
3134        /**
3135         * The transform matrix for the View. This transform is calculated internally
3136         * based on the translation, rotation, and scale properties.
3137         *
3138         * Do *not* use this variable directly; instead call getMatrix(), which will
3139         * load the value from the View's RenderNode.
3140         */
3141        private final Matrix mMatrix = new Matrix();
3142
3143        /**
3144         * The inverse transform matrix for the View. This transform is calculated
3145         * internally based on the translation, rotation, and scale properties.
3146         *
3147         * Do *not* use this variable directly; instead call getInverseMatrix(),
3148         * which will load the value from the View's RenderNode.
3149         */
3150        private Matrix mInverseMatrix;
3151
3152        /**
3153         * The opacity of the View. This is a value from 0 to 1, where 0 means
3154         * completely transparent and 1 means completely opaque.
3155         */
3156        @ViewDebug.ExportedProperty
3157        float mAlpha = 1f;
3158
3159        /**
3160         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3161         * property only used by transitions, which is composited with the other alpha
3162         * values to calculate the final visual alpha value.
3163         */
3164        float mTransitionAlpha = 1f;
3165    }
3166
3167    TransformationInfo mTransformationInfo;
3168
3169    /**
3170     * Current clip bounds. to which all drawing of this view are constrained.
3171     */
3172    Rect mClipBounds = null;
3173
3174    private boolean mLastIsOpaque;
3175
3176    /**
3177     * The distance in pixels from the left edge of this view's parent
3178     * to the left edge of this view.
3179     * {@hide}
3180     */
3181    @ViewDebug.ExportedProperty(category = "layout")
3182    protected int mLeft;
3183    /**
3184     * The distance in pixels from the left edge of this view's parent
3185     * to the right edge of this view.
3186     * {@hide}
3187     */
3188    @ViewDebug.ExportedProperty(category = "layout")
3189    protected int mRight;
3190    /**
3191     * The distance in pixels from the top edge of this view's parent
3192     * to the top edge of this view.
3193     * {@hide}
3194     */
3195    @ViewDebug.ExportedProperty(category = "layout")
3196    protected int mTop;
3197    /**
3198     * The distance in pixels from the top edge of this view's parent
3199     * to the bottom edge of this view.
3200     * {@hide}
3201     */
3202    @ViewDebug.ExportedProperty(category = "layout")
3203    protected int mBottom;
3204
3205    /**
3206     * The offset, in pixels, by which the content of this view is scrolled
3207     * horizontally.
3208     * {@hide}
3209     */
3210    @ViewDebug.ExportedProperty(category = "scrolling")
3211    protected int mScrollX;
3212    /**
3213     * The offset, in pixels, by which the content of this view is scrolled
3214     * vertically.
3215     * {@hide}
3216     */
3217    @ViewDebug.ExportedProperty(category = "scrolling")
3218    protected int mScrollY;
3219
3220    /**
3221     * The left padding in pixels, that is the distance in pixels between the
3222     * left edge of this view and the left edge of its content.
3223     * {@hide}
3224     */
3225    @ViewDebug.ExportedProperty(category = "padding")
3226    protected int mPaddingLeft = 0;
3227    /**
3228     * The right padding in pixels, that is the distance in pixels between the
3229     * right edge of this view and the right edge of its content.
3230     * {@hide}
3231     */
3232    @ViewDebug.ExportedProperty(category = "padding")
3233    protected int mPaddingRight = 0;
3234    /**
3235     * The top padding in pixels, that is the distance in pixels between the
3236     * top edge of this view and the top edge of its content.
3237     * {@hide}
3238     */
3239    @ViewDebug.ExportedProperty(category = "padding")
3240    protected int mPaddingTop;
3241    /**
3242     * The bottom padding in pixels, that is the distance in pixels between the
3243     * bottom edge of this view and the bottom edge of its content.
3244     * {@hide}
3245     */
3246    @ViewDebug.ExportedProperty(category = "padding")
3247    protected int mPaddingBottom;
3248
3249    /**
3250     * The layout insets in pixels, that is the distance in pixels between the
3251     * visible edges of this view its bounds.
3252     */
3253    private Insets mLayoutInsets;
3254
3255    /**
3256     * Briefly describes the view and is primarily used for accessibility support.
3257     */
3258    private CharSequence mContentDescription;
3259
3260    /**
3261     * Specifies the id of a view for which this view serves as a label for
3262     * accessibility purposes.
3263     */
3264    private int mLabelForId = View.NO_ID;
3265
3266    /**
3267     * Predicate for matching labeled view id with its label for
3268     * accessibility purposes.
3269     */
3270    private MatchLabelForPredicate mMatchLabelForPredicate;
3271
3272    /**
3273     * Specifies a view before which this one is visited in accessibility traversal.
3274     */
3275    private int mAccessibilityTraversalBeforeId = NO_ID;
3276
3277    /**
3278     * Specifies a view after which this one is visited in accessibility traversal.
3279     */
3280    private int mAccessibilityTraversalAfterId = NO_ID;
3281
3282    /**
3283     * Predicate for matching a view by its id.
3284     */
3285    private MatchIdPredicate mMatchIdPredicate;
3286
3287    /**
3288     * Cache the paddingRight set by the user to append to the scrollbar's size.
3289     *
3290     * @hide
3291     */
3292    @ViewDebug.ExportedProperty(category = "padding")
3293    protected int mUserPaddingRight;
3294
3295    /**
3296     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3297     *
3298     * @hide
3299     */
3300    @ViewDebug.ExportedProperty(category = "padding")
3301    protected int mUserPaddingBottom;
3302
3303    /**
3304     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3305     *
3306     * @hide
3307     */
3308    @ViewDebug.ExportedProperty(category = "padding")
3309    protected int mUserPaddingLeft;
3310
3311    /**
3312     * Cache the paddingStart set by the user to append to the scrollbar's size.
3313     *
3314     */
3315    @ViewDebug.ExportedProperty(category = "padding")
3316    int mUserPaddingStart;
3317
3318    /**
3319     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3320     *
3321     */
3322    @ViewDebug.ExportedProperty(category = "padding")
3323    int mUserPaddingEnd;
3324
3325    /**
3326     * Cache initial left padding.
3327     *
3328     * @hide
3329     */
3330    int mUserPaddingLeftInitial;
3331
3332    /**
3333     * Cache initial right padding.
3334     *
3335     * @hide
3336     */
3337    int mUserPaddingRightInitial;
3338
3339    /**
3340     * Default undefined padding
3341     */
3342    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3343
3344    /**
3345     * Cache if a left padding has been defined
3346     */
3347    private boolean mLeftPaddingDefined = false;
3348
3349    /**
3350     * Cache if a right padding has been defined
3351     */
3352    private boolean mRightPaddingDefined = false;
3353
3354    /**
3355     * @hide
3356     */
3357    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3358    /**
3359     * @hide
3360     */
3361    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3362
3363    private LongSparseLongArray mMeasureCache;
3364
3365    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3366    private Drawable mBackground;
3367    private TintInfo mBackgroundTint;
3368
3369    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3370    private ForegroundInfo mForegroundInfo;
3371
3372    private Drawable mScrollIndicatorDrawable;
3373
3374    /**
3375     * RenderNode used for backgrounds.
3376     * <p>
3377     * When non-null and valid, this is expected to contain an up-to-date copy
3378     * of the background drawable. It is cleared on temporary detach, and reset
3379     * on cleanup.
3380     */
3381    private RenderNode mBackgroundRenderNode;
3382
3383    private int mBackgroundResource;
3384    private boolean mBackgroundSizeChanged;
3385
3386    private String mTransitionName;
3387
3388    static class TintInfo {
3389        ColorStateList mTintList;
3390        PorterDuff.Mode mTintMode;
3391        boolean mHasTintMode;
3392        boolean mHasTintList;
3393    }
3394
3395    private static class ForegroundInfo {
3396        private Drawable mDrawable;
3397        private TintInfo mTintInfo;
3398        private int mGravity = Gravity.FILL;
3399        private boolean mInsidePadding = true;
3400        private boolean mBoundsChanged = true;
3401        private final Rect mSelfBounds = new Rect();
3402        private final Rect mOverlayBounds = new Rect();
3403    }
3404
3405    static class ListenerInfo {
3406        /**
3407         * Listener used to dispatch focus change events.
3408         * This field should be made private, so it is hidden from the SDK.
3409         * {@hide}
3410         */
3411        protected OnFocusChangeListener mOnFocusChangeListener;
3412
3413        /**
3414         * Listeners for layout change events.
3415         */
3416        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3417
3418        protected OnScrollChangeListener mOnScrollChangeListener;
3419
3420        /**
3421         * Listeners for attach events.
3422         */
3423        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3424
3425        /**
3426         * Listener used to dispatch click events.
3427         * This field should be made private, so it is hidden from the SDK.
3428         * {@hide}
3429         */
3430        public OnClickListener mOnClickListener;
3431
3432        /**
3433         * Listener used to dispatch long click events.
3434         * This field should be made private, so it is hidden from the SDK.
3435         * {@hide}
3436         */
3437        protected OnLongClickListener mOnLongClickListener;
3438
3439        /**
3440         * Listener used to dispatch context click events. This field should be made private, so it
3441         * is hidden from the SDK.
3442         * {@hide}
3443         */
3444        protected OnContextClickListener mOnContextClickListener;
3445
3446        /**
3447         * Listener used to build the context menu.
3448         * This field should be made private, so it is hidden from the SDK.
3449         * {@hide}
3450         */
3451        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3452
3453        private OnKeyListener mOnKeyListener;
3454
3455        private OnTouchListener mOnTouchListener;
3456
3457        private OnHoverListener mOnHoverListener;
3458
3459        private OnGenericMotionListener mOnGenericMotionListener;
3460
3461        private OnDragListener mOnDragListener;
3462
3463        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3464
3465        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3466    }
3467
3468    ListenerInfo mListenerInfo;
3469
3470    /**
3471     * The application environment this view lives in.
3472     * This field should be made private, so it is hidden from the SDK.
3473     * {@hide}
3474     */
3475    @ViewDebug.ExportedProperty(deepExport = true)
3476    protected Context mContext;
3477
3478    private final Resources mResources;
3479
3480    private ScrollabilityCache mScrollCache;
3481
3482    private int[] mDrawableState = null;
3483
3484    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3485
3486    /**
3487     * Animator that automatically runs based on state changes.
3488     */
3489    private StateListAnimator mStateListAnimator;
3490
3491    /**
3492     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3493     * the user may specify which view to go to next.
3494     */
3495    private int mNextFocusLeftId = View.NO_ID;
3496
3497    /**
3498     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3499     * the user may specify which view to go to next.
3500     */
3501    private int mNextFocusRightId = View.NO_ID;
3502
3503    /**
3504     * When this view has focus and the next focus is {@link #FOCUS_UP},
3505     * the user may specify which view to go to next.
3506     */
3507    private int mNextFocusUpId = View.NO_ID;
3508
3509    /**
3510     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3511     * the user may specify which view to go to next.
3512     */
3513    private int mNextFocusDownId = View.NO_ID;
3514
3515    /**
3516     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3517     * the user may specify which view to go to next.
3518     */
3519    int mNextFocusForwardId = View.NO_ID;
3520
3521    private CheckForLongPress mPendingCheckForLongPress;
3522    private CheckForTap mPendingCheckForTap = null;
3523    private PerformClick mPerformClick;
3524    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3525
3526    private UnsetPressedState mUnsetPressedState;
3527
3528    /**
3529     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3530     * up event while a long press is invoked as soon as the long press duration is reached, so
3531     * a long press could be performed before the tap is checked, in which case the tap's action
3532     * should not be invoked.
3533     */
3534    private boolean mHasPerformedLongPress;
3535
3536    /**
3537     * Whether a context click button is currently pressed down. This is true when the stylus is
3538     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3539     * pressed. This is false once the button is released or if the stylus has been lifted.
3540     */
3541    private boolean mInContextButtonPress;
3542
3543    /**
3544     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3545     * true after a stylus button press has occured, when the next up event should not be recognized
3546     * as a tap.
3547     */
3548    private boolean mIgnoreNextUpEvent;
3549
3550    /**
3551     * The minimum height of the view. We'll try our best to have the height
3552     * of this view to at least this amount.
3553     */
3554    @ViewDebug.ExportedProperty(category = "measurement")
3555    private int mMinHeight;
3556
3557    /**
3558     * The minimum width of the view. We'll try our best to have the width
3559     * of this view to at least this amount.
3560     */
3561    @ViewDebug.ExportedProperty(category = "measurement")
3562    private int mMinWidth;
3563
3564    /**
3565     * The delegate to handle touch events that are physically in this view
3566     * but should be handled by another view.
3567     */
3568    private TouchDelegate mTouchDelegate = null;
3569
3570    /**
3571     * Solid color to use as a background when creating the drawing cache. Enables
3572     * the cache to use 16 bit bitmaps instead of 32 bit.
3573     */
3574    private int mDrawingCacheBackgroundColor = 0;
3575
3576    /**
3577     * Special tree observer used when mAttachInfo is null.
3578     */
3579    private ViewTreeObserver mFloatingTreeObserver;
3580
3581    /**
3582     * Cache the touch slop from the context that created the view.
3583     */
3584    private int mTouchSlop;
3585
3586    /**
3587     * Object that handles automatic animation of view properties.
3588     */
3589    private ViewPropertyAnimator mAnimator = null;
3590
3591    /**
3592     * Flag indicating that a drag can cross window boundaries.  When
3593     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3594     * with this flag set, all visible applications will be able to participate
3595     * in the drag operation and receive the dragged content.
3596     *
3597     * @hide
3598     */
3599    public static final int DRAG_FLAG_GLOBAL = 1;
3600
3601    /**
3602     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3603     */
3604    private float mVerticalScrollFactor;
3605
3606    /**
3607     * Position of the vertical scroll bar.
3608     */
3609    private int mVerticalScrollbarPosition;
3610
3611    /**
3612     * Position the scroll bar at the default position as determined by the system.
3613     */
3614    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3615
3616    /**
3617     * Position the scroll bar along the left edge.
3618     */
3619    public static final int SCROLLBAR_POSITION_LEFT = 1;
3620
3621    /**
3622     * Position the scroll bar along the right edge.
3623     */
3624    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3625
3626    /**
3627     * Indicates that the view does not have a layer.
3628     *
3629     * @see #getLayerType()
3630     * @see #setLayerType(int, android.graphics.Paint)
3631     * @see #LAYER_TYPE_SOFTWARE
3632     * @see #LAYER_TYPE_HARDWARE
3633     */
3634    public static final int LAYER_TYPE_NONE = 0;
3635
3636    /**
3637     * <p>Indicates that the view has a software layer. A software layer is backed
3638     * by a bitmap and causes the view to be rendered using Android's software
3639     * rendering pipeline, even if hardware acceleration is enabled.</p>
3640     *
3641     * <p>Software layers have various usages:</p>
3642     * <p>When the application is not using hardware acceleration, a software layer
3643     * is useful to apply a specific color filter and/or blending mode and/or
3644     * translucency to a view and all its children.</p>
3645     * <p>When the application is using hardware acceleration, a software layer
3646     * is useful to render drawing primitives not supported by the hardware
3647     * accelerated pipeline. It can also be used to cache a complex view tree
3648     * into a texture and reduce the complexity of drawing operations. For instance,
3649     * when animating a complex view tree with a translation, a software layer can
3650     * be used to render the view tree only once.</p>
3651     * <p>Software layers should be avoided when the affected view tree updates
3652     * often. Every update will require to re-render the software layer, which can
3653     * potentially be slow (particularly when hardware acceleration is turned on
3654     * since the layer will have to be uploaded into a hardware texture after every
3655     * update.)</p>
3656     *
3657     * @see #getLayerType()
3658     * @see #setLayerType(int, android.graphics.Paint)
3659     * @see #LAYER_TYPE_NONE
3660     * @see #LAYER_TYPE_HARDWARE
3661     */
3662    public static final int LAYER_TYPE_SOFTWARE = 1;
3663
3664    /**
3665     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3666     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3667     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3668     * rendering pipeline, but only if hardware acceleration is turned on for the
3669     * view hierarchy. When hardware acceleration is turned off, hardware layers
3670     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3671     *
3672     * <p>A hardware layer is useful to apply a specific color filter and/or
3673     * blending mode and/or translucency to a view and all its children.</p>
3674     * <p>A hardware layer can be used to cache a complex view tree into a
3675     * texture and reduce the complexity of drawing operations. For instance,
3676     * when animating a complex view tree with a translation, a hardware layer can
3677     * be used to render the view tree only once.</p>
3678     * <p>A hardware layer can also be used to increase the rendering quality when
3679     * rotation transformations are applied on a view. It can also be used to
3680     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3681     *
3682     * @see #getLayerType()
3683     * @see #setLayerType(int, android.graphics.Paint)
3684     * @see #LAYER_TYPE_NONE
3685     * @see #LAYER_TYPE_SOFTWARE
3686     */
3687    public static final int LAYER_TYPE_HARDWARE = 2;
3688
3689    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3690            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3691            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3692            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3693    })
3694    int mLayerType = LAYER_TYPE_NONE;
3695    Paint mLayerPaint;
3696
3697    /**
3698     * Set to true when drawing cache is enabled and cannot be created.
3699     *
3700     * @hide
3701     */
3702    public boolean mCachingFailed;
3703    private Bitmap mDrawingCache;
3704    private Bitmap mUnscaledDrawingCache;
3705
3706    /**
3707     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3708     * <p>
3709     * When non-null and valid, this is expected to contain an up-to-date copy
3710     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3711     * cleanup.
3712     */
3713    final RenderNode mRenderNode;
3714
3715    /**
3716     * Set to true when the view is sending hover accessibility events because it
3717     * is the innermost hovered view.
3718     */
3719    private boolean mSendingHoverAccessibilityEvents;
3720
3721    /**
3722     * Delegate for injecting accessibility functionality.
3723     */
3724    AccessibilityDelegate mAccessibilityDelegate;
3725
3726    /**
3727     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3728     * and add/remove objects to/from the overlay directly through the Overlay methods.
3729     */
3730    ViewOverlay mOverlay;
3731
3732    /**
3733     * The currently active parent view for receiving delegated nested scrolling events.
3734     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3735     * by {@link #stopNestedScroll()} at the same point where we clear
3736     * requestDisallowInterceptTouchEvent.
3737     */
3738    private ViewParent mNestedScrollingParent;
3739
3740    /**
3741     * Consistency verifier for debugging purposes.
3742     * @hide
3743     */
3744    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3745            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3746                    new InputEventConsistencyVerifier(this, 0) : null;
3747
3748    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3749
3750    private int[] mTempNestedScrollConsumed;
3751
3752    /**
3753     * An overlay is going to draw this View instead of being drawn as part of this
3754     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3755     * when this view is invalidated.
3756     */
3757    GhostView mGhostView;
3758
3759    /**
3760     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3761     * @hide
3762     */
3763    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3764    public String[] mAttributes;
3765
3766    /**
3767     * Maps a Resource id to its name.
3768     */
3769    private static SparseArray<String> mAttributeMap;
3770
3771    /**
3772     * @hide
3773     */
3774    String mStartActivityRequestWho;
3775
3776    /**
3777     * Simple constructor to use when creating a view from code.
3778     *
3779     * @param context The Context the view is running in, through which it can
3780     *        access the current theme, resources, etc.
3781     */
3782    public View(Context context) {
3783        mContext = context;
3784        mResources = context != null ? context.getResources() : null;
3785        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3786        // Set some flags defaults
3787        mPrivateFlags2 =
3788                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3789                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3790                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3791                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3792                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3793                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3794        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3795        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3796        mUserPaddingStart = UNDEFINED_PADDING;
3797        mUserPaddingEnd = UNDEFINED_PADDING;
3798        mRenderNode = RenderNode.create(getClass().getName(), this);
3799
3800        if (!sCompatibilityDone && context != null) {
3801            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3802
3803            // Older apps may need this compatibility hack for measurement.
3804            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3805
3806            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3807            // of whether a layout was requested on that View.
3808            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3809
3810            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3811
3812            // In M and newer, our widgets can pass a "hint" value in the size
3813            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3814            // know what the expected parent size is going to be, so e.g. list items can size
3815            // themselves at 1/3 the size of their container. It breaks older apps though,
3816            // specifically apps that use some popular open source libraries.
3817            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3818
3819            sCompatibilityDone = true;
3820        }
3821    }
3822
3823    /**
3824     * Constructor that is called when inflating a view from XML. This is called
3825     * when a view is being constructed from an XML file, supplying attributes
3826     * that were specified in the XML file. This version uses a default style of
3827     * 0, so the only attribute values applied are those in the Context's Theme
3828     * and the given AttributeSet.
3829     *
3830     * <p>
3831     * The method onFinishInflate() will be called after all children have been
3832     * added.
3833     *
3834     * @param context The Context the view is running in, through which it can
3835     *        access the current theme, resources, etc.
3836     * @param attrs The attributes of the XML tag that is inflating the view.
3837     * @see #View(Context, AttributeSet, int)
3838     */
3839    public View(Context context, @Nullable AttributeSet attrs) {
3840        this(context, attrs, 0);
3841    }
3842
3843    /**
3844     * Perform inflation from XML and apply a class-specific base style from a
3845     * theme attribute. This constructor of View allows subclasses to use their
3846     * own base style when they are inflating. For example, a Button class's
3847     * constructor would call this version of the super class constructor and
3848     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3849     * allows the theme's button style to modify all of the base view attributes
3850     * (in particular its background) as well as the Button class's attributes.
3851     *
3852     * @param context The Context the view is running in, through which it can
3853     *        access the current theme, resources, etc.
3854     * @param attrs The attributes of the XML tag that is inflating the view.
3855     * @param defStyleAttr An attribute in the current theme that contains a
3856     *        reference to a style resource that supplies default values for
3857     *        the view. Can be 0 to not look for defaults.
3858     * @see #View(Context, AttributeSet)
3859     */
3860    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
3861        this(context, attrs, defStyleAttr, 0);
3862    }
3863
3864    /**
3865     * Perform inflation from XML and apply a class-specific base style from a
3866     * theme attribute or style resource. This constructor of View allows
3867     * subclasses to use their own base style when they are inflating.
3868     * <p>
3869     * When determining the final value of a particular attribute, there are
3870     * four inputs that come into play:
3871     * <ol>
3872     * <li>Any attribute values in the given AttributeSet.
3873     * <li>The style resource specified in the AttributeSet (named "style").
3874     * <li>The default style specified by <var>defStyleAttr</var>.
3875     * <li>The default style specified by <var>defStyleRes</var>.
3876     * <li>The base values in this theme.
3877     * </ol>
3878     * <p>
3879     * Each of these inputs is considered in-order, with the first listed taking
3880     * precedence over the following ones. In other words, if in the
3881     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
3882     * , then the button's text will <em>always</em> be black, regardless of
3883     * what is specified in any of the styles.
3884     *
3885     * @param context The Context the view is running in, through which it can
3886     *        access the current theme, resources, etc.
3887     * @param attrs The attributes of the XML tag that is inflating the view.
3888     * @param defStyleAttr An attribute in the current theme that contains a
3889     *        reference to a style resource that supplies default values for
3890     *        the view. Can be 0 to not look for defaults.
3891     * @param defStyleRes A resource identifier of a style resource that
3892     *        supplies default values for the view, used only if
3893     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
3894     *        to not look for defaults.
3895     * @see #View(Context, AttributeSet, int)
3896     */
3897    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
3898        this(context);
3899
3900        final TypedArray a = context.obtainStyledAttributes(
3901                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
3902
3903        if (mDebugViewAttributes) {
3904            saveAttributeData(attrs, a);
3905        }
3906
3907        Drawable background = null;
3908
3909        int leftPadding = -1;
3910        int topPadding = -1;
3911        int rightPadding = -1;
3912        int bottomPadding = -1;
3913        int startPadding = UNDEFINED_PADDING;
3914        int endPadding = UNDEFINED_PADDING;
3915
3916        int padding = -1;
3917
3918        int viewFlagValues = 0;
3919        int viewFlagMasks = 0;
3920
3921        boolean setScrollContainer = false;
3922
3923        int x = 0;
3924        int y = 0;
3925
3926        float tx = 0;
3927        float ty = 0;
3928        float tz = 0;
3929        float elevation = 0;
3930        float rotation = 0;
3931        float rotationX = 0;
3932        float rotationY = 0;
3933        float sx = 1f;
3934        float sy = 1f;
3935        boolean transformSet = false;
3936
3937        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
3938        int overScrollMode = mOverScrollMode;
3939        boolean initializeScrollbars = false;
3940        boolean initializeScrollIndicators = false;
3941
3942        boolean startPaddingDefined = false;
3943        boolean endPaddingDefined = false;
3944        boolean leftPaddingDefined = false;
3945        boolean rightPaddingDefined = false;
3946
3947        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3948
3949        final int N = a.getIndexCount();
3950        for (int i = 0; i < N; i++) {
3951            int attr = a.getIndex(i);
3952            switch (attr) {
3953                case com.android.internal.R.styleable.View_background:
3954                    background = a.getDrawable(attr);
3955                    break;
3956                case com.android.internal.R.styleable.View_padding:
3957                    padding = a.getDimensionPixelSize(attr, -1);
3958                    mUserPaddingLeftInitial = padding;
3959                    mUserPaddingRightInitial = padding;
3960                    leftPaddingDefined = true;
3961                    rightPaddingDefined = true;
3962                    break;
3963                 case com.android.internal.R.styleable.View_paddingLeft:
3964                    leftPadding = a.getDimensionPixelSize(attr, -1);
3965                    mUserPaddingLeftInitial = leftPadding;
3966                    leftPaddingDefined = true;
3967                    break;
3968                case com.android.internal.R.styleable.View_paddingTop:
3969                    topPadding = a.getDimensionPixelSize(attr, -1);
3970                    break;
3971                case com.android.internal.R.styleable.View_paddingRight:
3972                    rightPadding = a.getDimensionPixelSize(attr, -1);
3973                    mUserPaddingRightInitial = rightPadding;
3974                    rightPaddingDefined = true;
3975                    break;
3976                case com.android.internal.R.styleable.View_paddingBottom:
3977                    bottomPadding = a.getDimensionPixelSize(attr, -1);
3978                    break;
3979                case com.android.internal.R.styleable.View_paddingStart:
3980                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3981                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
3982                    break;
3983                case com.android.internal.R.styleable.View_paddingEnd:
3984                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
3985                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
3986                    break;
3987                case com.android.internal.R.styleable.View_scrollX:
3988                    x = a.getDimensionPixelOffset(attr, 0);
3989                    break;
3990                case com.android.internal.R.styleable.View_scrollY:
3991                    y = a.getDimensionPixelOffset(attr, 0);
3992                    break;
3993                case com.android.internal.R.styleable.View_alpha:
3994                    setAlpha(a.getFloat(attr, 1f));
3995                    break;
3996                case com.android.internal.R.styleable.View_transformPivotX:
3997                    setPivotX(a.getDimensionPixelOffset(attr, 0));
3998                    break;
3999                case com.android.internal.R.styleable.View_transformPivotY:
4000                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4001                    break;
4002                case com.android.internal.R.styleable.View_translationX:
4003                    tx = a.getDimensionPixelOffset(attr, 0);
4004                    transformSet = true;
4005                    break;
4006                case com.android.internal.R.styleable.View_translationY:
4007                    ty = a.getDimensionPixelOffset(attr, 0);
4008                    transformSet = true;
4009                    break;
4010                case com.android.internal.R.styleable.View_translationZ:
4011                    tz = a.getDimensionPixelOffset(attr, 0);
4012                    transformSet = true;
4013                    break;
4014                case com.android.internal.R.styleable.View_elevation:
4015                    elevation = a.getDimensionPixelOffset(attr, 0);
4016                    transformSet = true;
4017                    break;
4018                case com.android.internal.R.styleable.View_rotation:
4019                    rotation = a.getFloat(attr, 0);
4020                    transformSet = true;
4021                    break;
4022                case com.android.internal.R.styleable.View_rotationX:
4023                    rotationX = a.getFloat(attr, 0);
4024                    transformSet = true;
4025                    break;
4026                case com.android.internal.R.styleable.View_rotationY:
4027                    rotationY = a.getFloat(attr, 0);
4028                    transformSet = true;
4029                    break;
4030                case com.android.internal.R.styleable.View_scaleX:
4031                    sx = a.getFloat(attr, 1f);
4032                    transformSet = true;
4033                    break;
4034                case com.android.internal.R.styleable.View_scaleY:
4035                    sy = a.getFloat(attr, 1f);
4036                    transformSet = true;
4037                    break;
4038                case com.android.internal.R.styleable.View_id:
4039                    mID = a.getResourceId(attr, NO_ID);
4040                    break;
4041                case com.android.internal.R.styleable.View_tag:
4042                    mTag = a.getText(attr);
4043                    break;
4044                case com.android.internal.R.styleable.View_fitsSystemWindows:
4045                    if (a.getBoolean(attr, false)) {
4046                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4047                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4048                    }
4049                    break;
4050                case com.android.internal.R.styleable.View_focusable:
4051                    if (a.getBoolean(attr, false)) {
4052                        viewFlagValues |= FOCUSABLE;
4053                        viewFlagMasks |= FOCUSABLE_MASK;
4054                    }
4055                    break;
4056                case com.android.internal.R.styleable.View_focusableInTouchMode:
4057                    if (a.getBoolean(attr, false)) {
4058                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4059                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4060                    }
4061                    break;
4062                case com.android.internal.R.styleable.View_clickable:
4063                    if (a.getBoolean(attr, false)) {
4064                        viewFlagValues |= CLICKABLE;
4065                        viewFlagMasks |= CLICKABLE;
4066                    }
4067                    break;
4068                case com.android.internal.R.styleable.View_longClickable:
4069                    if (a.getBoolean(attr, false)) {
4070                        viewFlagValues |= LONG_CLICKABLE;
4071                        viewFlagMasks |= LONG_CLICKABLE;
4072                    }
4073                    break;
4074                case com.android.internal.R.styleable.View_contextClickable:
4075                    if (a.getBoolean(attr, false)) {
4076                        viewFlagValues |= CONTEXT_CLICKABLE;
4077                        viewFlagMasks |= CONTEXT_CLICKABLE;
4078                    }
4079                    break;
4080                case com.android.internal.R.styleable.View_saveEnabled:
4081                    if (!a.getBoolean(attr, true)) {
4082                        viewFlagValues |= SAVE_DISABLED;
4083                        viewFlagMasks |= SAVE_DISABLED_MASK;
4084                    }
4085                    break;
4086                case com.android.internal.R.styleable.View_duplicateParentState:
4087                    if (a.getBoolean(attr, false)) {
4088                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4089                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4090                    }
4091                    break;
4092                case com.android.internal.R.styleable.View_visibility:
4093                    final int visibility = a.getInt(attr, 0);
4094                    if (visibility != 0) {
4095                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4096                        viewFlagMasks |= VISIBILITY_MASK;
4097                    }
4098                    break;
4099                case com.android.internal.R.styleable.View_layoutDirection:
4100                    // Clear any layout direction flags (included resolved bits) already set
4101                    mPrivateFlags2 &=
4102                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4103                    // Set the layout direction flags depending on the value of the attribute
4104                    final int layoutDirection = a.getInt(attr, -1);
4105                    final int value = (layoutDirection != -1) ?
4106                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4107                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4108                    break;
4109                case com.android.internal.R.styleable.View_drawingCacheQuality:
4110                    final int cacheQuality = a.getInt(attr, 0);
4111                    if (cacheQuality != 0) {
4112                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4113                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4114                    }
4115                    break;
4116                case com.android.internal.R.styleable.View_contentDescription:
4117                    setContentDescription(a.getString(attr));
4118                    break;
4119                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4120                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4121                    break;
4122                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4123                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4124                    break;
4125                case com.android.internal.R.styleable.View_labelFor:
4126                    setLabelFor(a.getResourceId(attr, NO_ID));
4127                    break;
4128                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4129                    if (!a.getBoolean(attr, true)) {
4130                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4131                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4132                    }
4133                    break;
4134                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4135                    if (!a.getBoolean(attr, true)) {
4136                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4137                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4138                    }
4139                    break;
4140                case R.styleable.View_scrollbars:
4141                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4142                    if (scrollbars != SCROLLBARS_NONE) {
4143                        viewFlagValues |= scrollbars;
4144                        viewFlagMasks |= SCROLLBARS_MASK;
4145                        initializeScrollbars = true;
4146                    }
4147                    break;
4148                //noinspection deprecation
4149                case R.styleable.View_fadingEdge:
4150                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4151                        // Ignore the attribute starting with ICS
4152                        break;
4153                    }
4154                    // With builds < ICS, fall through and apply fading edges
4155                case R.styleable.View_requiresFadingEdge:
4156                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4157                    if (fadingEdge != FADING_EDGE_NONE) {
4158                        viewFlagValues |= fadingEdge;
4159                        viewFlagMasks |= FADING_EDGE_MASK;
4160                        initializeFadingEdgeInternal(a);
4161                    }
4162                    break;
4163                case R.styleable.View_scrollbarStyle:
4164                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4165                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4166                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4167                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4168                    }
4169                    break;
4170                case R.styleable.View_isScrollContainer:
4171                    setScrollContainer = true;
4172                    if (a.getBoolean(attr, false)) {
4173                        setScrollContainer(true);
4174                    }
4175                    break;
4176                case com.android.internal.R.styleable.View_keepScreenOn:
4177                    if (a.getBoolean(attr, false)) {
4178                        viewFlagValues |= KEEP_SCREEN_ON;
4179                        viewFlagMasks |= KEEP_SCREEN_ON;
4180                    }
4181                    break;
4182                case R.styleable.View_filterTouchesWhenObscured:
4183                    if (a.getBoolean(attr, false)) {
4184                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4185                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4186                    }
4187                    break;
4188                case R.styleable.View_nextFocusLeft:
4189                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4190                    break;
4191                case R.styleable.View_nextFocusRight:
4192                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4193                    break;
4194                case R.styleable.View_nextFocusUp:
4195                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4196                    break;
4197                case R.styleable.View_nextFocusDown:
4198                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4199                    break;
4200                case R.styleable.View_nextFocusForward:
4201                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4202                    break;
4203                case R.styleable.View_minWidth:
4204                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4205                    break;
4206                case R.styleable.View_minHeight:
4207                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4208                    break;
4209                case R.styleable.View_onClick:
4210                    if (context.isRestricted()) {
4211                        throw new IllegalStateException("The android:onClick attribute cannot "
4212                                + "be used within a restricted context");
4213                    }
4214
4215                    final String handlerName = a.getString(attr);
4216                    if (handlerName != null) {
4217                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4218                    }
4219                    break;
4220                case R.styleable.View_overScrollMode:
4221                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4222                    break;
4223                case R.styleable.View_verticalScrollbarPosition:
4224                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4225                    break;
4226                case R.styleable.View_layerType:
4227                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4228                    break;
4229                case R.styleable.View_textDirection:
4230                    // Clear any text direction flag already set
4231                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4232                    // Set the text direction flags depending on the value of the attribute
4233                    final int textDirection = a.getInt(attr, -1);
4234                    if (textDirection != -1) {
4235                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4236                    }
4237                    break;
4238                case R.styleable.View_textAlignment:
4239                    // Clear any text alignment flag already set
4240                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4241                    // Set the text alignment flag depending on the value of the attribute
4242                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4243                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4244                    break;
4245                case R.styleable.View_importantForAccessibility:
4246                    setImportantForAccessibility(a.getInt(attr,
4247                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4248                    break;
4249                case R.styleable.View_accessibilityLiveRegion:
4250                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4251                    break;
4252                case R.styleable.View_transitionName:
4253                    setTransitionName(a.getString(attr));
4254                    break;
4255                case R.styleable.View_nestedScrollingEnabled:
4256                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4257                    break;
4258                case R.styleable.View_stateListAnimator:
4259                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4260                            a.getResourceId(attr, 0)));
4261                    break;
4262                case R.styleable.View_backgroundTint:
4263                    // This will get applied later during setBackground().
4264                    if (mBackgroundTint == null) {
4265                        mBackgroundTint = new TintInfo();
4266                    }
4267                    mBackgroundTint.mTintList = a.getColorStateList(
4268                            R.styleable.View_backgroundTint);
4269                    mBackgroundTint.mHasTintList = true;
4270                    break;
4271                case R.styleable.View_backgroundTintMode:
4272                    // This will get applied later during setBackground().
4273                    if (mBackgroundTint == null) {
4274                        mBackgroundTint = new TintInfo();
4275                    }
4276                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4277                            R.styleable.View_backgroundTintMode, -1), null);
4278                    mBackgroundTint.mHasTintMode = true;
4279                    break;
4280                case R.styleable.View_outlineProvider:
4281                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4282                            PROVIDER_BACKGROUND));
4283                    break;
4284                case R.styleable.View_foreground:
4285                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4286                        setForeground(a.getDrawable(attr));
4287                    }
4288                    break;
4289                case R.styleable.View_foregroundGravity:
4290                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4291                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4292                    }
4293                    break;
4294                case R.styleable.View_foregroundTintMode:
4295                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4296                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4297                    }
4298                    break;
4299                case R.styleable.View_foregroundTint:
4300                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4301                        setForegroundTintList(a.getColorStateList(attr));
4302                    }
4303                    break;
4304                case R.styleable.View_foregroundInsidePadding:
4305                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4306                        if (mForegroundInfo == null) {
4307                            mForegroundInfo = new ForegroundInfo();
4308                        }
4309                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4310                                mForegroundInfo.mInsidePadding);
4311                    }
4312                    break;
4313                case R.styleable.View_scrollIndicators:
4314                    final int scrollIndicators =
4315                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4316                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4317                    if (scrollIndicators != 0) {
4318                        mPrivateFlags3 |= scrollIndicators;
4319                        initializeScrollIndicators = true;
4320                    }
4321                    break;
4322            }
4323        }
4324
4325        setOverScrollMode(overScrollMode);
4326
4327        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4328        // the resolved layout direction). Those cached values will be used later during padding
4329        // resolution.
4330        mUserPaddingStart = startPadding;
4331        mUserPaddingEnd = endPadding;
4332
4333        if (background != null) {
4334            setBackground(background);
4335        }
4336
4337        // setBackground above will record that padding is currently provided by the background.
4338        // If we have padding specified via xml, record that here instead and use it.
4339        mLeftPaddingDefined = leftPaddingDefined;
4340        mRightPaddingDefined = rightPaddingDefined;
4341
4342        if (padding >= 0) {
4343            leftPadding = padding;
4344            topPadding = padding;
4345            rightPadding = padding;
4346            bottomPadding = padding;
4347            mUserPaddingLeftInitial = padding;
4348            mUserPaddingRightInitial = padding;
4349        }
4350
4351        if (isRtlCompatibilityMode()) {
4352            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4353            // left / right padding are used if defined (meaning here nothing to do). If they are not
4354            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4355            // start / end and resolve them as left / right (layout direction is not taken into account).
4356            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4357            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4358            // defined.
4359            if (!mLeftPaddingDefined && startPaddingDefined) {
4360                leftPadding = startPadding;
4361            }
4362            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4363            if (!mRightPaddingDefined && endPaddingDefined) {
4364                rightPadding = endPadding;
4365            }
4366            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4367        } else {
4368            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4369            // values defined. Otherwise, left /right values are used.
4370            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4371            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4372            // defined.
4373            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4374
4375            if (mLeftPaddingDefined && !hasRelativePadding) {
4376                mUserPaddingLeftInitial = leftPadding;
4377            }
4378            if (mRightPaddingDefined && !hasRelativePadding) {
4379                mUserPaddingRightInitial = rightPadding;
4380            }
4381        }
4382
4383        internalSetPadding(
4384                mUserPaddingLeftInitial,
4385                topPadding >= 0 ? topPadding : mPaddingTop,
4386                mUserPaddingRightInitial,
4387                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4388
4389        if (viewFlagMasks != 0) {
4390            setFlags(viewFlagValues, viewFlagMasks);
4391        }
4392
4393        if (initializeScrollbars) {
4394            initializeScrollbarsInternal(a);
4395        }
4396
4397        if (initializeScrollIndicators) {
4398            initializeScrollIndicatorsInternal();
4399        }
4400
4401        a.recycle();
4402
4403        // Needs to be called after mViewFlags is set
4404        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4405            recomputePadding();
4406        }
4407
4408        if (x != 0 || y != 0) {
4409            scrollTo(x, y);
4410        }
4411
4412        if (transformSet) {
4413            setTranslationX(tx);
4414            setTranslationY(ty);
4415            setTranslationZ(tz);
4416            setElevation(elevation);
4417            setRotation(rotation);
4418            setRotationX(rotationX);
4419            setRotationY(rotationY);
4420            setScaleX(sx);
4421            setScaleY(sy);
4422        }
4423
4424        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4425            setScrollContainer(true);
4426        }
4427
4428        computeOpaqueFlags();
4429    }
4430
4431    /**
4432     * An implementation of OnClickListener that attempts to lazily load a
4433     * named click handling method from a parent or ancestor context.
4434     */
4435    private static class DeclaredOnClickListener implements OnClickListener {
4436        private final View mHostView;
4437        private final String mMethodName;
4438
4439        private Method mMethod;
4440
4441        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4442            mHostView = hostView;
4443            mMethodName = methodName;
4444        }
4445
4446        @Override
4447        public void onClick(@NonNull View v) {
4448            if (mMethod == null) {
4449                mMethod = resolveMethod(mHostView.getContext(), mMethodName);
4450            }
4451
4452            try {
4453                mMethod.invoke(mHostView.getContext(), v);
4454            } catch (IllegalAccessException e) {
4455                throw new IllegalStateException(
4456                        "Could not execute non-public method for android:onClick", e);
4457            } catch (InvocationTargetException e) {
4458                throw new IllegalStateException(
4459                        "Could not execute method for android:onClick", e);
4460            }
4461        }
4462
4463        @NonNull
4464        private Method resolveMethod(@Nullable Context context, @NonNull String name) {
4465            while (context != null) {
4466                try {
4467                    if (!context.isRestricted()) {
4468                        return context.getClass().getMethod(mMethodName, View.class);
4469                    }
4470                } catch (NoSuchMethodException e) {
4471                    // Failed to find method, keep searching up the hierarchy.
4472                }
4473
4474                if (context instanceof ContextWrapper) {
4475                    context = ((ContextWrapper) context).getBaseContext();
4476                } else {
4477                    // Can't search up the hierarchy, null out and fail.
4478                    context = null;
4479                }
4480            }
4481
4482            final int id = mHostView.getId();
4483            final String idText = id == NO_ID ? "" : " with id '"
4484                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4485            throw new IllegalStateException("Could not find method " + mMethodName
4486                    + "(View) in a parent or ancestor Context for android:onClick "
4487                    + "attribute defined on view " + mHostView.getClass() + idText);
4488        }
4489    }
4490
4491    /**
4492     * Non-public constructor for use in testing
4493     */
4494    View() {
4495        mResources = null;
4496        mRenderNode = RenderNode.create(getClass().getName(), this);
4497    }
4498
4499    private static SparseArray<String> getAttributeMap() {
4500        if (mAttributeMap == null) {
4501            mAttributeMap = new SparseArray<>();
4502        }
4503        return mAttributeMap;
4504    }
4505
4506    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4507        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4508        final int indexCount = t.getIndexCount();
4509        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4510
4511        int i = 0;
4512
4513        // Store raw XML attributes.
4514        for (int j = 0; j < attrsCount; ++j) {
4515            attributes[i] = attrs.getAttributeName(j);
4516            attributes[i + 1] = attrs.getAttributeValue(j);
4517            i += 2;
4518        }
4519
4520        // Store resolved styleable attributes.
4521        final Resources res = t.getResources();
4522        final SparseArray<String> attributeMap = getAttributeMap();
4523        for (int j = 0; j < indexCount; ++j) {
4524            final int index = t.getIndex(j);
4525            if (!t.hasValueOrEmpty(index)) {
4526                // Value is undefined. Skip it.
4527                continue;
4528            }
4529
4530            final int resourceId = t.getResourceId(index, 0);
4531            if (resourceId == 0) {
4532                // Value is not a reference. Skip it.
4533                continue;
4534            }
4535
4536            String resourceName = attributeMap.get(resourceId);
4537            if (resourceName == null) {
4538                try {
4539                    resourceName = res.getResourceName(resourceId);
4540                } catch (Resources.NotFoundException e) {
4541                    resourceName = "0x" + Integer.toHexString(resourceId);
4542                }
4543                attributeMap.put(resourceId, resourceName);
4544            }
4545
4546            attributes[i] = resourceName;
4547            attributes[i + 1] = t.getString(index);
4548            i += 2;
4549        }
4550
4551        // Trim to fit contents.
4552        final String[] trimmed = new String[i];
4553        System.arraycopy(attributes, 0, trimmed, 0, i);
4554        mAttributes = trimmed;
4555    }
4556
4557    public String toString() {
4558        StringBuilder out = new StringBuilder(128);
4559        out.append(getClass().getName());
4560        out.append('{');
4561        out.append(Integer.toHexString(System.identityHashCode(this)));
4562        out.append(' ');
4563        switch (mViewFlags&VISIBILITY_MASK) {
4564            case VISIBLE: out.append('V'); break;
4565            case INVISIBLE: out.append('I'); break;
4566            case GONE: out.append('G'); break;
4567            default: out.append('.'); break;
4568        }
4569        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4570        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4571        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4572        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4573        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4574        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4575        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4576        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4577        out.append(' ');
4578        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4579        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4580        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4581        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4582            out.append('p');
4583        } else {
4584            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4585        }
4586        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4587        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4588        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4589        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4590        out.append(' ');
4591        out.append(mLeft);
4592        out.append(',');
4593        out.append(mTop);
4594        out.append('-');
4595        out.append(mRight);
4596        out.append(',');
4597        out.append(mBottom);
4598        final int id = getId();
4599        if (id != NO_ID) {
4600            out.append(" #");
4601            out.append(Integer.toHexString(id));
4602            final Resources r = mResources;
4603            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4604                try {
4605                    String pkgname;
4606                    switch (id&0xff000000) {
4607                        case 0x7f000000:
4608                            pkgname="app";
4609                            break;
4610                        case 0x01000000:
4611                            pkgname="android";
4612                            break;
4613                        default:
4614                            pkgname = r.getResourcePackageName(id);
4615                            break;
4616                    }
4617                    String typename = r.getResourceTypeName(id);
4618                    String entryname = r.getResourceEntryName(id);
4619                    out.append(" ");
4620                    out.append(pkgname);
4621                    out.append(":");
4622                    out.append(typename);
4623                    out.append("/");
4624                    out.append(entryname);
4625                } catch (Resources.NotFoundException e) {
4626                }
4627            }
4628        }
4629        out.append("}");
4630        return out.toString();
4631    }
4632
4633    /**
4634     * <p>
4635     * Initializes the fading edges from a given set of styled attributes. This
4636     * method should be called by subclasses that need fading edges and when an
4637     * instance of these subclasses is created programmatically rather than
4638     * being inflated from XML. This method is automatically called when the XML
4639     * is inflated.
4640     * </p>
4641     *
4642     * @param a the styled attributes set to initialize the fading edges from
4643     *
4644     * @removed
4645     */
4646    protected void initializeFadingEdge(TypedArray a) {
4647        // This method probably shouldn't have been included in the SDK to begin with.
4648        // It relies on 'a' having been initialized using an attribute filter array that is
4649        // not publicly available to the SDK. The old method has been renamed
4650        // to initializeFadingEdgeInternal and hidden for framework use only;
4651        // this one initializes using defaults to make it safe to call for apps.
4652
4653        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4654
4655        initializeFadingEdgeInternal(arr);
4656
4657        arr.recycle();
4658    }
4659
4660    /**
4661     * <p>
4662     * Initializes the fading edges from a given set of styled attributes. This
4663     * method should be called by subclasses that need fading edges and when an
4664     * instance of these subclasses is created programmatically rather than
4665     * being inflated from XML. This method is automatically called when the XML
4666     * is inflated.
4667     * </p>
4668     *
4669     * @param a the styled attributes set to initialize the fading edges from
4670     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4671     */
4672    protected void initializeFadingEdgeInternal(TypedArray a) {
4673        initScrollCache();
4674
4675        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4676                R.styleable.View_fadingEdgeLength,
4677                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4678    }
4679
4680    /**
4681     * Returns the size of the vertical faded edges used to indicate that more
4682     * content in this view is visible.
4683     *
4684     * @return The size in pixels of the vertical faded edge or 0 if vertical
4685     *         faded edges are not enabled for this view.
4686     * @attr ref android.R.styleable#View_fadingEdgeLength
4687     */
4688    public int getVerticalFadingEdgeLength() {
4689        if (isVerticalFadingEdgeEnabled()) {
4690            ScrollabilityCache cache = mScrollCache;
4691            if (cache != null) {
4692                return cache.fadingEdgeLength;
4693            }
4694        }
4695        return 0;
4696    }
4697
4698    /**
4699     * Set the size of the faded edge used to indicate that more content in this
4700     * view is available.  Will not change whether the fading edge is enabled; use
4701     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4702     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4703     * for the vertical or horizontal fading edges.
4704     *
4705     * @param length The size in pixels of the faded edge used to indicate that more
4706     *        content in this view is visible.
4707     */
4708    public void setFadingEdgeLength(int length) {
4709        initScrollCache();
4710        mScrollCache.fadingEdgeLength = length;
4711    }
4712
4713    /**
4714     * Returns the size of the horizontal faded edges used to indicate that more
4715     * content in this view is visible.
4716     *
4717     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4718     *         faded edges are not enabled for this view.
4719     * @attr ref android.R.styleable#View_fadingEdgeLength
4720     */
4721    public int getHorizontalFadingEdgeLength() {
4722        if (isHorizontalFadingEdgeEnabled()) {
4723            ScrollabilityCache cache = mScrollCache;
4724            if (cache != null) {
4725                return cache.fadingEdgeLength;
4726            }
4727        }
4728        return 0;
4729    }
4730
4731    /**
4732     * Returns the width of the vertical scrollbar.
4733     *
4734     * @return The width in pixels of the vertical scrollbar or 0 if there
4735     *         is no vertical scrollbar.
4736     */
4737    public int getVerticalScrollbarWidth() {
4738        ScrollabilityCache cache = mScrollCache;
4739        if (cache != null) {
4740            ScrollBarDrawable scrollBar = cache.scrollBar;
4741            if (scrollBar != null) {
4742                int size = scrollBar.getSize(true);
4743                if (size <= 0) {
4744                    size = cache.scrollBarSize;
4745                }
4746                return size;
4747            }
4748            return 0;
4749        }
4750        return 0;
4751    }
4752
4753    /**
4754     * Returns the height of the horizontal scrollbar.
4755     *
4756     * @return The height in pixels of the horizontal scrollbar or 0 if
4757     *         there is no horizontal scrollbar.
4758     */
4759    protected int getHorizontalScrollbarHeight() {
4760        ScrollabilityCache cache = mScrollCache;
4761        if (cache != null) {
4762            ScrollBarDrawable scrollBar = cache.scrollBar;
4763            if (scrollBar != null) {
4764                int size = scrollBar.getSize(false);
4765                if (size <= 0) {
4766                    size = cache.scrollBarSize;
4767                }
4768                return size;
4769            }
4770            return 0;
4771        }
4772        return 0;
4773    }
4774
4775    /**
4776     * <p>
4777     * Initializes the scrollbars from a given set of styled attributes. This
4778     * method should be called by subclasses that need scrollbars and when an
4779     * instance of these subclasses is created programmatically rather than
4780     * being inflated from XML. This method is automatically called when the XML
4781     * is inflated.
4782     * </p>
4783     *
4784     * @param a the styled attributes set to initialize the scrollbars from
4785     *
4786     * @removed
4787     */
4788    protected void initializeScrollbars(TypedArray a) {
4789        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4790        // using the View filter array which is not available to the SDK. As such, internal
4791        // framework usage now uses initializeScrollbarsInternal and we grab a default
4792        // TypedArray with the right filter instead here.
4793        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4794
4795        initializeScrollbarsInternal(arr);
4796
4797        // We ignored the method parameter. Recycle the one we actually did use.
4798        arr.recycle();
4799    }
4800
4801    /**
4802     * <p>
4803     * Initializes the scrollbars from a given set of styled attributes. This
4804     * method should be called by subclasses that need scrollbars and when an
4805     * instance of these subclasses is created programmatically rather than
4806     * being inflated from XML. This method is automatically called when the XML
4807     * is inflated.
4808     * </p>
4809     *
4810     * @param a the styled attributes set to initialize the scrollbars from
4811     * @hide
4812     */
4813    protected void initializeScrollbarsInternal(TypedArray a) {
4814        initScrollCache();
4815
4816        final ScrollabilityCache scrollabilityCache = mScrollCache;
4817
4818        if (scrollabilityCache.scrollBar == null) {
4819            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4820            scrollabilityCache.scrollBar.setCallback(this);
4821            scrollabilityCache.scrollBar.setState(getDrawableState());
4822        }
4823
4824        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4825
4826        if (!fadeScrollbars) {
4827            scrollabilityCache.state = ScrollabilityCache.ON;
4828        }
4829        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4830
4831
4832        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4833                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4834                        .getScrollBarFadeDuration());
4835        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4836                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4837                ViewConfiguration.getScrollDefaultDelay());
4838
4839
4840        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4841                com.android.internal.R.styleable.View_scrollbarSize,
4842                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4843
4844        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4845        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4846
4847        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4848        if (thumb != null) {
4849            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4850        }
4851
4852        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
4853                false);
4854        if (alwaysDraw) {
4855            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
4856        }
4857
4858        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
4859        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
4860
4861        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
4862        if (thumb != null) {
4863            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
4864        }
4865
4866        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
4867                false);
4868        if (alwaysDraw) {
4869            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
4870        }
4871
4872        // Apply layout direction to the new Drawables if needed
4873        final int layoutDirection = getLayoutDirection();
4874        if (track != null) {
4875            track.setLayoutDirection(layoutDirection);
4876        }
4877        if (thumb != null) {
4878            thumb.setLayoutDirection(layoutDirection);
4879        }
4880
4881        // Re-apply user/background padding so that scrollbar(s) get added
4882        resolvePadding();
4883    }
4884
4885    private void initializeScrollIndicatorsInternal() {
4886        // Some day maybe we'll break this into top/left/start/etc. and let the
4887        // client control it. Until then, you can have any scroll indicator you
4888        // want as long as it's a 1dp foreground-colored rectangle.
4889        if (mScrollIndicatorDrawable == null) {
4890            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
4891        }
4892    }
4893
4894    /**
4895     * <p>
4896     * Initalizes the scrollability cache if necessary.
4897     * </p>
4898     */
4899    private void initScrollCache() {
4900        if (mScrollCache == null) {
4901            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
4902        }
4903    }
4904
4905    private ScrollabilityCache getScrollCache() {
4906        initScrollCache();
4907        return mScrollCache;
4908    }
4909
4910    /**
4911     * Set the position of the vertical scroll bar. Should be one of
4912     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
4913     * {@link #SCROLLBAR_POSITION_RIGHT}.
4914     *
4915     * @param position Where the vertical scroll bar should be positioned.
4916     */
4917    public void setVerticalScrollbarPosition(int position) {
4918        if (mVerticalScrollbarPosition != position) {
4919            mVerticalScrollbarPosition = position;
4920            computeOpaqueFlags();
4921            resolvePadding();
4922        }
4923    }
4924
4925    /**
4926     * @return The position where the vertical scroll bar will show, if applicable.
4927     * @see #setVerticalScrollbarPosition(int)
4928     */
4929    public int getVerticalScrollbarPosition() {
4930        return mVerticalScrollbarPosition;
4931    }
4932
4933    /**
4934     * Sets the state of all scroll indicators.
4935     * <p>
4936     * See {@link #setScrollIndicators(int, int)} for usage information.
4937     *
4938     * @param indicators a bitmask of indicators that should be enabled, or
4939     *                   {@code 0} to disable all indicators
4940     * @see #setScrollIndicators(int, int)
4941     * @see #getScrollIndicators()
4942     * @attr ref android.R.styleable#View_scrollIndicators
4943     */
4944    public void setScrollIndicators(@ScrollIndicators int indicators) {
4945        setScrollIndicators(indicators,
4946                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
4947    }
4948
4949    /**
4950     * Sets the state of the scroll indicators specified by the mask. To change
4951     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
4952     * <p>
4953     * When a scroll indicator is enabled, it will be displayed if the view
4954     * can scroll in the direction of the indicator.
4955     * <p>
4956     * Multiple indicator types may be enabled or disabled by passing the
4957     * logical OR of the desired types. If multiple types are specified, they
4958     * will all be set to the same enabled state.
4959     * <p>
4960     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
4961     *
4962     * @param indicators the indicator direction, or the logical OR of multiple
4963     *             indicator directions. One or more of:
4964     *             <ul>
4965     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
4966     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
4967     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
4968     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
4969     *               <li>{@link #SCROLL_INDICATOR_START}</li>
4970     *               <li>{@link #SCROLL_INDICATOR_END}</li>
4971     *             </ul>
4972     * @see #setScrollIndicators(int)
4973     * @see #getScrollIndicators()
4974     * @attr ref android.R.styleable#View_scrollIndicators
4975     */
4976    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
4977        // Shift and sanitize mask.
4978        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4979        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
4980
4981        // Shift and mask indicators.
4982        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
4983        indicators &= mask;
4984
4985        // Merge with non-masked flags.
4986        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
4987
4988        if (mPrivateFlags3 != updatedFlags) {
4989            mPrivateFlags3 = updatedFlags;
4990
4991            if (indicators != 0) {
4992                initializeScrollIndicatorsInternal();
4993            }
4994            invalidate();
4995        }
4996    }
4997
4998    /**
4999     * Returns a bitmask representing the enabled scroll indicators.
5000     * <p>
5001     * For example, if the top and left scroll indicators are enabled and all
5002     * other indicators are disabled, the return value will be
5003     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5004     * <p>
5005     * To check whether the bottom scroll indicator is enabled, use the value
5006     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5007     *
5008     * @return a bitmask representing the enabled scroll indicators
5009     */
5010    @ScrollIndicators
5011    public int getScrollIndicators() {
5012        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5013                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5014    }
5015
5016    ListenerInfo getListenerInfo() {
5017        if (mListenerInfo != null) {
5018            return mListenerInfo;
5019        }
5020        mListenerInfo = new ListenerInfo();
5021        return mListenerInfo;
5022    }
5023
5024    /**
5025     * Register a callback to be invoked when the scroll X or Y positions of
5026     * this view change.
5027     * <p>
5028     * <b>Note:</b> Some views handle scrolling independently from View and may
5029     * have their own separate listeners for scroll-type events. For example,
5030     * {@link android.widget.ListView ListView} allows clients to register an
5031     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5032     * to listen for changes in list scroll position.
5033     *
5034     * @param l The listener to notify when the scroll X or Y position changes.
5035     * @see android.view.View#getScrollX()
5036     * @see android.view.View#getScrollY()
5037     */
5038    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5039        getListenerInfo().mOnScrollChangeListener = l;
5040    }
5041
5042    /**
5043     * Register a callback to be invoked when focus of this view changed.
5044     *
5045     * @param l The callback that will run.
5046     */
5047    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5048        getListenerInfo().mOnFocusChangeListener = l;
5049    }
5050
5051    /**
5052     * Add a listener that will be called when the bounds of the view change due to
5053     * layout processing.
5054     *
5055     * @param listener The listener that will be called when layout bounds change.
5056     */
5057    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5058        ListenerInfo li = getListenerInfo();
5059        if (li.mOnLayoutChangeListeners == null) {
5060            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5061        }
5062        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5063            li.mOnLayoutChangeListeners.add(listener);
5064        }
5065    }
5066
5067    /**
5068     * Remove a listener for layout changes.
5069     *
5070     * @param listener The listener for layout bounds change.
5071     */
5072    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5073        ListenerInfo li = mListenerInfo;
5074        if (li == null || li.mOnLayoutChangeListeners == null) {
5075            return;
5076        }
5077        li.mOnLayoutChangeListeners.remove(listener);
5078    }
5079
5080    /**
5081     * Add a listener for attach state changes.
5082     *
5083     * This listener will be called whenever this view is attached or detached
5084     * from a window. Remove the listener using
5085     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5086     *
5087     * @param listener Listener to attach
5088     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5089     */
5090    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5091        ListenerInfo li = getListenerInfo();
5092        if (li.mOnAttachStateChangeListeners == null) {
5093            li.mOnAttachStateChangeListeners
5094                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5095        }
5096        li.mOnAttachStateChangeListeners.add(listener);
5097    }
5098
5099    /**
5100     * Remove a listener for attach state changes. The listener will receive no further
5101     * notification of window attach/detach events.
5102     *
5103     * @param listener Listener to remove
5104     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5105     */
5106    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5107        ListenerInfo li = mListenerInfo;
5108        if (li == null || li.mOnAttachStateChangeListeners == null) {
5109            return;
5110        }
5111        li.mOnAttachStateChangeListeners.remove(listener);
5112    }
5113
5114    /**
5115     * Returns the focus-change callback registered for this view.
5116     *
5117     * @return The callback, or null if one is not registered.
5118     */
5119    public OnFocusChangeListener getOnFocusChangeListener() {
5120        ListenerInfo li = mListenerInfo;
5121        return li != null ? li.mOnFocusChangeListener : null;
5122    }
5123
5124    /**
5125     * Register a callback to be invoked when this view is clicked. If this view is not
5126     * clickable, it becomes clickable.
5127     *
5128     * @param l The callback that will run
5129     *
5130     * @see #setClickable(boolean)
5131     */
5132    public void setOnClickListener(@Nullable OnClickListener l) {
5133        if (!isClickable()) {
5134            setClickable(true);
5135        }
5136        getListenerInfo().mOnClickListener = l;
5137    }
5138
5139    /**
5140     * Return whether this view has an attached OnClickListener.  Returns
5141     * true if there is a listener, false if there is none.
5142     */
5143    public boolean hasOnClickListeners() {
5144        ListenerInfo li = mListenerInfo;
5145        return (li != null && li.mOnClickListener != null);
5146    }
5147
5148    /**
5149     * Register a callback to be invoked when this view is clicked and held. If this view is not
5150     * long clickable, it becomes long clickable.
5151     *
5152     * @param l The callback that will run
5153     *
5154     * @see #setLongClickable(boolean)
5155     */
5156    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5157        if (!isLongClickable()) {
5158            setLongClickable(true);
5159        }
5160        getListenerInfo().mOnLongClickListener = l;
5161    }
5162
5163    /**
5164     * Register a callback to be invoked when this view is context clicked. If the view is not
5165     * context clickable, it becomes context clickable.
5166     *
5167     * @param l The callback that will run
5168     * @see #setContextClickable(boolean)
5169     */
5170    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5171        if (!isContextClickable()) {
5172            setContextClickable(true);
5173        }
5174        getListenerInfo().mOnContextClickListener = l;
5175    }
5176
5177    /**
5178     * Register a callback to be invoked when the context menu for this view is
5179     * being built. If this view is not long clickable, it becomes long clickable.
5180     *
5181     * @param l The callback that will run
5182     *
5183     */
5184    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5185        if (!isLongClickable()) {
5186            setLongClickable(true);
5187        }
5188        getListenerInfo().mOnCreateContextMenuListener = l;
5189    }
5190
5191    /**
5192     * Call this view's OnClickListener, if it is defined.  Performs all normal
5193     * actions associated with clicking: reporting accessibility event, playing
5194     * a sound, etc.
5195     *
5196     * @return True there was an assigned OnClickListener that was called, false
5197     *         otherwise is returned.
5198     */
5199    public boolean performClick() {
5200        final boolean result;
5201        final ListenerInfo li = mListenerInfo;
5202        if (li != null && li.mOnClickListener != null) {
5203            playSoundEffect(SoundEffectConstants.CLICK);
5204            li.mOnClickListener.onClick(this);
5205            result = true;
5206        } else {
5207            result = false;
5208        }
5209
5210        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5211        return result;
5212    }
5213
5214    /**
5215     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5216     * this only calls the listener, and does not do any associated clicking
5217     * actions like reporting an accessibility event.
5218     *
5219     * @return True there was an assigned OnClickListener that was called, false
5220     *         otherwise is returned.
5221     */
5222    public boolean callOnClick() {
5223        ListenerInfo li = mListenerInfo;
5224        if (li != null && li.mOnClickListener != null) {
5225            li.mOnClickListener.onClick(this);
5226            return true;
5227        }
5228        return false;
5229    }
5230
5231    /**
5232     * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
5233     * OnLongClickListener did not consume the event.
5234     *
5235     * @return True if one of the above receivers consumed the event, false otherwise.
5236     */
5237    public boolean performLongClick() {
5238        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5239
5240        boolean handled = false;
5241        ListenerInfo li = mListenerInfo;
5242        if (li != null && li.mOnLongClickListener != null) {
5243            handled = li.mOnLongClickListener.onLongClick(View.this);
5244        }
5245        if (!handled) {
5246            handled = showContextMenu();
5247        }
5248        if (handled) {
5249            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5250        }
5251        return handled;
5252    }
5253
5254    /**
5255     * Call this view's OnContextClickListener, if it is defined.
5256     *
5257     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5258     *         otherwise.
5259     */
5260    public boolean performContextClick() {
5261        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5262
5263        boolean handled = false;
5264        ListenerInfo li = mListenerInfo;
5265        if (li != null && li.mOnContextClickListener != null) {
5266            handled = li.mOnContextClickListener.onContextClick(View.this);
5267        }
5268        if (handled) {
5269            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5270        }
5271        return handled;
5272    }
5273
5274    /**
5275     * Performs button-related actions during a touch down event.
5276     *
5277     * @param event The event.
5278     * @return True if the down was consumed.
5279     *
5280     * @hide
5281     */
5282    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5283        if (event.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
5284            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5285            showContextMenu(event.getX(), event.getY(), event.getMetaState());
5286            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5287            return true;
5288        }
5289        return false;
5290    }
5291
5292    /**
5293     * Bring up the context menu for this view.
5294     *
5295     * @return Whether a context menu was displayed.
5296     */
5297    public boolean showContextMenu() {
5298        return getParent().showContextMenuForChild(this);
5299    }
5300
5301    /**
5302     * Bring up the context menu for this view, referring to the item under the specified point.
5303     *
5304     * @param x The referenced x coordinate.
5305     * @param y The referenced y coordinate.
5306     * @param metaState The keyboard modifiers that were pressed.
5307     * @return Whether a context menu was displayed.
5308     *
5309     * @hide
5310     */
5311    public boolean showContextMenu(float x, float y, int metaState) {
5312        return showContextMenu();
5313    }
5314
5315    /**
5316     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5317     *
5318     * @param callback Callback that will control the lifecycle of the action mode
5319     * @return The new action mode if it is started, null otherwise
5320     *
5321     * @see ActionMode
5322     * @see #startActionMode(android.view.ActionMode.Callback, int)
5323     */
5324    public ActionMode startActionMode(ActionMode.Callback callback) {
5325        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5326    }
5327
5328    /**
5329     * Start an action mode with the given type.
5330     *
5331     * @param callback Callback that will control the lifecycle of the action mode
5332     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5333     * @return The new action mode if it is started, null otherwise
5334     *
5335     * @see ActionMode
5336     */
5337    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5338        ViewParent parent = getParent();
5339        if (parent == null) return null;
5340        try {
5341            return parent.startActionModeForChild(this, callback, type);
5342        } catch (AbstractMethodError ame) {
5343            // Older implementations of custom views might not implement this.
5344            return parent.startActionModeForChild(this, callback);
5345        }
5346    }
5347
5348    /**
5349     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5350     * Context, creating a unique View identifier to retrieve the result.
5351     *
5352     * @param intent The Intent to be started.
5353     * @param requestCode The request code to use.
5354     * @hide
5355     */
5356    public void startActivityForResult(Intent intent, int requestCode) {
5357        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5358        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5359    }
5360
5361    /**
5362     * If this View corresponds to the calling who, dispatches the activity result.
5363     * @param who The identifier for the targeted View to receive the result.
5364     * @param requestCode The integer request code originally supplied to
5365     *                    startActivityForResult(), allowing you to identify who this
5366     *                    result came from.
5367     * @param resultCode The integer result code returned by the child activity
5368     *                   through its setResult().
5369     * @param data An Intent, which can return result data to the caller
5370     *               (various data can be attached to Intent "extras").
5371     * @return {@code true} if the activity result was dispatched.
5372     * @hide
5373     */
5374    public boolean dispatchActivityResult(
5375            String who, int requestCode, int resultCode, Intent data) {
5376        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5377            onActivityResult(requestCode, resultCode, data);
5378            mStartActivityRequestWho = null;
5379            return true;
5380        }
5381        return false;
5382    }
5383
5384    /**
5385     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5386     *
5387     * @param requestCode The integer request code originally supplied to
5388     *                    startActivityForResult(), allowing you to identify who this
5389     *                    result came from.
5390     * @param resultCode The integer result code returned by the child activity
5391     *                   through its setResult().
5392     * @param data An Intent, which can return result data to the caller
5393     *               (various data can be attached to Intent "extras").
5394     * @hide
5395     */
5396    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5397        // Do nothing.
5398    }
5399
5400    /**
5401     * Register a callback to be invoked when a hardware key is pressed in this view.
5402     * Key presses in software input methods will generally not trigger the methods of
5403     * this listener.
5404     * @param l the key listener to attach to this view
5405     */
5406    public void setOnKeyListener(OnKeyListener l) {
5407        getListenerInfo().mOnKeyListener = l;
5408    }
5409
5410    /**
5411     * Register a callback to be invoked when a touch event is sent to this view.
5412     * @param l the touch listener to attach to this view
5413     */
5414    public void setOnTouchListener(OnTouchListener l) {
5415        getListenerInfo().mOnTouchListener = l;
5416    }
5417
5418    /**
5419     * Register a callback to be invoked when a generic motion event is sent to this view.
5420     * @param l the generic motion listener to attach to this view
5421     */
5422    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5423        getListenerInfo().mOnGenericMotionListener = l;
5424    }
5425
5426    /**
5427     * Register a callback to be invoked when a hover event is sent to this view.
5428     * @param l the hover listener to attach to this view
5429     */
5430    public void setOnHoverListener(OnHoverListener l) {
5431        getListenerInfo().mOnHoverListener = l;
5432    }
5433
5434    /**
5435     * Register a drag event listener callback object for this View. The parameter is
5436     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5437     * View, the system calls the
5438     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5439     * @param l An implementation of {@link android.view.View.OnDragListener}.
5440     */
5441    public void setOnDragListener(OnDragListener l) {
5442        getListenerInfo().mOnDragListener = l;
5443    }
5444
5445    /**
5446     * Give this view focus. This will cause
5447     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5448     *
5449     * Note: this does not check whether this {@link View} should get focus, it just
5450     * gives it focus no matter what.  It should only be called internally by framework
5451     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5452     *
5453     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5454     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5455     *        focus moved when requestFocus() is called. It may not always
5456     *        apply, in which case use the default View.FOCUS_DOWN.
5457     * @param previouslyFocusedRect The rectangle of the view that had focus
5458     *        prior in this View's coordinate system.
5459     */
5460    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5461        if (DBG) {
5462            System.out.println(this + " requestFocus()");
5463        }
5464
5465        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5466            mPrivateFlags |= PFLAG_FOCUSED;
5467
5468            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5469
5470            if (mParent != null) {
5471                mParent.requestChildFocus(this, this);
5472            }
5473
5474            if (mAttachInfo != null) {
5475                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5476            }
5477
5478            onFocusChanged(true, direction, previouslyFocusedRect);
5479            refreshDrawableState();
5480        }
5481    }
5482
5483    /**
5484     * Populates <code>outRect</code> with the hotspot bounds. By default,
5485     * the hotspot bounds are identical to the screen bounds.
5486     *
5487     * @param outRect rect to populate with hotspot bounds
5488     * @hide Only for internal use by views and widgets.
5489     */
5490    public void getHotspotBounds(Rect outRect) {
5491        final Drawable background = getBackground();
5492        if (background != null) {
5493            background.getHotspotBounds(outRect);
5494        } else {
5495            getBoundsOnScreen(outRect);
5496        }
5497    }
5498
5499    /**
5500     * Request that a rectangle of this view be visible on the screen,
5501     * scrolling if necessary just enough.
5502     *
5503     * <p>A View should call this if it maintains some notion of which part
5504     * of its content is interesting.  For example, a text editing view
5505     * should call this when its cursor moves.
5506     *
5507     * @param rectangle The rectangle.
5508     * @return Whether any parent scrolled.
5509     */
5510    public boolean requestRectangleOnScreen(Rect rectangle) {
5511        return requestRectangleOnScreen(rectangle, false);
5512    }
5513
5514    /**
5515     * Request that a rectangle of this view be visible on the screen,
5516     * scrolling if necessary just enough.
5517     *
5518     * <p>A View should call this if it maintains some notion of which part
5519     * of its content is interesting.  For example, a text editing view
5520     * should call this when its cursor moves.
5521     *
5522     * <p>When <code>immediate</code> is set to true, scrolling will not be
5523     * animated.
5524     *
5525     * @param rectangle The rectangle.
5526     * @param immediate True to forbid animated scrolling, false otherwise
5527     * @return Whether any parent scrolled.
5528     */
5529    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5530        if (mParent == null) {
5531            return false;
5532        }
5533
5534        View child = this;
5535
5536        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5537        position.set(rectangle);
5538
5539        ViewParent parent = mParent;
5540        boolean scrolled = false;
5541        while (parent != null) {
5542            rectangle.set((int) position.left, (int) position.top,
5543                    (int) position.right, (int) position.bottom);
5544
5545            scrolled |= parent.requestChildRectangleOnScreen(child,
5546                    rectangle, immediate);
5547
5548            if (!child.hasIdentityMatrix()) {
5549                child.getMatrix().mapRect(position);
5550            }
5551
5552            position.offset(child.mLeft, child.mTop);
5553
5554            if (!(parent instanceof View)) {
5555                break;
5556            }
5557
5558            View parentView = (View) parent;
5559
5560            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5561
5562            child = parentView;
5563            parent = child.getParent();
5564        }
5565
5566        return scrolled;
5567    }
5568
5569    /**
5570     * Called when this view wants to give up focus. If focus is cleared
5571     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5572     * <p>
5573     * <strong>Note:</strong> When a View clears focus the framework is trying
5574     * to give focus to the first focusable View from the top. Hence, if this
5575     * View is the first from the top that can take focus, then all callbacks
5576     * related to clearing focus will be invoked after which the framework will
5577     * give focus to this view.
5578     * </p>
5579     */
5580    public void clearFocus() {
5581        if (DBG) {
5582            System.out.println(this + " clearFocus()");
5583        }
5584
5585        clearFocusInternal(null, true, true);
5586    }
5587
5588    /**
5589     * Clears focus from the view, optionally propagating the change up through
5590     * the parent hierarchy and requesting that the root view place new focus.
5591     *
5592     * @param propagate whether to propagate the change up through the parent
5593     *            hierarchy
5594     * @param refocus when propagate is true, specifies whether to request the
5595     *            root view place new focus
5596     */
5597    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5598        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5599            mPrivateFlags &= ~PFLAG_FOCUSED;
5600
5601            if (propagate && mParent != null) {
5602                mParent.clearChildFocus(this);
5603            }
5604
5605            onFocusChanged(false, 0, null);
5606            refreshDrawableState();
5607
5608            if (propagate && (!refocus || !rootViewRequestFocus())) {
5609                notifyGlobalFocusCleared(this);
5610            }
5611        }
5612    }
5613
5614    void notifyGlobalFocusCleared(View oldFocus) {
5615        if (oldFocus != null && mAttachInfo != null) {
5616            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5617        }
5618    }
5619
5620    boolean rootViewRequestFocus() {
5621        final View root = getRootView();
5622        return root != null && root.requestFocus();
5623    }
5624
5625    /**
5626     * Called internally by the view system when a new view is getting focus.
5627     * This is what clears the old focus.
5628     * <p>
5629     * <b>NOTE:</b> The parent view's focused child must be updated manually
5630     * after calling this method. Otherwise, the view hierarchy may be left in
5631     * an inconstent state.
5632     */
5633    void unFocus(View focused) {
5634        if (DBG) {
5635            System.out.println(this + " unFocus()");
5636        }
5637
5638        clearFocusInternal(focused, false, false);
5639    }
5640
5641    /**
5642     * Returns true if this view has focus itself, or is the ancestor of the
5643     * view that has focus.
5644     *
5645     * @return True if this view has or contains focus, false otherwise.
5646     */
5647    @ViewDebug.ExportedProperty(category = "focus")
5648    public boolean hasFocus() {
5649        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5650    }
5651
5652    /**
5653     * Returns true if this view is focusable or if it contains a reachable View
5654     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5655     * is a View whose parents do not block descendants focus.
5656     *
5657     * Only {@link #VISIBLE} views are considered focusable.
5658     *
5659     * @return True if the view is focusable or if the view contains a focusable
5660     *         View, false otherwise.
5661     *
5662     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5663     * @see ViewGroup#getTouchscreenBlocksFocus()
5664     */
5665    public boolean hasFocusable() {
5666        if (!isFocusableInTouchMode()) {
5667            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5668                final ViewGroup g = (ViewGroup) p;
5669                if (g.shouldBlockFocusForTouchscreen()) {
5670                    return false;
5671                }
5672            }
5673        }
5674        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5675    }
5676
5677    /**
5678     * Called by the view system when the focus state of this view changes.
5679     * When the focus change event is caused by directional navigation, direction
5680     * and previouslyFocusedRect provide insight into where the focus is coming from.
5681     * When overriding, be sure to call up through to the super class so that
5682     * the standard focus handling will occur.
5683     *
5684     * @param gainFocus True if the View has focus; false otherwise.
5685     * @param direction The direction focus has moved when requestFocus()
5686     *                  is called to give this view focus. Values are
5687     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5688     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5689     *                  It may not always apply, in which case use the default.
5690     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5691     *        system, of the previously focused view.  If applicable, this will be
5692     *        passed in as finer grained information about where the focus is coming
5693     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5694     */
5695    @CallSuper
5696    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5697            @Nullable Rect previouslyFocusedRect) {
5698        if (gainFocus) {
5699            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5700        } else {
5701            notifyViewAccessibilityStateChangedIfNeeded(
5702                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5703        }
5704
5705        InputMethodManager imm = InputMethodManager.peekInstance();
5706        if (!gainFocus) {
5707            if (isPressed()) {
5708                setPressed(false);
5709            }
5710            if (imm != null && mAttachInfo != null
5711                    && mAttachInfo.mHasWindowFocus) {
5712                imm.focusOut(this);
5713            }
5714            onFocusLost();
5715        } else if (imm != null && mAttachInfo != null
5716                && mAttachInfo.mHasWindowFocus) {
5717            imm.focusIn(this);
5718        }
5719
5720        invalidate(true);
5721        ListenerInfo li = mListenerInfo;
5722        if (li != null && li.mOnFocusChangeListener != null) {
5723            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5724        }
5725
5726        if (mAttachInfo != null) {
5727            mAttachInfo.mKeyDispatchState.reset(this);
5728        }
5729    }
5730
5731    /**
5732     * Sends an accessibility event of the given type. If accessibility is
5733     * not enabled this method has no effect. The default implementation calls
5734     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5735     * to populate information about the event source (this View), then calls
5736     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5737     * populate the text content of the event source including its descendants,
5738     * and last calls
5739     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5740     * on its parent to request sending of the event to interested parties.
5741     * <p>
5742     * If an {@link AccessibilityDelegate} has been specified via calling
5743     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5744     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5745     * responsible for handling this call.
5746     * </p>
5747     *
5748     * @param eventType The type of the event to send, as defined by several types from
5749     * {@link android.view.accessibility.AccessibilityEvent}, such as
5750     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5751     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5752     *
5753     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5754     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5755     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5756     * @see AccessibilityDelegate
5757     */
5758    public void sendAccessibilityEvent(int eventType) {
5759        if (mAccessibilityDelegate != null) {
5760            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5761        } else {
5762            sendAccessibilityEventInternal(eventType);
5763        }
5764    }
5765
5766    /**
5767     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5768     * {@link AccessibilityEvent} to make an announcement which is related to some
5769     * sort of a context change for which none of the events representing UI transitions
5770     * is a good fit. For example, announcing a new page in a book. If accessibility
5771     * is not enabled this method does nothing.
5772     *
5773     * @param text The announcement text.
5774     */
5775    public void announceForAccessibility(CharSequence text) {
5776        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5777            AccessibilityEvent event = AccessibilityEvent.obtain(
5778                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5779            onInitializeAccessibilityEvent(event);
5780            event.getText().add(text);
5781            event.setContentDescription(null);
5782            mParent.requestSendAccessibilityEvent(this, event);
5783        }
5784    }
5785
5786    /**
5787     * @see #sendAccessibilityEvent(int)
5788     *
5789     * Note: Called from the default {@link AccessibilityDelegate}.
5790     *
5791     * @hide
5792     */
5793    public void sendAccessibilityEventInternal(int eventType) {
5794        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5795            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5796        }
5797    }
5798
5799    /**
5800     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5801     * takes as an argument an empty {@link AccessibilityEvent} and does not
5802     * perform a check whether accessibility is enabled.
5803     * <p>
5804     * If an {@link AccessibilityDelegate} has been specified via calling
5805     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5806     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5807     * is responsible for handling this call.
5808     * </p>
5809     *
5810     * @param event The event to send.
5811     *
5812     * @see #sendAccessibilityEvent(int)
5813     */
5814    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5815        if (mAccessibilityDelegate != null) {
5816            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
5817        } else {
5818            sendAccessibilityEventUncheckedInternal(event);
5819        }
5820    }
5821
5822    /**
5823     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
5824     *
5825     * Note: Called from the default {@link AccessibilityDelegate}.
5826     *
5827     * @hide
5828     */
5829    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
5830        if (!isShown()) {
5831            return;
5832        }
5833        onInitializeAccessibilityEvent(event);
5834        // Only a subset of accessibility events populates text content.
5835        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
5836            dispatchPopulateAccessibilityEvent(event);
5837        }
5838        // In the beginning we called #isShown(), so we know that getParent() is not null.
5839        getParent().requestSendAccessibilityEvent(this, event);
5840    }
5841
5842    /**
5843     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
5844     * to its children for adding their text content to the event. Note that the
5845     * event text is populated in a separate dispatch path since we add to the
5846     * event not only the text of the source but also the text of all its descendants.
5847     * A typical implementation will call
5848     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
5849     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5850     * on each child. Override this method if custom population of the event text
5851     * content is required.
5852     * <p>
5853     * If an {@link AccessibilityDelegate} has been specified via calling
5854     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5855     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
5856     * is responsible for handling this call.
5857     * </p>
5858     * <p>
5859     * <em>Note:</em> Accessibility events of certain types are not dispatched for
5860     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
5861     * </p>
5862     *
5863     * @param event The event.
5864     *
5865     * @return True if the event population was completed.
5866     */
5867    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
5868        if (mAccessibilityDelegate != null) {
5869            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
5870        } else {
5871            return dispatchPopulateAccessibilityEventInternal(event);
5872        }
5873    }
5874
5875    /**
5876     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5877     *
5878     * Note: Called from the default {@link AccessibilityDelegate}.
5879     *
5880     * @hide
5881     */
5882    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5883        onPopulateAccessibilityEvent(event);
5884        return false;
5885    }
5886
5887    /**
5888     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
5889     * giving a chance to this View to populate the accessibility event with its
5890     * text content. While this method is free to modify event
5891     * attributes other than text content, doing so should normally be performed in
5892     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
5893     * <p>
5894     * Example: Adding formatted date string to an accessibility event in addition
5895     *          to the text added by the super implementation:
5896     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5897     *     super.onPopulateAccessibilityEvent(event);
5898     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
5899     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
5900     *         mCurrentDate.getTimeInMillis(), flags);
5901     *     event.getText().add(selectedDateUtterance);
5902     * }</pre>
5903     * <p>
5904     * If an {@link AccessibilityDelegate} has been specified via calling
5905     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5906     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
5907     * is responsible for handling this call.
5908     * </p>
5909     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5910     * information to the event, in case the default implementation has basic information to add.
5911     * </p>
5912     *
5913     * @param event The accessibility event which to populate.
5914     *
5915     * @see #sendAccessibilityEvent(int)
5916     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5917     */
5918    @CallSuper
5919    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
5920        if (mAccessibilityDelegate != null) {
5921            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
5922        } else {
5923            onPopulateAccessibilityEventInternal(event);
5924        }
5925    }
5926
5927    /**
5928     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
5929     *
5930     * Note: Called from the default {@link AccessibilityDelegate}.
5931     *
5932     * @hide
5933     */
5934    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
5935    }
5936
5937    /**
5938     * Initializes an {@link AccessibilityEvent} with information about
5939     * this View which is the event source. In other words, the source of
5940     * an accessibility event is the view whose state change triggered firing
5941     * the event.
5942     * <p>
5943     * Example: Setting the password property of an event in addition
5944     *          to properties set by the super implementation:
5945     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5946     *     super.onInitializeAccessibilityEvent(event);
5947     *     event.setPassword(true);
5948     * }</pre>
5949     * <p>
5950     * If an {@link AccessibilityDelegate} has been specified via calling
5951     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5952     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
5953     * is responsible for handling this call.
5954     * </p>
5955     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
5956     * information to the event, in case the default implementation has basic information to add.
5957     * </p>
5958     * @param event The event to initialize.
5959     *
5960     * @see #sendAccessibilityEvent(int)
5961     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5962     */
5963    @CallSuper
5964    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
5965        if (mAccessibilityDelegate != null) {
5966            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
5967        } else {
5968            onInitializeAccessibilityEventInternal(event);
5969        }
5970    }
5971
5972    /**
5973     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5974     *
5975     * Note: Called from the default {@link AccessibilityDelegate}.
5976     *
5977     * @hide
5978     */
5979    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
5980        event.setSource(this);
5981        event.setClassName(getAccessibilityClassName());
5982        event.setPackageName(getContext().getPackageName());
5983        event.setEnabled(isEnabled());
5984        event.setContentDescription(mContentDescription);
5985
5986        switch (event.getEventType()) {
5987            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
5988                ArrayList<View> focusablesTempList = (mAttachInfo != null)
5989                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
5990                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
5991                event.setItemCount(focusablesTempList.size());
5992                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
5993                if (mAttachInfo != null) {
5994                    focusablesTempList.clear();
5995                }
5996            } break;
5997            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
5998                CharSequence text = getIterableTextForAccessibility();
5999                if (text != null && text.length() > 0) {
6000                    event.setFromIndex(getAccessibilitySelectionStart());
6001                    event.setToIndex(getAccessibilitySelectionEnd());
6002                    event.setItemCount(text.length());
6003                }
6004            } break;
6005        }
6006    }
6007
6008    /**
6009     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6010     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6011     * This method is responsible for obtaining an accessibility node info from a
6012     * pool of reusable instances and calling
6013     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6014     * initialize the former.
6015     * <p>
6016     * Note: The client is responsible for recycling the obtained instance by calling
6017     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6018     * </p>
6019     *
6020     * @return A populated {@link AccessibilityNodeInfo}.
6021     *
6022     * @see AccessibilityNodeInfo
6023     */
6024    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6025        if (mAccessibilityDelegate != null) {
6026            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6027        } else {
6028            return createAccessibilityNodeInfoInternal();
6029        }
6030    }
6031
6032    /**
6033     * @see #createAccessibilityNodeInfo()
6034     *
6035     * @hide
6036     */
6037    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6038        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6039        if (provider != null) {
6040            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6041        } else {
6042            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6043            onInitializeAccessibilityNodeInfo(info);
6044            return info;
6045        }
6046    }
6047
6048    /**
6049     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6050     * The base implementation sets:
6051     * <ul>
6052     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6053     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6054     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6055     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6056     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6057     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6058     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6059     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6060     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6061     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6062     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6063     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6064     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6065     * </ul>
6066     * <p>
6067     * Subclasses should override this method, call the super implementation,
6068     * and set additional attributes.
6069     * </p>
6070     * <p>
6071     * If an {@link AccessibilityDelegate} has been specified via calling
6072     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6073     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6074     * is responsible for handling this call.
6075     * </p>
6076     *
6077     * @param info The instance to initialize.
6078     */
6079    @CallSuper
6080    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6081        if (mAccessibilityDelegate != null) {
6082            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6083        } else {
6084            onInitializeAccessibilityNodeInfoInternal(info);
6085        }
6086    }
6087
6088    /**
6089     * Gets the location of this view in screen coordinates.
6090     *
6091     * @param outRect The output location
6092     * @hide
6093     */
6094    public void getBoundsOnScreen(Rect outRect) {
6095        getBoundsOnScreen(outRect, false);
6096    }
6097
6098    /**
6099     * Gets the location of this view in screen coordinates.
6100     *
6101     * @param outRect The output location
6102     * @param clipToParent Whether to clip child bounds to the parent ones.
6103     * @hide
6104     */
6105    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6106        if (mAttachInfo == null) {
6107            return;
6108        }
6109
6110        RectF position = mAttachInfo.mTmpTransformRect;
6111        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6112
6113        if (!hasIdentityMatrix()) {
6114            getMatrix().mapRect(position);
6115        }
6116
6117        position.offset(mLeft, mTop);
6118
6119        ViewParent parent = mParent;
6120        while (parent instanceof View) {
6121            View parentView = (View) parent;
6122
6123            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6124
6125            if (clipToParent) {
6126                position.left = Math.max(position.left, 0);
6127                position.top = Math.max(position.top, 0);
6128                position.right = Math.min(position.right, parentView.getWidth());
6129                position.bottom = Math.min(position.bottom, parentView.getHeight());
6130            }
6131
6132            if (!parentView.hasIdentityMatrix()) {
6133                parentView.getMatrix().mapRect(position);
6134            }
6135
6136            position.offset(parentView.mLeft, parentView.mTop);
6137
6138            parent = parentView.mParent;
6139        }
6140
6141        if (parent instanceof ViewRootImpl) {
6142            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6143            position.offset(0, -viewRootImpl.mCurScrollY);
6144        }
6145
6146        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6147
6148        outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
6149                (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
6150    }
6151
6152    /**
6153     * Return the class name of this object to be used for accessibility purposes.
6154     * Subclasses should only override this if they are implementing something that
6155     * should be seen as a completely new class of view when used by accessibility,
6156     * unrelated to the class it is deriving from.  This is used to fill in
6157     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6158     */
6159    public CharSequence getAccessibilityClassName() {
6160        return View.class.getName();
6161    }
6162
6163    /**
6164     * Called when assist structure is being retrieved from a view as part of
6165     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6166     * @param structure Fill in with structured view data.  The default implementation
6167     * fills in all data that can be inferred from the view itself.
6168     */
6169    public void onProvideStructure(ViewStructure structure) {
6170        final int id = mID;
6171        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6172                && (id&0x0000ffff) != 0) {
6173            String pkg, type, entry;
6174            try {
6175                final Resources res = getResources();
6176                entry = res.getResourceEntryName(id);
6177                type = res.getResourceTypeName(id);
6178                pkg = res.getResourcePackageName(id);
6179            } catch (Resources.NotFoundException e) {
6180                entry = type = pkg = null;
6181            }
6182            structure.setId(id, pkg, type, entry);
6183        } else {
6184            structure.setId(id, null, null, null);
6185        }
6186        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6187        if (!hasIdentityMatrix()) {
6188            structure.setTransformation(getMatrix());
6189        }
6190        structure.setElevation(getZ());
6191        structure.setVisibility(getVisibility());
6192        structure.setEnabled(isEnabled());
6193        if (isClickable()) {
6194            structure.setClickable(true);
6195        }
6196        if (isFocusable()) {
6197            structure.setFocusable(true);
6198        }
6199        if (isFocused()) {
6200            structure.setFocused(true);
6201        }
6202        if (isAccessibilityFocused()) {
6203            structure.setAccessibilityFocused(true);
6204        }
6205        if (isSelected()) {
6206            structure.setSelected(true);
6207        }
6208        if (isActivated()) {
6209            structure.setActivated(true);
6210        }
6211        if (isLongClickable()) {
6212            structure.setLongClickable(true);
6213        }
6214        if (this instanceof Checkable) {
6215            structure.setCheckable(true);
6216            if (((Checkable)this).isChecked()) {
6217                structure.setChecked(true);
6218            }
6219        }
6220        if (isContextClickable()) {
6221            structure.setContextClickable(true);
6222        }
6223        structure.setClassName(getAccessibilityClassName().toString());
6224        structure.setContentDescription(getContentDescription());
6225    }
6226
6227    /**
6228     * Called when assist structure is being retrieved from a view as part of
6229     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6230     * generate additional virtual structure under this view.  The defaullt implementation
6231     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6232     * view's virtual accessibility nodes, if any.  You can override this for a more
6233     * optimal implementation providing this data.
6234     */
6235    public void onProvideVirtualStructure(ViewStructure structure) {
6236        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6237        if (provider != null) {
6238            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6239            structure.setChildCount(1);
6240            ViewStructure root = structure.newChild(0);
6241            populateVirtualStructure(root, provider, info);
6242            info.recycle();
6243        }
6244    }
6245
6246    private void populateVirtualStructure(ViewStructure structure,
6247            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6248        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6249                null, null, null);
6250        Rect rect = structure.getTempRect();
6251        info.getBoundsInParent(rect);
6252        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6253        structure.setVisibility(VISIBLE);
6254        structure.setEnabled(info.isEnabled());
6255        if (info.isClickable()) {
6256            structure.setClickable(true);
6257        }
6258        if (info.isFocusable()) {
6259            structure.setFocusable(true);
6260        }
6261        if (info.isFocused()) {
6262            structure.setFocused(true);
6263        }
6264        if (info.isAccessibilityFocused()) {
6265            structure.setAccessibilityFocused(true);
6266        }
6267        if (info.isSelected()) {
6268            structure.setSelected(true);
6269        }
6270        if (info.isLongClickable()) {
6271            structure.setLongClickable(true);
6272        }
6273        if (info.isCheckable()) {
6274            structure.setCheckable(true);
6275            if (info.isChecked()) {
6276                structure.setChecked(true);
6277            }
6278        }
6279        if (info.isContextClickable()) {
6280            structure.setContextClickable(true);
6281        }
6282        CharSequence cname = info.getClassName();
6283        structure.setClassName(cname != null ? cname.toString() : null);
6284        structure.setContentDescription(info.getContentDescription());
6285        if (info.getText() != null || info.getError() != null) {
6286            structure.setText(info.getText(), info.getTextSelectionStart(),
6287                    info.getTextSelectionEnd());
6288        }
6289        final int NCHILDREN = info.getChildCount();
6290        if (NCHILDREN > 0) {
6291            structure.setChildCount(NCHILDREN);
6292            for (int i=0; i<NCHILDREN; i++) {
6293                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6294                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6295                ViewStructure child = structure.newChild(i);
6296                populateVirtualStructure(child, provider, cinfo);
6297                cinfo.recycle();
6298            }
6299        }
6300    }
6301
6302    /**
6303     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6304     * implementation calls {@link #onProvideStructure} and
6305     * {@link #onProvideVirtualStructure}.
6306     */
6307    public void dispatchProvideStructure(ViewStructure structure) {
6308        if (!isAssistBlocked()) {
6309            onProvideStructure(structure);
6310            onProvideVirtualStructure(structure);
6311        } else {
6312            structure.setClassName(getAccessibilityClassName().toString());
6313            structure.setAssistBlocked(true);
6314        }
6315    }
6316
6317    /**
6318     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6319     *
6320     * Note: Called from the default {@link AccessibilityDelegate}.
6321     *
6322     * @hide
6323     */
6324    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6325        if (mAttachInfo == null) {
6326            return;
6327        }
6328
6329        Rect bounds = mAttachInfo.mTmpInvalRect;
6330
6331        getDrawingRect(bounds);
6332        info.setBoundsInParent(bounds);
6333
6334        getBoundsOnScreen(bounds, true);
6335        info.setBoundsInScreen(bounds);
6336
6337        ViewParent parent = getParentForAccessibility();
6338        if (parent instanceof View) {
6339            info.setParent((View) parent);
6340        }
6341
6342        if (mID != View.NO_ID) {
6343            View rootView = getRootView();
6344            if (rootView == null) {
6345                rootView = this;
6346            }
6347
6348            View label = rootView.findLabelForView(this, mID);
6349            if (label != null) {
6350                info.setLabeledBy(label);
6351            }
6352
6353            if ((mAttachInfo.mAccessibilityFetchFlags
6354                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6355                    && Resources.resourceHasPackage(mID)) {
6356                try {
6357                    String viewId = getResources().getResourceName(mID);
6358                    info.setViewIdResourceName(viewId);
6359                } catch (Resources.NotFoundException nfe) {
6360                    /* ignore */
6361                }
6362            }
6363        }
6364
6365        if (mLabelForId != View.NO_ID) {
6366            View rootView = getRootView();
6367            if (rootView == null) {
6368                rootView = this;
6369            }
6370            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6371            if (labeled != null) {
6372                info.setLabelFor(labeled);
6373            }
6374        }
6375
6376        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6377            View rootView = getRootView();
6378            if (rootView == null) {
6379                rootView = this;
6380            }
6381            View next = rootView.findViewInsideOutShouldExist(this,
6382                    mAccessibilityTraversalBeforeId);
6383            if (next != null && next.includeForAccessibility()) {
6384                info.setTraversalBefore(next);
6385            }
6386        }
6387
6388        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6389            View rootView = getRootView();
6390            if (rootView == null) {
6391                rootView = this;
6392            }
6393            View next = rootView.findViewInsideOutShouldExist(this,
6394                    mAccessibilityTraversalAfterId);
6395            if (next != null && next.includeForAccessibility()) {
6396                info.setTraversalAfter(next);
6397            }
6398        }
6399
6400        info.setVisibleToUser(isVisibleToUser());
6401
6402        info.setPackageName(mContext.getPackageName());
6403        info.setClassName(getAccessibilityClassName());
6404        info.setContentDescription(getContentDescription());
6405
6406        info.setEnabled(isEnabled());
6407        info.setClickable(isClickable());
6408        info.setFocusable(isFocusable());
6409        info.setFocused(isFocused());
6410        info.setAccessibilityFocused(isAccessibilityFocused());
6411        info.setSelected(isSelected());
6412        info.setLongClickable(isLongClickable());
6413        info.setContextClickable(isContextClickable());
6414        info.setLiveRegion(getAccessibilityLiveRegion());
6415
6416        // TODO: These make sense only if we are in an AdapterView but all
6417        // views can be selected. Maybe from accessibility perspective
6418        // we should report as selectable view in an AdapterView.
6419        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6420        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6421
6422        if (isFocusable()) {
6423            if (isFocused()) {
6424                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6425            } else {
6426                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6427            }
6428        }
6429
6430        if (!isAccessibilityFocused()) {
6431            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6432        } else {
6433            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6434        }
6435
6436        if (isClickable() && isEnabled()) {
6437            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6438        }
6439
6440        if (isLongClickable() && isEnabled()) {
6441            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6442        }
6443
6444        if (isContextClickable() && isEnabled()) {
6445            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6446        }
6447
6448        CharSequence text = getIterableTextForAccessibility();
6449        if (text != null && text.length() > 0) {
6450            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6451
6452            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6453            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6454            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6455            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6456                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6457                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6458        }
6459
6460        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6461    }
6462
6463    private View findLabelForView(View view, int labeledId) {
6464        if (mMatchLabelForPredicate == null) {
6465            mMatchLabelForPredicate = new MatchLabelForPredicate();
6466        }
6467        mMatchLabelForPredicate.mLabeledId = labeledId;
6468        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6469    }
6470
6471    /**
6472     * Computes whether this view is visible to the user. Such a view is
6473     * attached, visible, all its predecessors are visible, it is not clipped
6474     * entirely by its predecessors, and has an alpha greater than zero.
6475     *
6476     * @return Whether the view is visible on the screen.
6477     *
6478     * @hide
6479     */
6480    protected boolean isVisibleToUser() {
6481        return isVisibleToUser(null);
6482    }
6483
6484    /**
6485     * Computes whether the given portion of this view is visible to the user.
6486     * Such a view is attached, visible, all its predecessors are visible,
6487     * has an alpha greater than zero, and the specified portion is not
6488     * clipped entirely by its predecessors.
6489     *
6490     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6491     *                    <code>null</code>, and the entire view will be tested in this case.
6492     *                    When <code>true</code> is returned by the function, the actual visible
6493     *                    region will be stored in this parameter; that is, if boundInView is fully
6494     *                    contained within the view, no modification will be made, otherwise regions
6495     *                    outside of the visible area of the view will be clipped.
6496     *
6497     * @return Whether the specified portion of the view is visible on the screen.
6498     *
6499     * @hide
6500     */
6501    protected boolean isVisibleToUser(Rect boundInView) {
6502        if (mAttachInfo != null) {
6503            // Attached to invisible window means this view is not visible.
6504            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6505                return false;
6506            }
6507            // An invisible predecessor or one with alpha zero means
6508            // that this view is not visible to the user.
6509            Object current = this;
6510            while (current instanceof View) {
6511                View view = (View) current;
6512                // We have attach info so this view is attached and there is no
6513                // need to check whether we reach to ViewRootImpl on the way up.
6514                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6515                        view.getVisibility() != VISIBLE) {
6516                    return false;
6517                }
6518                current = view.mParent;
6519            }
6520            // Check if the view is entirely covered by its predecessors.
6521            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6522            Point offset = mAttachInfo.mPoint;
6523            if (!getGlobalVisibleRect(visibleRect, offset)) {
6524                return false;
6525            }
6526            // Check if the visible portion intersects the rectangle of interest.
6527            if (boundInView != null) {
6528                visibleRect.offset(-offset.x, -offset.y);
6529                return boundInView.intersect(visibleRect);
6530            }
6531            return true;
6532        }
6533        return false;
6534    }
6535
6536    /**
6537     * Returns the delegate for implementing accessibility support via
6538     * composition. For more details see {@link AccessibilityDelegate}.
6539     *
6540     * @return The delegate, or null if none set.
6541     *
6542     * @hide
6543     */
6544    public AccessibilityDelegate getAccessibilityDelegate() {
6545        return mAccessibilityDelegate;
6546    }
6547
6548    /**
6549     * Sets a delegate for implementing accessibility support via composition as
6550     * opposed to inheritance. The delegate's primary use is for implementing
6551     * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
6552     *
6553     * @param delegate The delegate instance.
6554     *
6555     * @see AccessibilityDelegate
6556     */
6557    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6558        mAccessibilityDelegate = delegate;
6559    }
6560
6561    /**
6562     * Gets the provider for managing a virtual view hierarchy rooted at this View
6563     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6564     * that explore the window content.
6565     * <p>
6566     * If this method returns an instance, this instance is responsible for managing
6567     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6568     * View including the one representing the View itself. Similarly the returned
6569     * instance is responsible for performing accessibility actions on any virtual
6570     * view or the root view itself.
6571     * </p>
6572     * <p>
6573     * If an {@link AccessibilityDelegate} has been specified via calling
6574     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6575     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6576     * is responsible for handling this call.
6577     * </p>
6578     *
6579     * @return The provider.
6580     *
6581     * @see AccessibilityNodeProvider
6582     */
6583    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6584        if (mAccessibilityDelegate != null) {
6585            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6586        } else {
6587            return null;
6588        }
6589    }
6590
6591    /**
6592     * Gets the unique identifier of this view on the screen for accessibility purposes.
6593     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6594     *
6595     * @return The view accessibility id.
6596     *
6597     * @hide
6598     */
6599    public int getAccessibilityViewId() {
6600        if (mAccessibilityViewId == NO_ID) {
6601            mAccessibilityViewId = sNextAccessibilityViewId++;
6602        }
6603        return mAccessibilityViewId;
6604    }
6605
6606    /**
6607     * Gets the unique identifier of the window in which this View reseides.
6608     *
6609     * @return The window accessibility id.
6610     *
6611     * @hide
6612     */
6613    public int getAccessibilityWindowId() {
6614        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6615                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6616    }
6617
6618    /**
6619     * Gets the {@link View} description. It briefly describes the view and is
6620     * primarily used for accessibility support. Set this property to enable
6621     * better accessibility support for your application. This is especially
6622     * true for views that do not have textual representation (For example,
6623     * ImageButton).
6624     *
6625     * @return The content description.
6626     *
6627     * @attr ref android.R.styleable#View_contentDescription
6628     */
6629    @ViewDebug.ExportedProperty(category = "accessibility")
6630    public CharSequence getContentDescription() {
6631        return mContentDescription;
6632    }
6633
6634    /**
6635     * Sets the {@link View} description. It briefly describes the view and is
6636     * primarily used for accessibility support. Set this property to enable
6637     * better accessibility support for your application. This is especially
6638     * true for views that do not have textual representation (For example,
6639     * ImageButton).
6640     *
6641     * @param contentDescription The content description.
6642     *
6643     * @attr ref android.R.styleable#View_contentDescription
6644     */
6645    @RemotableViewMethod
6646    public void setContentDescription(CharSequence contentDescription) {
6647        if (mContentDescription == null) {
6648            if (contentDescription == null) {
6649                return;
6650            }
6651        } else if (mContentDescription.equals(contentDescription)) {
6652            return;
6653        }
6654        mContentDescription = contentDescription;
6655        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6656        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6657            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6658            notifySubtreeAccessibilityStateChangedIfNeeded();
6659        } else {
6660            notifyViewAccessibilityStateChangedIfNeeded(
6661                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6662        }
6663    }
6664
6665    /**
6666     * Sets the id of a view before which this one is visited in accessibility traversal.
6667     * A screen-reader must visit the content of this view before the content of the one
6668     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6669     * will traverse the entire content of B before traversing the entire content of A,
6670     * regardles of what traversal strategy it is using.
6671     * <p>
6672     * Views that do not have specified before/after relationships are traversed in order
6673     * determined by the screen-reader.
6674     * </p>
6675     * <p>
6676     * Setting that this view is before a view that is not important for accessibility
6677     * or if this view is not important for accessibility will have no effect as the
6678     * screen-reader is not aware of unimportant views.
6679     * </p>
6680     *
6681     * @param beforeId The id of a view this one precedes in accessibility traversal.
6682     *
6683     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6684     *
6685     * @see #setImportantForAccessibility(int)
6686     */
6687    @RemotableViewMethod
6688    public void setAccessibilityTraversalBefore(int beforeId) {
6689        if (mAccessibilityTraversalBeforeId == beforeId) {
6690            return;
6691        }
6692        mAccessibilityTraversalBeforeId = beforeId;
6693        notifyViewAccessibilityStateChangedIfNeeded(
6694                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6695    }
6696
6697    /**
6698     * Gets the id of a view before which this one is visited in accessibility traversal.
6699     *
6700     * @return The id of a view this one precedes in accessibility traversal if
6701     *         specified, otherwise {@link #NO_ID}.
6702     *
6703     * @see #setAccessibilityTraversalBefore(int)
6704     */
6705    public int getAccessibilityTraversalBefore() {
6706        return mAccessibilityTraversalBeforeId;
6707    }
6708
6709    /**
6710     * Sets the id of a view after which this one is visited in accessibility traversal.
6711     * A screen-reader must visit the content of the other view before the content of this
6712     * one. For example, if view B is set to be after view A, then a screen-reader
6713     * will traverse the entire content of A before traversing the entire content of B,
6714     * regardles of what traversal strategy it is using.
6715     * <p>
6716     * Views that do not have specified before/after relationships are traversed in order
6717     * determined by the screen-reader.
6718     * </p>
6719     * <p>
6720     * Setting that this view is after a view that is not important for accessibility
6721     * or if this view is not important for accessibility will have no effect as the
6722     * screen-reader is not aware of unimportant views.
6723     * </p>
6724     *
6725     * @param afterId The id of a view this one succedees in accessibility traversal.
6726     *
6727     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6728     *
6729     * @see #setImportantForAccessibility(int)
6730     */
6731    @RemotableViewMethod
6732    public void setAccessibilityTraversalAfter(int afterId) {
6733        if (mAccessibilityTraversalAfterId == afterId) {
6734            return;
6735        }
6736        mAccessibilityTraversalAfterId = afterId;
6737        notifyViewAccessibilityStateChangedIfNeeded(
6738                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6739    }
6740
6741    /**
6742     * Gets the id of a view after which this one is visited in accessibility traversal.
6743     *
6744     * @return The id of a view this one succeedes in accessibility traversal if
6745     *         specified, otherwise {@link #NO_ID}.
6746     *
6747     * @see #setAccessibilityTraversalAfter(int)
6748     */
6749    public int getAccessibilityTraversalAfter() {
6750        return mAccessibilityTraversalAfterId;
6751    }
6752
6753    /**
6754     * Gets the id of a view for which this view serves as a label for
6755     * accessibility purposes.
6756     *
6757     * @return The labeled view id.
6758     */
6759    @ViewDebug.ExportedProperty(category = "accessibility")
6760    public int getLabelFor() {
6761        return mLabelForId;
6762    }
6763
6764    /**
6765     * Sets the id of a view for which this view serves as a label for
6766     * accessibility purposes.
6767     *
6768     * @param id The labeled view id.
6769     */
6770    @RemotableViewMethod
6771    public void setLabelFor(@IdRes int id) {
6772        if (mLabelForId == id) {
6773            return;
6774        }
6775        mLabelForId = id;
6776        if (mLabelForId != View.NO_ID
6777                && mID == View.NO_ID) {
6778            mID = generateViewId();
6779        }
6780        notifyViewAccessibilityStateChangedIfNeeded(
6781                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6782    }
6783
6784    /**
6785     * Invoked whenever this view loses focus, either by losing window focus or by losing
6786     * focus within its window. This method can be used to clear any state tied to the
6787     * focus. For instance, if a button is held pressed with the trackball and the window
6788     * loses focus, this method can be used to cancel the press.
6789     *
6790     * Subclasses of View overriding this method should always call super.onFocusLost().
6791     *
6792     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6793     * @see #onWindowFocusChanged(boolean)
6794     *
6795     * @hide pending API council approval
6796     */
6797    @CallSuper
6798    protected void onFocusLost() {
6799        resetPressedState();
6800    }
6801
6802    private void resetPressedState() {
6803        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
6804            return;
6805        }
6806
6807        if (isPressed()) {
6808            setPressed(false);
6809
6810            if (!mHasPerformedLongPress) {
6811                removeLongPressCallback();
6812            }
6813        }
6814    }
6815
6816    /**
6817     * Returns true if this view has focus
6818     *
6819     * @return True if this view has focus, false otherwise.
6820     */
6821    @ViewDebug.ExportedProperty(category = "focus")
6822    public boolean isFocused() {
6823        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
6824    }
6825
6826    /**
6827     * Find the view in the hierarchy rooted at this view that currently has
6828     * focus.
6829     *
6830     * @return The view that currently has focus, or null if no focused view can
6831     *         be found.
6832     */
6833    public View findFocus() {
6834        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
6835    }
6836
6837    /**
6838     * Indicates whether this view is one of the set of scrollable containers in
6839     * its window.
6840     *
6841     * @return whether this view is one of the set of scrollable containers in
6842     * its window
6843     *
6844     * @attr ref android.R.styleable#View_isScrollContainer
6845     */
6846    public boolean isScrollContainer() {
6847        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
6848    }
6849
6850    /**
6851     * Change whether this view is one of the set of scrollable containers in
6852     * its window.  This will be used to determine whether the window can
6853     * resize or must pan when a soft input area is open -- scrollable
6854     * containers allow the window to use resize mode since the container
6855     * will appropriately shrink.
6856     *
6857     * @attr ref android.R.styleable#View_isScrollContainer
6858     */
6859    public void setScrollContainer(boolean isScrollContainer) {
6860        if (isScrollContainer) {
6861            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
6862                mAttachInfo.mScrollContainers.add(this);
6863                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
6864            }
6865            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
6866        } else {
6867            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
6868                mAttachInfo.mScrollContainers.remove(this);
6869            }
6870            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
6871        }
6872    }
6873
6874    /**
6875     * Returns the quality of the drawing cache.
6876     *
6877     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6878     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6879     *
6880     * @see #setDrawingCacheQuality(int)
6881     * @see #setDrawingCacheEnabled(boolean)
6882     * @see #isDrawingCacheEnabled()
6883     *
6884     * @attr ref android.R.styleable#View_drawingCacheQuality
6885     */
6886    @DrawingCacheQuality
6887    public int getDrawingCacheQuality() {
6888        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
6889    }
6890
6891    /**
6892     * Set the drawing cache quality of this view. This value is used only when the
6893     * drawing cache is enabled
6894     *
6895     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
6896     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
6897     *
6898     * @see #getDrawingCacheQuality()
6899     * @see #setDrawingCacheEnabled(boolean)
6900     * @see #isDrawingCacheEnabled()
6901     *
6902     * @attr ref android.R.styleable#View_drawingCacheQuality
6903     */
6904    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
6905        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
6906    }
6907
6908    /**
6909     * Returns whether the screen should remain on, corresponding to the current
6910     * value of {@link #KEEP_SCREEN_ON}.
6911     *
6912     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
6913     *
6914     * @see #setKeepScreenOn(boolean)
6915     *
6916     * @attr ref android.R.styleable#View_keepScreenOn
6917     */
6918    public boolean getKeepScreenOn() {
6919        return (mViewFlags & KEEP_SCREEN_ON) != 0;
6920    }
6921
6922    /**
6923     * Controls whether the screen should remain on, modifying the
6924     * value of {@link #KEEP_SCREEN_ON}.
6925     *
6926     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
6927     *
6928     * @see #getKeepScreenOn()
6929     *
6930     * @attr ref android.R.styleable#View_keepScreenOn
6931     */
6932    public void setKeepScreenOn(boolean keepScreenOn) {
6933        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
6934    }
6935
6936    /**
6937     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6938     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6939     *
6940     * @attr ref android.R.styleable#View_nextFocusLeft
6941     */
6942    public int getNextFocusLeftId() {
6943        return mNextFocusLeftId;
6944    }
6945
6946    /**
6947     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
6948     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
6949     * decide automatically.
6950     *
6951     * @attr ref android.R.styleable#View_nextFocusLeft
6952     */
6953    public void setNextFocusLeftId(int nextFocusLeftId) {
6954        mNextFocusLeftId = nextFocusLeftId;
6955    }
6956
6957    /**
6958     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6959     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6960     *
6961     * @attr ref android.R.styleable#View_nextFocusRight
6962     */
6963    public int getNextFocusRightId() {
6964        return mNextFocusRightId;
6965    }
6966
6967    /**
6968     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
6969     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
6970     * decide automatically.
6971     *
6972     * @attr ref android.R.styleable#View_nextFocusRight
6973     */
6974    public void setNextFocusRightId(int nextFocusRightId) {
6975        mNextFocusRightId = nextFocusRightId;
6976    }
6977
6978    /**
6979     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6980     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
6981     *
6982     * @attr ref android.R.styleable#View_nextFocusUp
6983     */
6984    public int getNextFocusUpId() {
6985        return mNextFocusUpId;
6986    }
6987
6988    /**
6989     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
6990     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
6991     * decide automatically.
6992     *
6993     * @attr ref android.R.styleable#View_nextFocusUp
6994     */
6995    public void setNextFocusUpId(int nextFocusUpId) {
6996        mNextFocusUpId = nextFocusUpId;
6997    }
6998
6999    /**
7000     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7001     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7002     *
7003     * @attr ref android.R.styleable#View_nextFocusDown
7004     */
7005    public int getNextFocusDownId() {
7006        return mNextFocusDownId;
7007    }
7008
7009    /**
7010     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7011     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7012     * decide automatically.
7013     *
7014     * @attr ref android.R.styleable#View_nextFocusDown
7015     */
7016    public void setNextFocusDownId(int nextFocusDownId) {
7017        mNextFocusDownId = nextFocusDownId;
7018    }
7019
7020    /**
7021     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7022     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7023     *
7024     * @attr ref android.R.styleable#View_nextFocusForward
7025     */
7026    public int getNextFocusForwardId() {
7027        return mNextFocusForwardId;
7028    }
7029
7030    /**
7031     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7032     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7033     * decide automatically.
7034     *
7035     * @attr ref android.R.styleable#View_nextFocusForward
7036     */
7037    public void setNextFocusForwardId(int nextFocusForwardId) {
7038        mNextFocusForwardId = nextFocusForwardId;
7039    }
7040
7041    /**
7042     * Returns the visibility of this view and all of its ancestors
7043     *
7044     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7045     */
7046    public boolean isShown() {
7047        View current = this;
7048        //noinspection ConstantConditions
7049        do {
7050            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7051                return false;
7052            }
7053            ViewParent parent = current.mParent;
7054            if (parent == null) {
7055                return false; // We are not attached to the view root
7056            }
7057            if (!(parent instanceof View)) {
7058                return true;
7059            }
7060            current = (View) parent;
7061        } while (current != null);
7062
7063        return false;
7064    }
7065
7066    /**
7067     * Called by the view hierarchy when the content insets for a window have
7068     * changed, to allow it to adjust its content to fit within those windows.
7069     * The content insets tell you the space that the status bar, input method,
7070     * and other system windows infringe on the application's window.
7071     *
7072     * <p>You do not normally need to deal with this function, since the default
7073     * window decoration given to applications takes care of applying it to the
7074     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7075     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7076     * and your content can be placed under those system elements.  You can then
7077     * use this method within your view hierarchy if you have parts of your UI
7078     * which you would like to ensure are not being covered.
7079     *
7080     * <p>The default implementation of this method simply applies the content
7081     * insets to the view's padding, consuming that content (modifying the
7082     * insets to be 0), and returning true.  This behavior is off by default, but can
7083     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7084     *
7085     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7086     * insets object is propagated down the hierarchy, so any changes made to it will
7087     * be seen by all following views (including potentially ones above in
7088     * the hierarchy since this is a depth-first traversal).  The first view
7089     * that returns true will abort the entire traversal.
7090     *
7091     * <p>The default implementation works well for a situation where it is
7092     * used with a container that covers the entire window, allowing it to
7093     * apply the appropriate insets to its content on all edges.  If you need
7094     * a more complicated layout (such as two different views fitting system
7095     * windows, one on the top of the window, and one on the bottom),
7096     * you can override the method and handle the insets however you would like.
7097     * Note that the insets provided by the framework are always relative to the
7098     * far edges of the window, not accounting for the location of the called view
7099     * within that window.  (In fact when this method is called you do not yet know
7100     * where the layout will place the view, as it is done before layout happens.)
7101     *
7102     * <p>Note: unlike many View methods, there is no dispatch phase to this
7103     * call.  If you are overriding it in a ViewGroup and want to allow the
7104     * call to continue to your children, you must be sure to call the super
7105     * implementation.
7106     *
7107     * <p>Here is a sample layout that makes use of fitting system windows
7108     * to have controls for a video view placed inside of the window decorations
7109     * that it hides and shows.  This can be used with code like the second
7110     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7111     *
7112     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7113     *
7114     * @param insets Current content insets of the window.  Prior to
7115     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7116     * the insets or else you and Android will be unhappy.
7117     *
7118     * @return {@code true} if this view applied the insets and it should not
7119     * continue propagating further down the hierarchy, {@code false} otherwise.
7120     * @see #getFitsSystemWindows()
7121     * @see #setFitsSystemWindows(boolean)
7122     * @see #setSystemUiVisibility(int)
7123     *
7124     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7125     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7126     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7127     * to implement handling their own insets.
7128     */
7129    protected boolean fitSystemWindows(Rect insets) {
7130        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7131            if (insets == null) {
7132                // Null insets by definition have already been consumed.
7133                // This call cannot apply insets since there are none to apply,
7134                // so return false.
7135                return false;
7136            }
7137            // If we're not in the process of dispatching the newer apply insets call,
7138            // that means we're not in the compatibility path. Dispatch into the newer
7139            // apply insets path and take things from there.
7140            try {
7141                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7142                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7143            } finally {
7144                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7145            }
7146        } else {
7147            // We're being called from the newer apply insets path.
7148            // Perform the standard fallback behavior.
7149            return fitSystemWindowsInt(insets);
7150        }
7151    }
7152
7153    private boolean fitSystemWindowsInt(Rect insets) {
7154        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7155            mUserPaddingStart = UNDEFINED_PADDING;
7156            mUserPaddingEnd = UNDEFINED_PADDING;
7157            Rect localInsets = sThreadLocal.get();
7158            if (localInsets == null) {
7159                localInsets = new Rect();
7160                sThreadLocal.set(localInsets);
7161            }
7162            boolean res = computeFitSystemWindows(insets, localInsets);
7163            mUserPaddingLeftInitial = localInsets.left;
7164            mUserPaddingRightInitial = localInsets.right;
7165            internalSetPadding(localInsets.left, localInsets.top,
7166                    localInsets.right, localInsets.bottom);
7167            return res;
7168        }
7169        return false;
7170    }
7171
7172    /**
7173     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7174     *
7175     * <p>This method should be overridden by views that wish to apply a policy different from or
7176     * in addition to the default behavior. Clients that wish to force a view subtree
7177     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7178     *
7179     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7180     * it will be called during dispatch instead of this method. The listener may optionally
7181     * call this method from its own implementation if it wishes to apply the view's default
7182     * insets policy in addition to its own.</p>
7183     *
7184     * <p>Implementations of this method should either return the insets parameter unchanged
7185     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7186     * that this view applied itself. This allows new inset types added in future platform
7187     * versions to pass through existing implementations unchanged without being erroneously
7188     * consumed.</p>
7189     *
7190     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7191     * property is set then the view will consume the system window insets and apply them
7192     * as padding for the view.</p>
7193     *
7194     * @param insets Insets to apply
7195     * @return The supplied insets with any applied insets consumed
7196     */
7197    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7198        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7199            // We weren't called from within a direct call to fitSystemWindows,
7200            // call into it as a fallback in case we're in a class that overrides it
7201            // and has logic to perform.
7202            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7203                return insets.consumeSystemWindowInsets();
7204            }
7205        } else {
7206            // We were called from within a direct call to fitSystemWindows.
7207            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7208                return insets.consumeSystemWindowInsets();
7209            }
7210        }
7211        return insets;
7212    }
7213
7214    /**
7215     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7216     * window insets to this view. The listener's
7217     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7218     * method will be called instead of the view's
7219     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7220     *
7221     * @param listener Listener to set
7222     *
7223     * @see #onApplyWindowInsets(WindowInsets)
7224     */
7225    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7226        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7227    }
7228
7229    /**
7230     * Request to apply the given window insets to this view or another view in its subtree.
7231     *
7232     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7233     * obscured by window decorations or overlays. This can include the status and navigation bars,
7234     * action bars, input methods and more. New inset categories may be added in the future.
7235     * The method returns the insets provided minus any that were applied by this view or its
7236     * children.</p>
7237     *
7238     * <p>Clients wishing to provide custom behavior should override the
7239     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7240     * {@link OnApplyWindowInsetsListener} via the
7241     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7242     * method.</p>
7243     *
7244     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7245     * </p>
7246     *
7247     * @param insets Insets to apply
7248     * @return The provided insets minus the insets that were consumed
7249     */
7250    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7251        try {
7252            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7253            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7254                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7255            } else {
7256                return onApplyWindowInsets(insets);
7257            }
7258        } finally {
7259            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7260        }
7261    }
7262
7263    /**
7264     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7265     * only available if the view is attached.
7266     *
7267     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7268     */
7269    public WindowInsets getRootWindowInsets() {
7270        if (mAttachInfo != null) {
7271            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7272        }
7273        return null;
7274    }
7275
7276    /**
7277     * @hide Compute the insets that should be consumed by this view and the ones
7278     * that should propagate to those under it.
7279     */
7280    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7281        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7282                || mAttachInfo == null
7283                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7284                        && !mAttachInfo.mOverscanRequested)) {
7285            outLocalInsets.set(inoutInsets);
7286            inoutInsets.set(0, 0, 0, 0);
7287            return true;
7288        } else {
7289            // The application wants to take care of fitting system window for
7290            // the content...  however we still need to take care of any overscan here.
7291            final Rect overscan = mAttachInfo.mOverscanInsets;
7292            outLocalInsets.set(overscan);
7293            inoutInsets.left -= overscan.left;
7294            inoutInsets.top -= overscan.top;
7295            inoutInsets.right -= overscan.right;
7296            inoutInsets.bottom -= overscan.bottom;
7297            return false;
7298        }
7299    }
7300
7301    /**
7302     * Compute insets that should be consumed by this view and the ones that should propagate
7303     * to those under it.
7304     *
7305     * @param in Insets currently being processed by this View, likely received as a parameter
7306     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7307     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7308     *                       by this view
7309     * @return Insets that should be passed along to views under this one
7310     */
7311    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7312        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7313                || mAttachInfo == null
7314                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7315            outLocalInsets.set(in.getSystemWindowInsets());
7316            return in.consumeSystemWindowInsets();
7317        } else {
7318            outLocalInsets.set(0, 0, 0, 0);
7319            return in;
7320        }
7321    }
7322
7323    /**
7324     * Sets whether or not this view should account for system screen decorations
7325     * such as the status bar and inset its content; that is, controlling whether
7326     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7327     * executed.  See that method for more details.
7328     *
7329     * <p>Note that if you are providing your own implementation of
7330     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7331     * flag to true -- your implementation will be overriding the default
7332     * implementation that checks this flag.
7333     *
7334     * @param fitSystemWindows If true, then the default implementation of
7335     * {@link #fitSystemWindows(Rect)} will be executed.
7336     *
7337     * @attr ref android.R.styleable#View_fitsSystemWindows
7338     * @see #getFitsSystemWindows()
7339     * @see #fitSystemWindows(Rect)
7340     * @see #setSystemUiVisibility(int)
7341     */
7342    public void setFitsSystemWindows(boolean fitSystemWindows) {
7343        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7344    }
7345
7346    /**
7347     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7348     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7349     * will be executed.
7350     *
7351     * @return {@code true} if the default implementation of
7352     * {@link #fitSystemWindows(Rect)} will be executed.
7353     *
7354     * @attr ref android.R.styleable#View_fitsSystemWindows
7355     * @see #setFitsSystemWindows(boolean)
7356     * @see #fitSystemWindows(Rect)
7357     * @see #setSystemUiVisibility(int)
7358     */
7359    @ViewDebug.ExportedProperty
7360    public boolean getFitsSystemWindows() {
7361        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7362    }
7363
7364    /** @hide */
7365    public boolean fitsSystemWindows() {
7366        return getFitsSystemWindows();
7367    }
7368
7369    /**
7370     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7371     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7372     */
7373    public void requestFitSystemWindows() {
7374        if (mParent != null) {
7375            mParent.requestFitSystemWindows();
7376        }
7377    }
7378
7379    /**
7380     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7381     */
7382    public void requestApplyInsets() {
7383        requestFitSystemWindows();
7384    }
7385
7386    /**
7387     * For use by PhoneWindow to make its own system window fitting optional.
7388     * @hide
7389     */
7390    public void makeOptionalFitsSystemWindows() {
7391        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7392    }
7393
7394    /**
7395     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7396     * treat them as such.
7397     * @hide
7398     */
7399    public void getOutsets(Rect outOutsetRect) {
7400        if (mAttachInfo != null) {
7401            outOutsetRect.set(mAttachInfo.mOutsets);
7402        } else {
7403            outOutsetRect.setEmpty();
7404        }
7405    }
7406
7407    /**
7408     * Returns the visibility status for this view.
7409     *
7410     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7411     * @attr ref android.R.styleable#View_visibility
7412     */
7413    @ViewDebug.ExportedProperty(mapping = {
7414        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7415        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7416        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7417    })
7418    @Visibility
7419    public int getVisibility() {
7420        return mViewFlags & VISIBILITY_MASK;
7421    }
7422
7423    /**
7424     * Set the enabled state of this view.
7425     *
7426     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7427     * @attr ref android.R.styleable#View_visibility
7428     */
7429    @RemotableViewMethod
7430    public void setVisibility(@Visibility int visibility) {
7431        setFlags(visibility, VISIBILITY_MASK);
7432    }
7433
7434    /**
7435     * Returns the enabled status for this view. The interpretation of the
7436     * enabled state varies by subclass.
7437     *
7438     * @return True if this view is enabled, false otherwise.
7439     */
7440    @ViewDebug.ExportedProperty
7441    public boolean isEnabled() {
7442        return (mViewFlags & ENABLED_MASK) == ENABLED;
7443    }
7444
7445    /**
7446     * Set the enabled state of this view. The interpretation of the enabled
7447     * state varies by subclass.
7448     *
7449     * @param enabled True if this view is enabled, false otherwise.
7450     */
7451    @RemotableViewMethod
7452    public void setEnabled(boolean enabled) {
7453        if (enabled == isEnabled()) return;
7454
7455        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7456
7457        /*
7458         * The View most likely has to change its appearance, so refresh
7459         * the drawable state.
7460         */
7461        refreshDrawableState();
7462
7463        // Invalidate too, since the default behavior for views is to be
7464        // be drawn at 50% alpha rather than to change the drawable.
7465        invalidate(true);
7466
7467        if (!enabled) {
7468            cancelPendingInputEvents();
7469        }
7470    }
7471
7472    /**
7473     * Set whether this view can receive the focus.
7474     *
7475     * Setting this to false will also ensure that this view is not focusable
7476     * in touch mode.
7477     *
7478     * @param focusable If true, this view can receive the focus.
7479     *
7480     * @see #setFocusableInTouchMode(boolean)
7481     * @attr ref android.R.styleable#View_focusable
7482     */
7483    public void setFocusable(boolean focusable) {
7484        if (!focusable) {
7485            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7486        }
7487        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7488    }
7489
7490    /**
7491     * Set whether this view can receive focus while in touch mode.
7492     *
7493     * Setting this to true will also ensure that this view is focusable.
7494     *
7495     * @param focusableInTouchMode If true, this view can receive the focus while
7496     *   in touch mode.
7497     *
7498     * @see #setFocusable(boolean)
7499     * @attr ref android.R.styleable#View_focusableInTouchMode
7500     */
7501    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7502        // Focusable in touch mode should always be set before the focusable flag
7503        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7504        // which, in touch mode, will not successfully request focus on this view
7505        // because the focusable in touch mode flag is not set
7506        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7507        if (focusableInTouchMode) {
7508            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7509        }
7510    }
7511
7512    /**
7513     * Set whether this view should have sound effects enabled for events such as
7514     * clicking and touching.
7515     *
7516     * <p>You may wish to disable sound effects for a view if you already play sounds,
7517     * for instance, a dial key that plays dtmf tones.
7518     *
7519     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7520     * @see #isSoundEffectsEnabled()
7521     * @see #playSoundEffect(int)
7522     * @attr ref android.R.styleable#View_soundEffectsEnabled
7523     */
7524    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7525        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7526    }
7527
7528    /**
7529     * @return whether this view should have sound effects enabled for events such as
7530     *     clicking and touching.
7531     *
7532     * @see #setSoundEffectsEnabled(boolean)
7533     * @see #playSoundEffect(int)
7534     * @attr ref android.R.styleable#View_soundEffectsEnabled
7535     */
7536    @ViewDebug.ExportedProperty
7537    public boolean isSoundEffectsEnabled() {
7538        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7539    }
7540
7541    /**
7542     * Set whether this view should have haptic feedback for events such as
7543     * long presses.
7544     *
7545     * <p>You may wish to disable haptic feedback if your view already controls
7546     * its own haptic feedback.
7547     *
7548     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7549     * @see #isHapticFeedbackEnabled()
7550     * @see #performHapticFeedback(int)
7551     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7552     */
7553    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7554        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7555    }
7556
7557    /**
7558     * @return whether this view should have haptic feedback enabled for events
7559     * long presses.
7560     *
7561     * @see #setHapticFeedbackEnabled(boolean)
7562     * @see #performHapticFeedback(int)
7563     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7564     */
7565    @ViewDebug.ExportedProperty
7566    public boolean isHapticFeedbackEnabled() {
7567        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7568    }
7569
7570    /**
7571     * Returns the layout direction for this view.
7572     *
7573     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7574     *   {@link #LAYOUT_DIRECTION_RTL},
7575     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7576     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7577     *
7578     * @attr ref android.R.styleable#View_layoutDirection
7579     *
7580     * @hide
7581     */
7582    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7583        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7584        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7585        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7586        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7587    })
7588    @LayoutDir
7589    public int getRawLayoutDirection() {
7590        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7591    }
7592
7593    /**
7594     * Set the layout direction for this view. This will propagate a reset of layout direction
7595     * resolution to the view's children and resolve layout direction for this view.
7596     *
7597     * @param layoutDirection the layout direction to set. Should be one of:
7598     *
7599     * {@link #LAYOUT_DIRECTION_LTR},
7600     * {@link #LAYOUT_DIRECTION_RTL},
7601     * {@link #LAYOUT_DIRECTION_INHERIT},
7602     * {@link #LAYOUT_DIRECTION_LOCALE}.
7603     *
7604     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7605     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7606     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7607     *
7608     * @attr ref android.R.styleable#View_layoutDirection
7609     */
7610    @RemotableViewMethod
7611    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7612        if (getRawLayoutDirection() != layoutDirection) {
7613            // Reset the current layout direction and the resolved one
7614            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7615            resetRtlProperties();
7616            // Set the new layout direction (filtered)
7617            mPrivateFlags2 |=
7618                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7619            // We need to resolve all RTL properties as they all depend on layout direction
7620            resolveRtlPropertiesIfNeeded();
7621            requestLayout();
7622            invalidate(true);
7623        }
7624    }
7625
7626    /**
7627     * Returns the resolved layout direction for this view.
7628     *
7629     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7630     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7631     *
7632     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7633     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7634     *
7635     * @attr ref android.R.styleable#View_layoutDirection
7636     */
7637    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7638        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7639        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7640    })
7641    @ResolvedLayoutDir
7642    public int getLayoutDirection() {
7643        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7644        if (targetSdkVersion < JELLY_BEAN_MR1) {
7645            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7646            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7647        }
7648        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7649                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7650    }
7651
7652    /**
7653     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7654     * layout attribute and/or the inherited value from the parent
7655     *
7656     * @return true if the layout is right-to-left.
7657     *
7658     * @hide
7659     */
7660    @ViewDebug.ExportedProperty(category = "layout")
7661    public boolean isLayoutRtl() {
7662        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7663    }
7664
7665    /**
7666     * Indicates whether the view is currently tracking transient state that the
7667     * app should not need to concern itself with saving and restoring, but that
7668     * the framework should take special note to preserve when possible.
7669     *
7670     * <p>A view with transient state cannot be trivially rebound from an external
7671     * data source, such as an adapter binding item views in a list. This may be
7672     * because the view is performing an animation, tracking user selection
7673     * of content, or similar.</p>
7674     *
7675     * @return true if the view has transient state
7676     */
7677    @ViewDebug.ExportedProperty(category = "layout")
7678    public boolean hasTransientState() {
7679        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7680    }
7681
7682    /**
7683     * Set whether this view is currently tracking transient state that the
7684     * framework should attempt to preserve when possible. This flag is reference counted,
7685     * so every call to setHasTransientState(true) should be paired with a later call
7686     * to setHasTransientState(false).
7687     *
7688     * <p>A view with transient state cannot be trivially rebound from an external
7689     * data source, such as an adapter binding item views in a list. This may be
7690     * because the view is performing an animation, tracking user selection
7691     * of content, or similar.</p>
7692     *
7693     * @param hasTransientState true if this view has transient state
7694     */
7695    public void setHasTransientState(boolean hasTransientState) {
7696        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7697                mTransientStateCount - 1;
7698        if (mTransientStateCount < 0) {
7699            mTransientStateCount = 0;
7700            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7701                    "unmatched pair of setHasTransientState calls");
7702        } else if ((hasTransientState && mTransientStateCount == 1) ||
7703                (!hasTransientState && mTransientStateCount == 0)) {
7704            // update flag if we've just incremented up from 0 or decremented down to 0
7705            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7706                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7707            if (mParent != null) {
7708                try {
7709                    mParent.childHasTransientStateChanged(this, hasTransientState);
7710                } catch (AbstractMethodError e) {
7711                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7712                            " does not fully implement ViewParent", e);
7713                }
7714            }
7715        }
7716    }
7717
7718    /**
7719     * Returns true if this view is currently attached to a window.
7720     */
7721    public boolean isAttachedToWindow() {
7722        return mAttachInfo != null;
7723    }
7724
7725    /**
7726     * Returns true if this view has been through at least one layout since it
7727     * was last attached to or detached from a window.
7728     */
7729    public boolean isLaidOut() {
7730        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7731    }
7732
7733    /**
7734     * If this view doesn't do any drawing on its own, set this flag to
7735     * allow further optimizations. By default, this flag is not set on
7736     * View, but could be set on some View subclasses such as ViewGroup.
7737     *
7738     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7739     * you should clear this flag.
7740     *
7741     * @param willNotDraw whether or not this View draw on its own
7742     */
7743    public void setWillNotDraw(boolean willNotDraw) {
7744        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7745    }
7746
7747    /**
7748     * Returns whether or not this View draws on its own.
7749     *
7750     * @return true if this view has nothing to draw, false otherwise
7751     */
7752    @ViewDebug.ExportedProperty(category = "drawing")
7753    public boolean willNotDraw() {
7754        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7755    }
7756
7757    /**
7758     * When a View's drawing cache is enabled, drawing is redirected to an
7759     * offscreen bitmap. Some views, like an ImageView, must be able to
7760     * bypass this mechanism if they already draw a single bitmap, to avoid
7761     * unnecessary usage of the memory.
7762     *
7763     * @param willNotCacheDrawing true if this view does not cache its
7764     *        drawing, false otherwise
7765     */
7766    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7767        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7768    }
7769
7770    /**
7771     * Returns whether or not this View can cache its drawing or not.
7772     *
7773     * @return true if this view does not cache its drawing, false otherwise
7774     */
7775    @ViewDebug.ExportedProperty(category = "drawing")
7776    public boolean willNotCacheDrawing() {
7777        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7778    }
7779
7780    /**
7781     * Indicates whether this view reacts to click events or not.
7782     *
7783     * @return true if the view is clickable, false otherwise
7784     *
7785     * @see #setClickable(boolean)
7786     * @attr ref android.R.styleable#View_clickable
7787     */
7788    @ViewDebug.ExportedProperty
7789    public boolean isClickable() {
7790        return (mViewFlags & CLICKABLE) == CLICKABLE;
7791    }
7792
7793    /**
7794     * Enables or disables click events for this view. When a view
7795     * is clickable it will change its state to "pressed" on every click.
7796     * Subclasses should set the view clickable to visually react to
7797     * user's clicks.
7798     *
7799     * @param clickable true to make the view clickable, false otherwise
7800     *
7801     * @see #isClickable()
7802     * @attr ref android.R.styleable#View_clickable
7803     */
7804    public void setClickable(boolean clickable) {
7805        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
7806    }
7807
7808    /**
7809     * Indicates whether this view reacts to long click events or not.
7810     *
7811     * @return true if the view is long clickable, false otherwise
7812     *
7813     * @see #setLongClickable(boolean)
7814     * @attr ref android.R.styleable#View_longClickable
7815     */
7816    public boolean isLongClickable() {
7817        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7818    }
7819
7820    /**
7821     * Enables or disables long click events for this view. When a view is long
7822     * clickable it reacts to the user holding down the button for a longer
7823     * duration than a tap. This event can either launch the listener or a
7824     * context menu.
7825     *
7826     * @param longClickable true to make the view long clickable, false otherwise
7827     * @see #isLongClickable()
7828     * @attr ref android.R.styleable#View_longClickable
7829     */
7830    public void setLongClickable(boolean longClickable) {
7831        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
7832    }
7833
7834    /**
7835     * Indicates whether this view reacts to context clicks or not.
7836     *
7837     * @return true if the view is context clickable, false otherwise
7838     * @see #setContextClickable(boolean)
7839     * @attr ref android.R.styleable#View_contextClickable
7840     */
7841    public boolean isContextClickable() {
7842        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
7843    }
7844
7845    /**
7846     * Enables or disables context clicking for this view. This event can launch the listener.
7847     *
7848     * @param contextClickable true to make the view react to a context click, false otherwise
7849     * @see #isContextClickable()
7850     * @attr ref android.R.styleable#View_contextClickable
7851     */
7852    public void setContextClickable(boolean contextClickable) {
7853        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
7854    }
7855
7856    /**
7857     * Sets the pressed state for this view and provides a touch coordinate for
7858     * animation hinting.
7859     *
7860     * @param pressed Pass true to set the View's internal state to "pressed",
7861     *            or false to reverts the View's internal state from a
7862     *            previously set "pressed" state.
7863     * @param x The x coordinate of the touch that caused the press
7864     * @param y The y coordinate of the touch that caused the press
7865     */
7866    private void setPressed(boolean pressed, float x, float y) {
7867        if (pressed) {
7868            drawableHotspotChanged(x, y);
7869        }
7870
7871        setPressed(pressed);
7872    }
7873
7874    /**
7875     * Sets the pressed state for this view.
7876     *
7877     * @see #isClickable()
7878     * @see #setClickable(boolean)
7879     *
7880     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
7881     *        the View's internal state from a previously set "pressed" state.
7882     */
7883    public void setPressed(boolean pressed) {
7884        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
7885
7886        if (pressed) {
7887            mPrivateFlags |= PFLAG_PRESSED;
7888        } else {
7889            mPrivateFlags &= ~PFLAG_PRESSED;
7890        }
7891
7892        if (needsRefresh) {
7893            refreshDrawableState();
7894        }
7895        dispatchSetPressed(pressed);
7896    }
7897
7898    /**
7899     * Dispatch setPressed to all of this View's children.
7900     *
7901     * @see #setPressed(boolean)
7902     *
7903     * @param pressed The new pressed state
7904     */
7905    protected void dispatchSetPressed(boolean pressed) {
7906    }
7907
7908    /**
7909     * Indicates whether the view is currently in pressed state. Unless
7910     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
7911     * the pressed state.
7912     *
7913     * @see #setPressed(boolean)
7914     * @see #isClickable()
7915     * @see #setClickable(boolean)
7916     *
7917     * @return true if the view is currently pressed, false otherwise
7918     */
7919    @ViewDebug.ExportedProperty
7920    public boolean isPressed() {
7921        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
7922    }
7923
7924    /**
7925     * @hide
7926     * Indicates whether this view will participate in data collection through
7927     * {@link ViewStructure}.  If true, it will not provide any data
7928     * for itself or its children.  If false, the normal data collection will be allowed.
7929     *
7930     * @return Returns false if assist data collection is not blocked, else true.
7931     *
7932     * @see #setAssistBlocked(boolean)
7933     * @attr ref android.R.styleable#View_assistBlocked
7934     */
7935    public boolean isAssistBlocked() {
7936        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
7937    }
7938
7939    /**
7940     * @hide
7941     * Controls whether assist data collection from this view and its children is enabled
7942     * (that is, whether {@link #onProvideStructure} and
7943     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
7944     * allowing normal assist collection.  Setting this to false will disable assist collection.
7945     *
7946     * @param enabled Set to true to <em>disable</em> assist data collection, or false
7947     * (the default) to allow it.
7948     *
7949     * @see #isAssistBlocked()
7950     * @see #onProvideStructure
7951     * @see #onProvideVirtualStructure
7952     * @attr ref android.R.styleable#View_assistBlocked
7953     */
7954    public void setAssistBlocked(boolean enabled) {
7955        if (enabled) {
7956            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
7957        } else {
7958            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
7959        }
7960    }
7961
7962    /**
7963     * Indicates whether this view will save its state (that is,
7964     * whether its {@link #onSaveInstanceState} method will be called).
7965     *
7966     * @return Returns true if the view state saving is enabled, else false.
7967     *
7968     * @see #setSaveEnabled(boolean)
7969     * @attr ref android.R.styleable#View_saveEnabled
7970     */
7971    public boolean isSaveEnabled() {
7972        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
7973    }
7974
7975    /**
7976     * Controls whether the saving of this view's state is
7977     * enabled (that is, whether its {@link #onSaveInstanceState} method
7978     * will be called).  Note that even if freezing is enabled, the
7979     * view still must have an id assigned to it (via {@link #setId(int)})
7980     * for its state to be saved.  This flag can only disable the
7981     * saving of this view; any child views may still have their state saved.
7982     *
7983     * @param enabled Set to false to <em>disable</em> state saving, or true
7984     * (the default) to allow it.
7985     *
7986     * @see #isSaveEnabled()
7987     * @see #setId(int)
7988     * @see #onSaveInstanceState()
7989     * @attr ref android.R.styleable#View_saveEnabled
7990     */
7991    public void setSaveEnabled(boolean enabled) {
7992        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
7993    }
7994
7995    /**
7996     * Gets whether the framework should discard touches when the view's
7997     * window is obscured by another visible window.
7998     * Refer to the {@link View} security documentation for more details.
7999     *
8000     * @return True if touch filtering is enabled.
8001     *
8002     * @see #setFilterTouchesWhenObscured(boolean)
8003     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8004     */
8005    @ViewDebug.ExportedProperty
8006    public boolean getFilterTouchesWhenObscured() {
8007        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8008    }
8009
8010    /**
8011     * Sets whether the framework should discard touches when the view's
8012     * window is obscured by another visible window.
8013     * Refer to the {@link View} security documentation for more details.
8014     *
8015     * @param enabled True if touch filtering should be enabled.
8016     *
8017     * @see #getFilterTouchesWhenObscured
8018     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8019     */
8020    public void setFilterTouchesWhenObscured(boolean enabled) {
8021        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8022                FILTER_TOUCHES_WHEN_OBSCURED);
8023    }
8024
8025    /**
8026     * Indicates whether the entire hierarchy under this view will save its
8027     * state when a state saving traversal occurs from its parent.  The default
8028     * is true; if false, these views will not be saved unless
8029     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8030     *
8031     * @return Returns true if the view state saving from parent is enabled, else false.
8032     *
8033     * @see #setSaveFromParentEnabled(boolean)
8034     */
8035    public boolean isSaveFromParentEnabled() {
8036        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8037    }
8038
8039    /**
8040     * Controls whether the entire hierarchy under this view will save its
8041     * state when a state saving traversal occurs from its parent.  The default
8042     * is true; if false, these views will not be saved unless
8043     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8044     *
8045     * @param enabled Set to false to <em>disable</em> state saving, or true
8046     * (the default) to allow it.
8047     *
8048     * @see #isSaveFromParentEnabled()
8049     * @see #setId(int)
8050     * @see #onSaveInstanceState()
8051     */
8052    public void setSaveFromParentEnabled(boolean enabled) {
8053        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8054    }
8055
8056
8057    /**
8058     * Returns whether this View is able to take focus.
8059     *
8060     * @return True if this view can take focus, or false otherwise.
8061     * @attr ref android.R.styleable#View_focusable
8062     */
8063    @ViewDebug.ExportedProperty(category = "focus")
8064    public final boolean isFocusable() {
8065        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8066    }
8067
8068    /**
8069     * When a view is focusable, it may not want to take focus when in touch mode.
8070     * For example, a button would like focus when the user is navigating via a D-pad
8071     * so that the user can click on it, but once the user starts touching the screen,
8072     * the button shouldn't take focus
8073     * @return Whether the view is focusable in touch mode.
8074     * @attr ref android.R.styleable#View_focusableInTouchMode
8075     */
8076    @ViewDebug.ExportedProperty
8077    public final boolean isFocusableInTouchMode() {
8078        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8079    }
8080
8081    /**
8082     * Find the nearest view in the specified direction that can take focus.
8083     * This does not actually give focus to that view.
8084     *
8085     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8086     *
8087     * @return The nearest focusable in the specified direction, or null if none
8088     *         can be found.
8089     */
8090    public View focusSearch(@FocusRealDirection int direction) {
8091        if (mParent != null) {
8092            return mParent.focusSearch(this, direction);
8093        } else {
8094            return null;
8095        }
8096    }
8097
8098    /**
8099     * This method is the last chance for the focused view and its ancestors to
8100     * respond to an arrow key. This is called when the focused view did not
8101     * consume the key internally, nor could the view system find a new view in
8102     * the requested direction to give focus to.
8103     *
8104     * @param focused The currently focused view.
8105     * @param direction The direction focus wants to move. One of FOCUS_UP,
8106     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8107     * @return True if the this view consumed this unhandled move.
8108     */
8109    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8110        return false;
8111    }
8112
8113    /**
8114     * If a user manually specified the next view id for a particular direction,
8115     * use the root to look up the view.
8116     * @param root The root view of the hierarchy containing this view.
8117     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8118     * or FOCUS_BACKWARD.
8119     * @return The user specified next view, or null if there is none.
8120     */
8121    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8122        switch (direction) {
8123            case FOCUS_LEFT:
8124                if (mNextFocusLeftId == View.NO_ID) return null;
8125                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8126            case FOCUS_RIGHT:
8127                if (mNextFocusRightId == View.NO_ID) return null;
8128                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8129            case FOCUS_UP:
8130                if (mNextFocusUpId == View.NO_ID) return null;
8131                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8132            case FOCUS_DOWN:
8133                if (mNextFocusDownId == View.NO_ID) return null;
8134                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8135            case FOCUS_FORWARD:
8136                if (mNextFocusForwardId == View.NO_ID) return null;
8137                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8138            case FOCUS_BACKWARD: {
8139                if (mID == View.NO_ID) return null;
8140                final int id = mID;
8141                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8142                    @Override
8143                    public boolean apply(View t) {
8144                        return t.mNextFocusForwardId == id;
8145                    }
8146                });
8147            }
8148        }
8149        return null;
8150    }
8151
8152    private View findViewInsideOutShouldExist(View root, int id) {
8153        if (mMatchIdPredicate == null) {
8154            mMatchIdPredicate = new MatchIdPredicate();
8155        }
8156        mMatchIdPredicate.mId = id;
8157        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8158        if (result == null) {
8159            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8160        }
8161        return result;
8162    }
8163
8164    /**
8165     * Find and return all focusable views that are descendants of this view,
8166     * possibly including this view if it is focusable itself.
8167     *
8168     * @param direction The direction of the focus
8169     * @return A list of focusable views
8170     */
8171    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8172        ArrayList<View> result = new ArrayList<View>(24);
8173        addFocusables(result, direction);
8174        return result;
8175    }
8176
8177    /**
8178     * Add any focusable views that are descendants of this view (possibly
8179     * including this view if it is focusable itself) to views.  If we are in touch mode,
8180     * only add views that are also focusable in touch mode.
8181     *
8182     * @param views Focusable views found so far
8183     * @param direction The direction of the focus
8184     */
8185    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8186        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8187    }
8188
8189    /**
8190     * Adds any focusable views that are descendants of this view (possibly
8191     * including this view if it is focusable itself) to views. This method
8192     * adds all focusable views regardless if we are in touch mode or
8193     * only views focusable in touch mode if we are in touch mode or
8194     * only views that can take accessibility focus if accessibility is enabled
8195     * depending on the focusable mode parameter.
8196     *
8197     * @param views Focusable views found so far or null if all we are interested is
8198     *        the number of focusables.
8199     * @param direction The direction of the focus.
8200     * @param focusableMode The type of focusables to be added.
8201     *
8202     * @see #FOCUSABLES_ALL
8203     * @see #FOCUSABLES_TOUCH_MODE
8204     */
8205    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8206            @FocusableMode int focusableMode) {
8207        if (views == null) {
8208            return;
8209        }
8210        if (!isFocusable()) {
8211            return;
8212        }
8213        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8214                && isInTouchMode() && !isFocusableInTouchMode()) {
8215            return;
8216        }
8217        views.add(this);
8218    }
8219
8220    /**
8221     * Finds the Views that contain given text. The containment is case insensitive.
8222     * The search is performed by either the text that the View renders or the content
8223     * description that describes the view for accessibility purposes and the view does
8224     * not render or both. Clients can specify how the search is to be performed via
8225     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8226     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8227     *
8228     * @param outViews The output list of matching Views.
8229     * @param searched The text to match against.
8230     *
8231     * @see #FIND_VIEWS_WITH_TEXT
8232     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8233     * @see #setContentDescription(CharSequence)
8234     */
8235    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8236            @FindViewFlags int flags) {
8237        if (getAccessibilityNodeProvider() != null) {
8238            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8239                outViews.add(this);
8240            }
8241        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8242                && (searched != null && searched.length() > 0)
8243                && (mContentDescription != null && mContentDescription.length() > 0)) {
8244            String searchedLowerCase = searched.toString().toLowerCase();
8245            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8246            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8247                outViews.add(this);
8248            }
8249        }
8250    }
8251
8252    /**
8253     * Find and return all touchable views that are descendants of this view,
8254     * possibly including this view if it is touchable itself.
8255     *
8256     * @return A list of touchable views
8257     */
8258    public ArrayList<View> getTouchables() {
8259        ArrayList<View> result = new ArrayList<View>();
8260        addTouchables(result);
8261        return result;
8262    }
8263
8264    /**
8265     * Add any touchable views that are descendants of this view (possibly
8266     * including this view if it is touchable itself) to views.
8267     *
8268     * @param views Touchable views found so far
8269     */
8270    public void addTouchables(ArrayList<View> views) {
8271        final int viewFlags = mViewFlags;
8272
8273        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8274                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8275                && (viewFlags & ENABLED_MASK) == ENABLED) {
8276            views.add(this);
8277        }
8278    }
8279
8280    /**
8281     * Returns whether this View is accessibility focused.
8282     *
8283     * @return True if this View is accessibility focused.
8284     */
8285    public boolean isAccessibilityFocused() {
8286        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8287    }
8288
8289    /**
8290     * Call this to try to give accessibility focus to this view.
8291     *
8292     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8293     * returns false or the view is no visible or the view already has accessibility
8294     * focus.
8295     *
8296     * See also {@link #focusSearch(int)}, which is what you call to say that you
8297     * have focus, and you want your parent to look for the next one.
8298     *
8299     * @return Whether this view actually took accessibility focus.
8300     *
8301     * @hide
8302     */
8303    public boolean requestAccessibilityFocus() {
8304        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8305        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8306            return false;
8307        }
8308        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8309            return false;
8310        }
8311        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8312            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8313            ViewRootImpl viewRootImpl = getViewRootImpl();
8314            if (viewRootImpl != null) {
8315                viewRootImpl.setAccessibilityFocus(this, null);
8316            }
8317            invalidate();
8318            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8319            return true;
8320        }
8321        return false;
8322    }
8323
8324    /**
8325     * Call this to try to clear accessibility focus of this view.
8326     *
8327     * See also {@link #focusSearch(int)}, which is what you call to say that you
8328     * have focus, and you want your parent to look for the next one.
8329     *
8330     * @hide
8331     */
8332    public void clearAccessibilityFocus() {
8333        clearAccessibilityFocusNoCallbacks();
8334        // Clear the global reference of accessibility focus if this
8335        // view or any of its descendants had accessibility focus.
8336        ViewRootImpl viewRootImpl = getViewRootImpl();
8337        if (viewRootImpl != null) {
8338            View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8339            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8340                viewRootImpl.setAccessibilityFocus(null, null);
8341            }
8342        }
8343    }
8344
8345    private void sendAccessibilityHoverEvent(int eventType) {
8346        // Since we are not delivering to a client accessibility events from not
8347        // important views (unless the clinet request that) we need to fire the
8348        // event from the deepest view exposed to the client. As a consequence if
8349        // the user crosses a not exposed view the client will see enter and exit
8350        // of the exposed predecessor followed by and enter and exit of that same
8351        // predecessor when entering and exiting the not exposed descendant. This
8352        // is fine since the client has a clear idea which view is hovered at the
8353        // price of a couple more events being sent. This is a simple and
8354        // working solution.
8355        View source = this;
8356        while (true) {
8357            if (source.includeForAccessibility()) {
8358                source.sendAccessibilityEvent(eventType);
8359                return;
8360            }
8361            ViewParent parent = source.getParent();
8362            if (parent instanceof View) {
8363                source = (View) parent;
8364            } else {
8365                return;
8366            }
8367        }
8368    }
8369
8370    /**
8371     * Clears accessibility focus without calling any callback methods
8372     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8373     * is used for clearing accessibility focus when giving this focus to
8374     * another view.
8375     */
8376    void clearAccessibilityFocusNoCallbacks() {
8377        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8378            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8379            invalidate();
8380            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8381        }
8382    }
8383
8384    /**
8385     * Call this to try to give focus to a specific view or to one of its
8386     * descendants.
8387     *
8388     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8389     * false), or if it is focusable and it is not focusable in touch mode
8390     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8391     *
8392     * See also {@link #focusSearch(int)}, which is what you call to say that you
8393     * have focus, and you want your parent to look for the next one.
8394     *
8395     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8396     * {@link #FOCUS_DOWN} and <code>null</code>.
8397     *
8398     * @return Whether this view or one of its descendants actually took focus.
8399     */
8400    public final boolean requestFocus() {
8401        return requestFocus(View.FOCUS_DOWN);
8402    }
8403
8404    /**
8405     * Call this to try to give focus to a specific view or to one of its
8406     * descendants and give it a hint about what direction focus is heading.
8407     *
8408     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8409     * false), or if it is focusable and it is not focusable in touch mode
8410     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8411     *
8412     * See also {@link #focusSearch(int)}, which is what you call to say that you
8413     * have focus, and you want your parent to look for the next one.
8414     *
8415     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8416     * <code>null</code> set for the previously focused rectangle.
8417     *
8418     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8419     * @return Whether this view or one of its descendants actually took focus.
8420     */
8421    public final boolean requestFocus(int direction) {
8422        return requestFocus(direction, null);
8423    }
8424
8425    /**
8426     * Call this to try to give focus to a specific view or to one of its descendants
8427     * and give it hints about the direction and a specific rectangle that the focus
8428     * is coming from.  The rectangle can help give larger views a finer grained hint
8429     * about where focus is coming from, and therefore, where to show selection, or
8430     * forward focus change internally.
8431     *
8432     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8433     * false), or if it is focusable and it is not focusable in touch mode
8434     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8435     *
8436     * A View will not take focus if it is not visible.
8437     *
8438     * A View will not take focus if one of its parents has
8439     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8440     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8441     *
8442     * See also {@link #focusSearch(int)}, which is what you call to say that you
8443     * have focus, and you want your parent to look for the next one.
8444     *
8445     * You may wish to override this method if your custom {@link View} has an internal
8446     * {@link View} that it wishes to forward the request to.
8447     *
8448     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8449     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8450     *        to give a finer grained hint about where focus is coming from.  May be null
8451     *        if there is no hint.
8452     * @return Whether this view or one of its descendants actually took focus.
8453     */
8454    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8455        return requestFocusNoSearch(direction, previouslyFocusedRect);
8456    }
8457
8458    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8459        // need to be focusable
8460        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8461                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8462            return false;
8463        }
8464
8465        // need to be focusable in touch mode if in touch mode
8466        if (isInTouchMode() &&
8467            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8468               return false;
8469        }
8470
8471        // need to not have any parents blocking us
8472        if (hasAncestorThatBlocksDescendantFocus()) {
8473            return false;
8474        }
8475
8476        handleFocusGainInternal(direction, previouslyFocusedRect);
8477        return true;
8478    }
8479
8480    /**
8481     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8482     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8483     * touch mode to request focus when they are touched.
8484     *
8485     * @return Whether this view or one of its descendants actually took focus.
8486     *
8487     * @see #isInTouchMode()
8488     *
8489     */
8490    public final boolean requestFocusFromTouch() {
8491        // Leave touch mode if we need to
8492        if (isInTouchMode()) {
8493            ViewRootImpl viewRoot = getViewRootImpl();
8494            if (viewRoot != null) {
8495                viewRoot.ensureTouchMode(false);
8496            }
8497        }
8498        return requestFocus(View.FOCUS_DOWN);
8499    }
8500
8501    /**
8502     * @return Whether any ancestor of this view blocks descendant focus.
8503     */
8504    private boolean hasAncestorThatBlocksDescendantFocus() {
8505        final boolean focusableInTouchMode = isFocusableInTouchMode();
8506        ViewParent ancestor = mParent;
8507        while (ancestor instanceof ViewGroup) {
8508            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8509            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8510                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8511                return true;
8512            } else {
8513                ancestor = vgAncestor.getParent();
8514            }
8515        }
8516        return false;
8517    }
8518
8519    /**
8520     * Gets the mode for determining whether this View is important for accessibility
8521     * which is if it fires accessibility events and if it is reported to
8522     * accessibility services that query the screen.
8523     *
8524     * @return The mode for determining whether a View is important for accessibility.
8525     *
8526     * @attr ref android.R.styleable#View_importantForAccessibility
8527     *
8528     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8529     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8530     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8531     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8532     */
8533    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8534            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8535            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8536            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8537            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8538                    to = "noHideDescendants")
8539        })
8540    public int getImportantForAccessibility() {
8541        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8542                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8543    }
8544
8545    /**
8546     * Sets the live region mode for this view. This indicates to accessibility
8547     * services whether they should automatically notify the user about changes
8548     * to the view's content description or text, or to the content descriptions
8549     * or text of the view's children (where applicable).
8550     * <p>
8551     * For example, in a login screen with a TextView that displays an "incorrect
8552     * password" notification, that view should be marked as a live region with
8553     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8554     * <p>
8555     * To disable change notifications for this view, use
8556     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8557     * mode for most views.
8558     * <p>
8559     * To indicate that the user should be notified of changes, use
8560     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8561     * <p>
8562     * If the view's changes should interrupt ongoing speech and notify the user
8563     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8564     *
8565     * @param mode The live region mode for this view, one of:
8566     *        <ul>
8567     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8568     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8569     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8570     *        </ul>
8571     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8572     */
8573    public void setAccessibilityLiveRegion(int mode) {
8574        if (mode != getAccessibilityLiveRegion()) {
8575            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8576            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8577                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8578            notifyViewAccessibilityStateChangedIfNeeded(
8579                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8580        }
8581    }
8582
8583    /**
8584     * Gets the live region mode for this View.
8585     *
8586     * @return The live region mode for the view.
8587     *
8588     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8589     *
8590     * @see #setAccessibilityLiveRegion(int)
8591     */
8592    public int getAccessibilityLiveRegion() {
8593        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8594                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8595    }
8596
8597    /**
8598     * Sets how to determine whether this view is important for accessibility
8599     * which is if it fires accessibility events and if it is reported to
8600     * accessibility services that query the screen.
8601     *
8602     * @param mode How to determine whether this view is important for accessibility.
8603     *
8604     * @attr ref android.R.styleable#View_importantForAccessibility
8605     *
8606     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8607     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8608     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8609     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8610     */
8611    public void setImportantForAccessibility(int mode) {
8612        final int oldMode = getImportantForAccessibility();
8613        if (mode != oldMode) {
8614            // If we're moving between AUTO and another state, we might not need
8615            // to send a subtree changed notification. We'll store the computed
8616            // importance, since we'll need to check it later to make sure.
8617            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8618                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8619            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8620            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8621            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8622                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8623            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8624                notifySubtreeAccessibilityStateChangedIfNeeded();
8625            } else {
8626                notifyViewAccessibilityStateChangedIfNeeded(
8627                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8628            }
8629        }
8630    }
8631
8632    /**
8633     * Computes whether this view should be exposed for accessibility. In
8634     * general, views that are interactive or provide information are exposed
8635     * while views that serve only as containers are hidden.
8636     * <p>
8637     * If an ancestor of this view has importance
8638     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8639     * returns <code>false</code>.
8640     * <p>
8641     * Otherwise, the value is computed according to the view's
8642     * {@link #getImportantForAccessibility()} value:
8643     * <ol>
8644     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8645     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8646     * </code>
8647     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8648     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8649     * view satisfies any of the following:
8650     * <ul>
8651     * <li>Is actionable, e.g. {@link #isClickable()},
8652     * {@link #isLongClickable()}, or {@link #isFocusable()}
8653     * <li>Has an {@link AccessibilityDelegate}
8654     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8655     * {@link OnKeyListener}, etc.
8656     * <li>Is an accessibility live region, e.g.
8657     * {@link #getAccessibilityLiveRegion()} is not
8658     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8659     * </ul>
8660     * </ol>
8661     *
8662     * @return Whether the view is exposed for accessibility.
8663     * @see #setImportantForAccessibility(int)
8664     * @see #getImportantForAccessibility()
8665     */
8666    public boolean isImportantForAccessibility() {
8667        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8668                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8669        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8670                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8671            return false;
8672        }
8673
8674        // Check parent mode to ensure we're not hidden.
8675        ViewParent parent = mParent;
8676        while (parent instanceof View) {
8677            if (((View) parent).getImportantForAccessibility()
8678                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8679                return false;
8680            }
8681            parent = parent.getParent();
8682        }
8683
8684        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8685                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8686                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8687    }
8688
8689    /**
8690     * Gets the parent for accessibility purposes. Note that the parent for
8691     * accessibility is not necessary the immediate parent. It is the first
8692     * predecessor that is important for accessibility.
8693     *
8694     * @return The parent for accessibility purposes.
8695     */
8696    public ViewParent getParentForAccessibility() {
8697        if (mParent instanceof View) {
8698            View parentView = (View) mParent;
8699            if (parentView.includeForAccessibility()) {
8700                return mParent;
8701            } else {
8702                return mParent.getParentForAccessibility();
8703            }
8704        }
8705        return null;
8706    }
8707
8708    /**
8709     * Adds the children of this View relevant for accessibility to the given list
8710     * as output. Since some Views are not important for accessibility the added
8711     * child views are not necessarily direct children of this view, rather they are
8712     * the first level of descendants important for accessibility.
8713     *
8714     * @param outChildren The output list that will receive children for accessibility.
8715     */
8716    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8717
8718    }
8719
8720    /**
8721     * Whether to regard this view for accessibility. A view is regarded for
8722     * accessibility if it is important for accessibility or the querying
8723     * accessibility service has explicitly requested that view not
8724     * important for accessibility are regarded.
8725     *
8726     * @return Whether to regard the view for accessibility.
8727     *
8728     * @hide
8729     */
8730    public boolean includeForAccessibility() {
8731        if (mAttachInfo != null) {
8732            return (mAttachInfo.mAccessibilityFetchFlags
8733                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8734                    || isImportantForAccessibility();
8735        }
8736        return false;
8737    }
8738
8739    /**
8740     * Returns whether the View is considered actionable from
8741     * accessibility perspective. Such view are important for
8742     * accessibility.
8743     *
8744     * @return True if the view is actionable for accessibility.
8745     *
8746     * @hide
8747     */
8748    public boolean isActionableForAccessibility() {
8749        return (isClickable() || isLongClickable() || isFocusable());
8750    }
8751
8752    /**
8753     * Returns whether the View has registered callbacks which makes it
8754     * important for accessibility.
8755     *
8756     * @return True if the view is actionable for accessibility.
8757     */
8758    private boolean hasListenersForAccessibility() {
8759        ListenerInfo info = getListenerInfo();
8760        return mTouchDelegate != null || info.mOnKeyListener != null
8761                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
8762                || info.mOnHoverListener != null || info.mOnDragListener != null;
8763    }
8764
8765    /**
8766     * Notifies that the accessibility state of this view changed. The change
8767     * is local to this view and does not represent structural changes such
8768     * as children and parent. For example, the view became focusable. The
8769     * notification is at at most once every
8770     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8771     * to avoid unnecessary load to the system. Also once a view has a pending
8772     * notification this method is a NOP until the notification has been sent.
8773     *
8774     * @hide
8775     */
8776    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
8777        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8778            return;
8779        }
8780        if (mSendViewStateChangedAccessibilityEvent == null) {
8781            mSendViewStateChangedAccessibilityEvent =
8782                    new SendViewStateChangedAccessibilityEvent();
8783        }
8784        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
8785    }
8786
8787    /**
8788     * Notifies that the accessibility state of this view changed. The change
8789     * is *not* local to this view and does represent structural changes such
8790     * as children and parent. For example, the view size changed. The
8791     * notification is at at most once every
8792     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
8793     * to avoid unnecessary load to the system. Also once a view has a pending
8794     * notification this method is a NOP until the notification has been sent.
8795     *
8796     * @hide
8797     */
8798    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
8799        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
8800            return;
8801        }
8802        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
8803            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8804            if (mParent != null) {
8805                try {
8806                    mParent.notifySubtreeAccessibilityStateChanged(
8807                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
8808                } catch (AbstractMethodError e) {
8809                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
8810                            " does not fully implement ViewParent", e);
8811                }
8812            }
8813        }
8814    }
8815
8816    /**
8817     * Change the visibility of the View without triggering any other changes. This is
8818     * important for transitions, where visibility changes should not adjust focus or
8819     * trigger a new layout. This is only used when the visibility has already been changed
8820     * and we need a transient value during an animation. When the animation completes,
8821     * the original visibility value is always restored.
8822     *
8823     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
8824     * @hide
8825     */
8826    public void setTransitionVisibility(@Visibility int visibility) {
8827        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
8828    }
8829
8830    /**
8831     * Reset the flag indicating the accessibility state of the subtree rooted
8832     * at this view changed.
8833     */
8834    void resetSubtreeAccessibilityStateChanged() {
8835        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
8836    }
8837
8838    /**
8839     * Report an accessibility action to this view's parents for delegated processing.
8840     *
8841     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
8842     * call this method to delegate an accessibility action to a supporting parent. If the parent
8843     * returns true from its
8844     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
8845     * method this method will return true to signify that the action was consumed.</p>
8846     *
8847     * <p>This method is useful for implementing nested scrolling child views. If
8848     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
8849     * a custom view implementation may invoke this method to allow a parent to consume the
8850     * scroll first. If this method returns true the custom view should skip its own scrolling
8851     * behavior.</p>
8852     *
8853     * @param action Accessibility action to delegate
8854     * @param arguments Optional action arguments
8855     * @return true if the action was consumed by a parent
8856     */
8857    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
8858        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
8859            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
8860                return true;
8861            }
8862        }
8863        return false;
8864    }
8865
8866    /**
8867     * Performs the specified accessibility action on the view. For
8868     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
8869     * <p>
8870     * If an {@link AccessibilityDelegate} has been specified via calling
8871     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
8872     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
8873     * is responsible for handling this call.
8874     * </p>
8875     *
8876     * <p>The default implementation will delegate
8877     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
8878     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
8879     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
8880     *
8881     * @param action The action to perform.
8882     * @param arguments Optional action arguments.
8883     * @return Whether the action was performed.
8884     */
8885    public boolean performAccessibilityAction(int action, Bundle arguments) {
8886      if (mAccessibilityDelegate != null) {
8887          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
8888      } else {
8889          return performAccessibilityActionInternal(action, arguments);
8890      }
8891    }
8892
8893   /**
8894    * @see #performAccessibilityAction(int, Bundle)
8895    *
8896    * Note: Called from the default {@link AccessibilityDelegate}.
8897    *
8898    * @hide
8899    */
8900    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
8901        if (isNestedScrollingEnabled()
8902                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
8903                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
8904                || action == R.id.accessibilityActionScrollUp
8905                || action == R.id.accessibilityActionScrollLeft
8906                || action == R.id.accessibilityActionScrollDown
8907                || action == R.id.accessibilityActionScrollRight)) {
8908            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
8909                return true;
8910            }
8911        }
8912
8913        switch (action) {
8914            case AccessibilityNodeInfo.ACTION_CLICK: {
8915                if (isClickable()) {
8916                    performClick();
8917                    return true;
8918                }
8919            } break;
8920            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
8921                if (isLongClickable()) {
8922                    performLongClick();
8923                    return true;
8924                }
8925            } break;
8926            case AccessibilityNodeInfo.ACTION_FOCUS: {
8927                if (!hasFocus()) {
8928                    // Get out of touch mode since accessibility
8929                    // wants to move focus around.
8930                    getViewRootImpl().ensureTouchMode(false);
8931                    return requestFocus();
8932                }
8933            } break;
8934            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
8935                if (hasFocus()) {
8936                    clearFocus();
8937                    return !isFocused();
8938                }
8939            } break;
8940            case AccessibilityNodeInfo.ACTION_SELECT: {
8941                if (!isSelected()) {
8942                    setSelected(true);
8943                    return isSelected();
8944                }
8945            } break;
8946            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
8947                if (isSelected()) {
8948                    setSelected(false);
8949                    return !isSelected();
8950                }
8951            } break;
8952            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
8953                if (!isAccessibilityFocused()) {
8954                    return requestAccessibilityFocus();
8955                }
8956            } break;
8957            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
8958                if (isAccessibilityFocused()) {
8959                    clearAccessibilityFocus();
8960                    return true;
8961                }
8962            } break;
8963            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
8964                if (arguments != null) {
8965                    final int granularity = arguments.getInt(
8966                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8967                    final boolean extendSelection = arguments.getBoolean(
8968                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8969                    return traverseAtGranularity(granularity, true, extendSelection);
8970                }
8971            } break;
8972            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
8973                if (arguments != null) {
8974                    final int granularity = arguments.getInt(
8975                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
8976                    final boolean extendSelection = arguments.getBoolean(
8977                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
8978                    return traverseAtGranularity(granularity, false, extendSelection);
8979                }
8980            } break;
8981            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
8982                CharSequence text = getIterableTextForAccessibility();
8983                if (text == null) {
8984                    return false;
8985                }
8986                final int start = (arguments != null) ? arguments.getInt(
8987                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
8988                final int end = (arguments != null) ? arguments.getInt(
8989                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
8990                // Only cursor position can be specified (selection length == 0)
8991                if ((getAccessibilitySelectionStart() != start
8992                        || getAccessibilitySelectionEnd() != end)
8993                        && (start == end)) {
8994                    setAccessibilitySelection(start, end);
8995                    notifyViewAccessibilityStateChangedIfNeeded(
8996                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8997                    return true;
8998                }
8999            } break;
9000            case R.id.accessibilityActionShowOnScreen: {
9001                if (mAttachInfo != null) {
9002                    final Rect r = mAttachInfo.mTmpInvalRect;
9003                    getDrawingRect(r);
9004                    return requestRectangleOnScreen(r, true);
9005                }
9006            } break;
9007            case R.id.accessibilityActionContextClick: {
9008                if (isContextClickable()) {
9009                    performContextClick();
9010                    return true;
9011                }
9012            } break;
9013        }
9014        return false;
9015    }
9016
9017    private boolean traverseAtGranularity(int granularity, boolean forward,
9018            boolean extendSelection) {
9019        CharSequence text = getIterableTextForAccessibility();
9020        if (text == null || text.length() == 0) {
9021            return false;
9022        }
9023        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9024        if (iterator == null) {
9025            return false;
9026        }
9027        int current = getAccessibilitySelectionEnd();
9028        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9029            current = forward ? 0 : text.length();
9030        }
9031        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9032        if (range == null) {
9033            return false;
9034        }
9035        final int segmentStart = range[0];
9036        final int segmentEnd = range[1];
9037        int selectionStart;
9038        int selectionEnd;
9039        if (extendSelection && isAccessibilitySelectionExtendable()) {
9040            selectionStart = getAccessibilitySelectionStart();
9041            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9042                selectionStart = forward ? segmentStart : segmentEnd;
9043            }
9044            selectionEnd = forward ? segmentEnd : segmentStart;
9045        } else {
9046            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9047        }
9048        setAccessibilitySelection(selectionStart, selectionEnd);
9049        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9050                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9051        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9052        return true;
9053    }
9054
9055    /**
9056     * Gets the text reported for accessibility purposes.
9057     *
9058     * @return The accessibility text.
9059     *
9060     * @hide
9061     */
9062    public CharSequence getIterableTextForAccessibility() {
9063        return getContentDescription();
9064    }
9065
9066    /**
9067     * Gets whether accessibility selection can be extended.
9068     *
9069     * @return If selection is extensible.
9070     *
9071     * @hide
9072     */
9073    public boolean isAccessibilitySelectionExtendable() {
9074        return false;
9075    }
9076
9077    /**
9078     * @hide
9079     */
9080    public int getAccessibilitySelectionStart() {
9081        return mAccessibilityCursorPosition;
9082    }
9083
9084    /**
9085     * @hide
9086     */
9087    public int getAccessibilitySelectionEnd() {
9088        return getAccessibilitySelectionStart();
9089    }
9090
9091    /**
9092     * @hide
9093     */
9094    public void setAccessibilitySelection(int start, int end) {
9095        if (start ==  end && end == mAccessibilityCursorPosition) {
9096            return;
9097        }
9098        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9099            mAccessibilityCursorPosition = start;
9100        } else {
9101            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9102        }
9103        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9104    }
9105
9106    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9107            int fromIndex, int toIndex) {
9108        if (mParent == null) {
9109            return;
9110        }
9111        AccessibilityEvent event = AccessibilityEvent.obtain(
9112                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9113        onInitializeAccessibilityEvent(event);
9114        onPopulateAccessibilityEvent(event);
9115        event.setFromIndex(fromIndex);
9116        event.setToIndex(toIndex);
9117        event.setAction(action);
9118        event.setMovementGranularity(granularity);
9119        mParent.requestSendAccessibilityEvent(this, event);
9120    }
9121
9122    /**
9123     * @hide
9124     */
9125    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9126        switch (granularity) {
9127            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9128                CharSequence text = getIterableTextForAccessibility();
9129                if (text != null && text.length() > 0) {
9130                    CharacterTextSegmentIterator iterator =
9131                        CharacterTextSegmentIterator.getInstance(
9132                                mContext.getResources().getConfiguration().locale);
9133                    iterator.initialize(text.toString());
9134                    return iterator;
9135                }
9136            } break;
9137            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9138                CharSequence text = getIterableTextForAccessibility();
9139                if (text != null && text.length() > 0) {
9140                    WordTextSegmentIterator iterator =
9141                        WordTextSegmentIterator.getInstance(
9142                                mContext.getResources().getConfiguration().locale);
9143                    iterator.initialize(text.toString());
9144                    return iterator;
9145                }
9146            } break;
9147            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9148                CharSequence text = getIterableTextForAccessibility();
9149                if (text != null && text.length() > 0) {
9150                    ParagraphTextSegmentIterator iterator =
9151                        ParagraphTextSegmentIterator.getInstance();
9152                    iterator.initialize(text.toString());
9153                    return iterator;
9154                }
9155            } break;
9156        }
9157        return null;
9158    }
9159
9160    /**
9161     * @hide
9162     */
9163    public void dispatchStartTemporaryDetach() {
9164        onStartTemporaryDetach();
9165    }
9166
9167    /**
9168     * This is called when a container is going to temporarily detach a child, with
9169     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9170     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9171     * {@link #onDetachedFromWindow()} when the container is done.
9172     */
9173    public void onStartTemporaryDetach() {
9174        removeUnsetPressCallback();
9175        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9176    }
9177
9178    /**
9179     * @hide
9180     */
9181    public void dispatchFinishTemporaryDetach() {
9182        onFinishTemporaryDetach();
9183    }
9184
9185    /**
9186     * Called after {@link #onStartTemporaryDetach} when the container is done
9187     * changing the view.
9188     */
9189    public void onFinishTemporaryDetach() {
9190    }
9191
9192    /**
9193     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9194     * for this view's window.  Returns null if the view is not currently attached
9195     * to the window.  Normally you will not need to use this directly, but
9196     * just use the standard high-level event callbacks like
9197     * {@link #onKeyDown(int, KeyEvent)}.
9198     */
9199    public KeyEvent.DispatcherState getKeyDispatcherState() {
9200        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9201    }
9202
9203    /**
9204     * Dispatch a key event before it is processed by any input method
9205     * associated with the view hierarchy.  This can be used to intercept
9206     * key events in special situations before the IME consumes them; a
9207     * typical example would be handling the BACK key to update the application's
9208     * UI instead of allowing the IME to see it and close itself.
9209     *
9210     * @param event The key event to be dispatched.
9211     * @return True if the event was handled, false otherwise.
9212     */
9213    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9214        return onKeyPreIme(event.getKeyCode(), event);
9215    }
9216
9217    /**
9218     * Dispatch a key event to the next view on the focus path. This path runs
9219     * from the top of the view tree down to the currently focused view. If this
9220     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9221     * the next node down the focus path. This method also fires any key
9222     * listeners.
9223     *
9224     * @param event The key event to be dispatched.
9225     * @return True if the event was handled, false otherwise.
9226     */
9227    public boolean dispatchKeyEvent(KeyEvent event) {
9228        if (mInputEventConsistencyVerifier != null) {
9229            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9230        }
9231
9232        // Give any attached key listener a first crack at the event.
9233        //noinspection SimplifiableIfStatement
9234        ListenerInfo li = mListenerInfo;
9235        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9236                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9237            return true;
9238        }
9239
9240        if (event.dispatch(this, mAttachInfo != null
9241                ? mAttachInfo.mKeyDispatchState : null, this)) {
9242            return true;
9243        }
9244
9245        if (mInputEventConsistencyVerifier != null) {
9246            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9247        }
9248        return false;
9249    }
9250
9251    /**
9252     * Dispatches a key shortcut event.
9253     *
9254     * @param event The key event to be dispatched.
9255     * @return True if the event was handled by the view, false otherwise.
9256     */
9257    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9258        return onKeyShortcut(event.getKeyCode(), event);
9259    }
9260
9261    /**
9262     * Pass the touch screen motion event down to the target view, or this
9263     * view if it is the target.
9264     *
9265     * @param event The motion event to be dispatched.
9266     * @return True if the event was handled by the view, false otherwise.
9267     */
9268    public boolean dispatchTouchEvent(MotionEvent event) {
9269        // If the event should be handled by accessibility focus first.
9270        if (event.isTargetAccessibilityFocus()) {
9271            // We don't have focus or no virtual descendant has it, do not handle the event.
9272            if (!isAccessibilityFocusedViewOrHost()) {
9273                return false;
9274            }
9275            // We have focus and got the event, then use normal event dispatch.
9276            event.setTargetAccessibilityFocus(false);
9277        }
9278
9279        boolean result = false;
9280
9281        if (mInputEventConsistencyVerifier != null) {
9282            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9283        }
9284
9285        final int actionMasked = event.getActionMasked();
9286        if (actionMasked == MotionEvent.ACTION_DOWN) {
9287            // Defensive cleanup for new gesture
9288            stopNestedScroll();
9289        }
9290
9291        if (onFilterTouchEventForSecurity(event)) {
9292            //noinspection SimplifiableIfStatement
9293            ListenerInfo li = mListenerInfo;
9294            if (li != null && li.mOnTouchListener != null
9295                    && (mViewFlags & ENABLED_MASK) == ENABLED
9296                    && li.mOnTouchListener.onTouch(this, event)) {
9297                result = true;
9298            }
9299
9300            if (!result && onTouchEvent(event)) {
9301                result = true;
9302            }
9303        }
9304
9305        if (!result && mInputEventConsistencyVerifier != null) {
9306            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9307        }
9308
9309        // Clean up after nested scrolls if this is the end of a gesture;
9310        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9311        // of the gesture.
9312        if (actionMasked == MotionEvent.ACTION_UP ||
9313                actionMasked == MotionEvent.ACTION_CANCEL ||
9314                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9315            stopNestedScroll();
9316        }
9317
9318        return result;
9319    }
9320
9321    boolean isAccessibilityFocusedViewOrHost() {
9322        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9323                .getAccessibilityFocusedHost() == this);
9324    }
9325
9326    /**
9327     * Filter the touch event to apply security policies.
9328     *
9329     * @param event The motion event to be filtered.
9330     * @return True if the event should be dispatched, false if the event should be dropped.
9331     *
9332     * @see #getFilterTouchesWhenObscured
9333     */
9334    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9335        //noinspection RedundantIfStatement
9336        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9337                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9338            // Window is obscured, drop this touch.
9339            return false;
9340        }
9341        return true;
9342    }
9343
9344    /**
9345     * Pass a trackball motion event down to the focused view.
9346     *
9347     * @param event The motion event to be dispatched.
9348     * @return True if the event was handled by the view, false otherwise.
9349     */
9350    public boolean dispatchTrackballEvent(MotionEvent event) {
9351        if (mInputEventConsistencyVerifier != null) {
9352            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9353        }
9354
9355        return onTrackballEvent(event);
9356    }
9357
9358    /**
9359     * Dispatch a generic motion event.
9360     * <p>
9361     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9362     * are delivered to the view under the pointer.  All other generic motion events are
9363     * delivered to the focused view.  Hover events are handled specially and are delivered
9364     * to {@link #onHoverEvent(MotionEvent)}.
9365     * </p>
9366     *
9367     * @param event The motion event to be dispatched.
9368     * @return True if the event was handled by the view, false otherwise.
9369     */
9370    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9371        if (mInputEventConsistencyVerifier != null) {
9372            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9373        }
9374
9375        final int source = event.getSource();
9376        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9377            final int action = event.getAction();
9378            if (action == MotionEvent.ACTION_HOVER_ENTER
9379                    || action == MotionEvent.ACTION_HOVER_MOVE
9380                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9381                if (dispatchHoverEvent(event)) {
9382                    return true;
9383                }
9384            } else if (dispatchGenericPointerEvent(event)) {
9385                return true;
9386            }
9387        } else if (dispatchGenericFocusedEvent(event)) {
9388            return true;
9389        }
9390
9391        if (dispatchGenericMotionEventInternal(event)) {
9392            return true;
9393        }
9394
9395        if (mInputEventConsistencyVerifier != null) {
9396            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9397        }
9398        return false;
9399    }
9400
9401    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9402        //noinspection SimplifiableIfStatement
9403        ListenerInfo li = mListenerInfo;
9404        if (li != null && li.mOnGenericMotionListener != null
9405                && (mViewFlags & ENABLED_MASK) == ENABLED
9406                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9407            return true;
9408        }
9409
9410        if (onGenericMotionEvent(event)) {
9411            return true;
9412        }
9413
9414        final int actionButton = event.getActionButton();
9415        switch (event.getActionMasked()) {
9416            case MotionEvent.ACTION_BUTTON_PRESS:
9417                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9418                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9419                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9420                    if (performContextClick()) {
9421                        mInContextButtonPress = true;
9422                        setPressed(true, event.getX(), event.getY());
9423                        removeTapCallback();
9424                        removeLongPressCallback();
9425                        return true;
9426                    }
9427                }
9428                break;
9429
9430            case MotionEvent.ACTION_BUTTON_RELEASE:
9431                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9432                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9433                    mInContextButtonPress = false;
9434                    mIgnoreNextUpEvent = true;
9435                }
9436                break;
9437        }
9438
9439        if (mInputEventConsistencyVerifier != null) {
9440            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9441        }
9442        return false;
9443    }
9444
9445    /**
9446     * Dispatch a hover event.
9447     * <p>
9448     * Do not call this method directly.
9449     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9450     * </p>
9451     *
9452     * @param event The motion event to be dispatched.
9453     * @return True if the event was handled by the view, false otherwise.
9454     */
9455    protected boolean dispatchHoverEvent(MotionEvent event) {
9456        ListenerInfo li = mListenerInfo;
9457        //noinspection SimplifiableIfStatement
9458        if (li != null && li.mOnHoverListener != null
9459                && (mViewFlags & ENABLED_MASK) == ENABLED
9460                && li.mOnHoverListener.onHover(this, event)) {
9461            return true;
9462        }
9463
9464        return onHoverEvent(event);
9465    }
9466
9467    /**
9468     * Returns true if the view has a child to which it has recently sent
9469     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9470     * it does not have a hovered child, then it must be the innermost hovered view.
9471     * @hide
9472     */
9473    protected boolean hasHoveredChild() {
9474        return false;
9475    }
9476
9477    /**
9478     * Dispatch a generic motion event to the view under the first pointer.
9479     * <p>
9480     * Do not call this method directly.
9481     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9482     * </p>
9483     *
9484     * @param event The motion event to be dispatched.
9485     * @return True if the event was handled by the view, false otherwise.
9486     */
9487    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9488        return false;
9489    }
9490
9491    /**
9492     * Dispatch a generic motion event to the currently focused view.
9493     * <p>
9494     * Do not call this method directly.
9495     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9496     * </p>
9497     *
9498     * @param event The motion event to be dispatched.
9499     * @return True if the event was handled by the view, false otherwise.
9500     */
9501    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9502        return false;
9503    }
9504
9505    /**
9506     * Dispatch a pointer event.
9507     * <p>
9508     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9509     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9510     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9511     * and should not be expected to handle other pointing device features.
9512     * </p>
9513     *
9514     * @param event The motion event to be dispatched.
9515     * @return True if the event was handled by the view, false otherwise.
9516     * @hide
9517     */
9518    public final boolean dispatchPointerEvent(MotionEvent event) {
9519        if (event.isTouchEvent()) {
9520            return dispatchTouchEvent(event);
9521        } else {
9522            return dispatchGenericMotionEvent(event);
9523        }
9524    }
9525
9526    /**
9527     * Called when the window containing this view gains or loses window focus.
9528     * ViewGroups should override to route to their children.
9529     *
9530     * @param hasFocus True if the window containing this view now has focus,
9531     *        false otherwise.
9532     */
9533    public void dispatchWindowFocusChanged(boolean hasFocus) {
9534        onWindowFocusChanged(hasFocus);
9535    }
9536
9537    /**
9538     * Called when the window containing this view gains or loses focus.  Note
9539     * that this is separate from view focus: to receive key events, both
9540     * your view and its window must have focus.  If a window is displayed
9541     * on top of yours that takes input focus, then your own window will lose
9542     * focus but the view focus will remain unchanged.
9543     *
9544     * @param hasWindowFocus True if the window containing this view now has
9545     *        focus, false otherwise.
9546     */
9547    public void onWindowFocusChanged(boolean hasWindowFocus) {
9548        InputMethodManager imm = InputMethodManager.peekInstance();
9549        if (!hasWindowFocus) {
9550            if (isPressed()) {
9551                setPressed(false);
9552            }
9553            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9554                imm.focusOut(this);
9555            }
9556            removeLongPressCallback();
9557            removeTapCallback();
9558            onFocusLost();
9559        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9560            imm.focusIn(this);
9561        }
9562        refreshDrawableState();
9563    }
9564
9565    /**
9566     * Returns true if this view is in a window that currently has window focus.
9567     * Note that this is not the same as the view itself having focus.
9568     *
9569     * @return True if this view is in a window that currently has window focus.
9570     */
9571    public boolean hasWindowFocus() {
9572        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9573    }
9574
9575    /**
9576     * Dispatch a view visibility change down the view hierarchy.
9577     * ViewGroups should override to route to their children.
9578     * @param changedView The view whose visibility changed. Could be 'this' or
9579     * an ancestor view.
9580     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9581     * {@link #INVISIBLE} or {@link #GONE}.
9582     */
9583    protected void dispatchVisibilityChanged(@NonNull View changedView,
9584            @Visibility int visibility) {
9585        onVisibilityChanged(changedView, visibility);
9586    }
9587
9588    /**
9589     * Called when the visibility of the view or an ancestor of the view has
9590     * changed.
9591     *
9592     * @param changedView The view whose visibility changed. May be
9593     *                    {@code this} or an ancestor view.
9594     * @param visibility The new visibility, one of {@link #VISIBLE},
9595     *                   {@link #INVISIBLE} or {@link #GONE}.
9596     */
9597    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9598        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9599        if (visible && mAttachInfo != null) {
9600            initialAwakenScrollBars();
9601        }
9602
9603        final Drawable dr = mBackground;
9604        if (dr != null && visible != dr.isVisible()) {
9605            dr.setVisible(visible, false);
9606        }
9607        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9608        if (fg != null && visible != fg.isVisible()) {
9609            fg.setVisible(visible, false);
9610        }
9611    }
9612
9613    /**
9614     * Dispatch a hint about whether this view is displayed. For instance, when
9615     * a View moves out of the screen, it might receives a display hint indicating
9616     * the view is not displayed. Applications should not <em>rely</em> on this hint
9617     * as there is no guarantee that they will receive one.
9618     *
9619     * @param hint A hint about whether or not this view is displayed:
9620     * {@link #VISIBLE} or {@link #INVISIBLE}.
9621     */
9622    public void dispatchDisplayHint(@Visibility int hint) {
9623        onDisplayHint(hint);
9624    }
9625
9626    /**
9627     * Gives this view a hint about whether is displayed or not. For instance, when
9628     * a View moves out of the screen, it might receives a display hint indicating
9629     * the view is not displayed. Applications should not <em>rely</em> on this hint
9630     * as there is no guarantee that they will receive one.
9631     *
9632     * @param hint A hint about whether or not this view is displayed:
9633     * {@link #VISIBLE} or {@link #INVISIBLE}.
9634     */
9635    protected void onDisplayHint(@Visibility int hint) {
9636    }
9637
9638    /**
9639     * Dispatch a window visibility change down the view hierarchy.
9640     * ViewGroups should override to route to their children.
9641     *
9642     * @param visibility The new visibility of the window.
9643     *
9644     * @see #onWindowVisibilityChanged(int)
9645     */
9646    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9647        onWindowVisibilityChanged(visibility);
9648    }
9649
9650    /**
9651     * Called when the window containing has change its visibility
9652     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9653     * that this tells you whether or not your window is being made visible
9654     * to the window manager; this does <em>not</em> tell you whether or not
9655     * your window is obscured by other windows on the screen, even if it
9656     * is itself visible.
9657     *
9658     * @param visibility The new visibility of the window.
9659     */
9660    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9661        if (visibility == VISIBLE) {
9662            initialAwakenScrollBars();
9663        }
9664    }
9665
9666    /**
9667     * Returns the current visibility of the window this view is attached to
9668     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9669     *
9670     * @return Returns the current visibility of the view's window.
9671     */
9672    @Visibility
9673    public int getWindowVisibility() {
9674        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9675    }
9676
9677    /**
9678     * Retrieve the overall visible display size in which the window this view is
9679     * attached to has been positioned in.  This takes into account screen
9680     * decorations above the window, for both cases where the window itself
9681     * is being position inside of them or the window is being placed under
9682     * then and covered insets are used for the window to position its content
9683     * inside.  In effect, this tells you the available area where content can
9684     * be placed and remain visible to users.
9685     *
9686     * <p>This function requires an IPC back to the window manager to retrieve
9687     * the requested information, so should not be used in performance critical
9688     * code like drawing.
9689     *
9690     * @param outRect Filled in with the visible display frame.  If the view
9691     * is not attached to a window, this is simply the raw display size.
9692     */
9693    public void getWindowVisibleDisplayFrame(Rect outRect) {
9694        if (mAttachInfo != null) {
9695            try {
9696                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9697            } catch (RemoteException e) {
9698                return;
9699            }
9700            // XXX This is really broken, and probably all needs to be done
9701            // in the window manager, and we need to know more about whether
9702            // we want the area behind or in front of the IME.
9703            final Rect insets = mAttachInfo.mVisibleInsets;
9704            outRect.left += insets.left;
9705            outRect.top += insets.top;
9706            outRect.right -= insets.right;
9707            outRect.bottom -= insets.bottom;
9708            return;
9709        }
9710        // The view is not attached to a display so we don't have a context.
9711        // Make a best guess about the display size.
9712        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9713        d.getRectSize(outRect);
9714    }
9715
9716    /**
9717     * Dispatch a notification about a resource configuration change down
9718     * the view hierarchy.
9719     * ViewGroups should override to route to their children.
9720     *
9721     * @param newConfig The new resource configuration.
9722     *
9723     * @see #onConfigurationChanged(android.content.res.Configuration)
9724     */
9725    public void dispatchConfigurationChanged(Configuration newConfig) {
9726        onConfigurationChanged(newConfig);
9727    }
9728
9729    /**
9730     * Called when the current configuration of the resources being used
9731     * by the application have changed.  You can use this to decide when
9732     * to reload resources that can changed based on orientation and other
9733     * configuration characteristics.  You only need to use this if you are
9734     * not relying on the normal {@link android.app.Activity} mechanism of
9735     * recreating the activity instance upon a configuration change.
9736     *
9737     * @param newConfig The new resource configuration.
9738     */
9739    protected void onConfigurationChanged(Configuration newConfig) {
9740    }
9741
9742    /**
9743     * Private function to aggregate all per-view attributes in to the view
9744     * root.
9745     */
9746    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9747        performCollectViewAttributes(attachInfo, visibility);
9748    }
9749
9750    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
9751        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
9752            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
9753                attachInfo.mKeepScreenOn = true;
9754            }
9755            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
9756            ListenerInfo li = mListenerInfo;
9757            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
9758                attachInfo.mHasSystemUiListeners = true;
9759            }
9760        }
9761    }
9762
9763    void needGlobalAttributesUpdate(boolean force) {
9764        final AttachInfo ai = mAttachInfo;
9765        if (ai != null && !ai.mRecomputeGlobalAttributes) {
9766            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
9767                    || ai.mHasSystemUiListeners) {
9768                ai.mRecomputeGlobalAttributes = true;
9769            }
9770        }
9771    }
9772
9773    /**
9774     * Returns whether the device is currently in touch mode.  Touch mode is entered
9775     * once the user begins interacting with the device by touch, and affects various
9776     * things like whether focus is always visible to the user.
9777     *
9778     * @return Whether the device is in touch mode.
9779     */
9780    @ViewDebug.ExportedProperty
9781    public boolean isInTouchMode() {
9782        if (mAttachInfo != null) {
9783            return mAttachInfo.mInTouchMode;
9784        } else {
9785            return ViewRootImpl.isInTouchMode();
9786        }
9787    }
9788
9789    /**
9790     * Returns the context the view is running in, through which it can
9791     * access the current theme, resources, etc.
9792     *
9793     * @return The view's Context.
9794     */
9795    @ViewDebug.CapturedViewProperty
9796    public final Context getContext() {
9797        return mContext;
9798    }
9799
9800    /**
9801     * Handle a key event before it is processed by any input method
9802     * associated with the view hierarchy.  This can be used to intercept
9803     * key events in special situations before the IME consumes them; a
9804     * typical example would be handling the BACK key to update the application's
9805     * UI instead of allowing the IME to see it and close itself.
9806     *
9807     * @param keyCode The value in event.getKeyCode().
9808     * @param event Description of the key event.
9809     * @return If you handled the event, return true. If you want to allow the
9810     *         event to be handled by the next receiver, return false.
9811     */
9812    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
9813        return false;
9814    }
9815
9816    /**
9817     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
9818     * KeyEvent.Callback.onKeyDown()}: perform press of the view
9819     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
9820     * is released, if the view is enabled and clickable.
9821     *
9822     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9823     * although some may elect to do so in some situations. Do not rely on this to
9824     * catch software key presses.
9825     *
9826     * @param keyCode A key code that represents the button pressed, from
9827     *                {@link android.view.KeyEvent}.
9828     * @param event   The KeyEvent object that defines the button action.
9829     */
9830    public boolean onKeyDown(int keyCode, KeyEvent event) {
9831        boolean result = false;
9832
9833        if (KeyEvent.isConfirmKey(keyCode)) {
9834            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9835                return true;
9836            }
9837            // Long clickable items don't necessarily have to be clickable
9838            if (((mViewFlags & CLICKABLE) == CLICKABLE ||
9839                    (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
9840                    (event.getRepeatCount() == 0)) {
9841                setPressed(true);
9842                checkForLongClick(0);
9843                return true;
9844            }
9845        }
9846        return result;
9847    }
9848
9849    /**
9850     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
9851     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
9852     * the event).
9853     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9854     * although some may elect to do so in some situations. Do not rely on this to
9855     * catch software key presses.
9856     */
9857    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
9858        return false;
9859    }
9860
9861    /**
9862     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
9863     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
9864     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
9865     * {@link KeyEvent#KEYCODE_ENTER} is released.
9866     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9867     * although some may elect to do so in some situations. Do not rely on this to
9868     * catch software key presses.
9869     *
9870     * @param keyCode A key code that represents the button pressed, from
9871     *                {@link android.view.KeyEvent}.
9872     * @param event   The KeyEvent object that defines the button action.
9873     */
9874    public boolean onKeyUp(int keyCode, KeyEvent event) {
9875        if (KeyEvent.isConfirmKey(keyCode)) {
9876            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
9877                return true;
9878            }
9879            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
9880                setPressed(false);
9881
9882                if (!mHasPerformedLongPress) {
9883                    // This is a tap, so remove the longpress check
9884                    removeLongPressCallback();
9885                    return performClick();
9886                }
9887            }
9888        }
9889        return false;
9890    }
9891
9892    /**
9893     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
9894     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
9895     * the event).
9896     * <p>Key presses in software keyboards will generally NOT trigger this listener,
9897     * although some may elect to do so in some situations. Do not rely on this to
9898     * catch software key presses.
9899     *
9900     * @param keyCode     A key code that represents the button pressed, from
9901     *                    {@link android.view.KeyEvent}.
9902     * @param repeatCount The number of times the action was made.
9903     * @param event       The KeyEvent object that defines the button action.
9904     */
9905    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
9906        return false;
9907    }
9908
9909    /**
9910     * Called on the focused view when a key shortcut event is not handled.
9911     * Override this method to implement local key shortcuts for the View.
9912     * Key shortcuts can also be implemented by setting the
9913     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
9914     *
9915     * @param keyCode The value in event.getKeyCode().
9916     * @param event Description of the key event.
9917     * @return If you handled the event, return true. If you want to allow the
9918     *         event to be handled by the next receiver, return false.
9919     */
9920    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
9921        return false;
9922    }
9923
9924    /**
9925     * Check whether the called view is a text editor, in which case it
9926     * would make sense to automatically display a soft input window for
9927     * it.  Subclasses should override this if they implement
9928     * {@link #onCreateInputConnection(EditorInfo)} to return true if
9929     * a call on that method would return a non-null InputConnection, and
9930     * they are really a first-class editor that the user would normally
9931     * start typing on when the go into a window containing your view.
9932     *
9933     * <p>The default implementation always returns false.  This does
9934     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
9935     * will not be called or the user can not otherwise perform edits on your
9936     * view; it is just a hint to the system that this is not the primary
9937     * purpose of this view.
9938     *
9939     * @return Returns true if this view is a text editor, else false.
9940     */
9941    public boolean onCheckIsTextEditor() {
9942        return false;
9943    }
9944
9945    /**
9946     * Create a new InputConnection for an InputMethod to interact
9947     * with the view.  The default implementation returns null, since it doesn't
9948     * support input methods.  You can override this to implement such support.
9949     * This is only needed for views that take focus and text input.
9950     *
9951     * <p>When implementing this, you probably also want to implement
9952     * {@link #onCheckIsTextEditor()} to indicate you will return a
9953     * non-null InputConnection.</p>
9954     *
9955     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
9956     * object correctly and in its entirety, so that the connected IME can rely
9957     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
9958     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
9959     * must be filled in with the correct cursor position for IMEs to work correctly
9960     * with your application.</p>
9961     *
9962     * @param outAttrs Fill in with attribute information about the connection.
9963     */
9964    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
9965        return null;
9966    }
9967
9968    /**
9969     * Called by the {@link android.view.inputmethod.InputMethodManager}
9970     * when a view who is not the current
9971     * input connection target is trying to make a call on the manager.  The
9972     * default implementation returns false; you can override this to return
9973     * true for certain views if you are performing InputConnection proxying
9974     * to them.
9975     * @param view The View that is making the InputMethodManager call.
9976     * @return Return true to allow the call, false to reject.
9977     */
9978    public boolean checkInputConnectionProxy(View view) {
9979        return false;
9980    }
9981
9982    /**
9983     * Show the context menu for this view. It is not safe to hold on to the
9984     * menu after returning from this method.
9985     *
9986     * You should normally not overload this method. Overload
9987     * {@link #onCreateContextMenu(ContextMenu)} or define an
9988     * {@link OnCreateContextMenuListener} to add items to the context menu.
9989     *
9990     * @param menu The context menu to populate
9991     */
9992    public void createContextMenu(ContextMenu menu) {
9993        ContextMenuInfo menuInfo = getContextMenuInfo();
9994
9995        // Sets the current menu info so all items added to menu will have
9996        // my extra info set.
9997        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
9998
9999        onCreateContextMenu(menu);
10000        ListenerInfo li = mListenerInfo;
10001        if (li != null && li.mOnCreateContextMenuListener != null) {
10002            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10003        }
10004
10005        // Clear the extra information so subsequent items that aren't mine don't
10006        // have my extra info.
10007        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10008
10009        if (mParent != null) {
10010            mParent.createContextMenu(menu);
10011        }
10012    }
10013
10014    /**
10015     * Views should implement this if they have extra information to associate
10016     * with the context menu. The return result is supplied as a parameter to
10017     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10018     * callback.
10019     *
10020     * @return Extra information about the item for which the context menu
10021     *         should be shown. This information will vary across different
10022     *         subclasses of View.
10023     */
10024    protected ContextMenuInfo getContextMenuInfo() {
10025        return null;
10026    }
10027
10028    /**
10029     * Views should implement this if the view itself is going to add items to
10030     * the context menu.
10031     *
10032     * @param menu the context menu to populate
10033     */
10034    protected void onCreateContextMenu(ContextMenu menu) {
10035    }
10036
10037    /**
10038     * Implement this method to handle trackball motion events.  The
10039     * <em>relative</em> movement of the trackball since the last event
10040     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10041     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10042     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10043     * they will often be fractional values, representing the more fine-grained
10044     * movement information available from a trackball).
10045     *
10046     * @param event The motion event.
10047     * @return True if the event was handled, false otherwise.
10048     */
10049    public boolean onTrackballEvent(MotionEvent event) {
10050        return false;
10051    }
10052
10053    /**
10054     * Implement this method to handle generic motion events.
10055     * <p>
10056     * Generic motion events describe joystick movements, mouse hovers, track pad
10057     * touches, scroll wheel movements and other input events.  The
10058     * {@link MotionEvent#getSource() source} of the motion event specifies
10059     * the class of input that was received.  Implementations of this method
10060     * must examine the bits in the source before processing the event.
10061     * The following code example shows how this is done.
10062     * </p><p>
10063     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10064     * are delivered to the view under the pointer.  All other generic motion events are
10065     * delivered to the focused view.
10066     * </p>
10067     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10068     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10069     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10070     *             // process the joystick movement...
10071     *             return true;
10072     *         }
10073     *     }
10074     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10075     *         switch (event.getAction()) {
10076     *             case MotionEvent.ACTION_HOVER_MOVE:
10077     *                 // process the mouse hover movement...
10078     *                 return true;
10079     *             case MotionEvent.ACTION_SCROLL:
10080     *                 // process the scroll wheel movement...
10081     *                 return true;
10082     *         }
10083     *     }
10084     *     return super.onGenericMotionEvent(event);
10085     * }</pre>
10086     *
10087     * @param event The generic motion event being processed.
10088     * @return True if the event was handled, false otherwise.
10089     */
10090    public boolean onGenericMotionEvent(MotionEvent event) {
10091        return false;
10092    }
10093
10094    /**
10095     * Implement this method to handle hover events.
10096     * <p>
10097     * This method is called whenever a pointer is hovering into, over, or out of the
10098     * bounds of a view and the view is not currently being touched.
10099     * Hover events are represented as pointer events with action
10100     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10101     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10102     * </p>
10103     * <ul>
10104     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10105     * when the pointer enters the bounds of the view.</li>
10106     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10107     * when the pointer has already entered the bounds of the view and has moved.</li>
10108     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10109     * when the pointer has exited the bounds of the view or when the pointer is
10110     * about to go down due to a button click, tap, or similar user action that
10111     * causes the view to be touched.</li>
10112     * </ul>
10113     * <p>
10114     * The view should implement this method to return true to indicate that it is
10115     * handling the hover event, such as by changing its drawable state.
10116     * </p><p>
10117     * The default implementation calls {@link #setHovered} to update the hovered state
10118     * of the view when a hover enter or hover exit event is received, if the view
10119     * is enabled and is clickable.  The default implementation also sends hover
10120     * accessibility events.
10121     * </p>
10122     *
10123     * @param event The motion event that describes the hover.
10124     * @return True if the view handled the hover event.
10125     *
10126     * @see #isHovered
10127     * @see #setHovered
10128     * @see #onHoverChanged
10129     */
10130    public boolean onHoverEvent(MotionEvent event) {
10131        // The root view may receive hover (or touch) events that are outside the bounds of
10132        // the window.  This code ensures that we only send accessibility events for
10133        // hovers that are actually within the bounds of the root view.
10134        final int action = event.getActionMasked();
10135        if (!mSendingHoverAccessibilityEvents) {
10136            if ((action == MotionEvent.ACTION_HOVER_ENTER
10137                    || action == MotionEvent.ACTION_HOVER_MOVE)
10138                    && !hasHoveredChild()
10139                    && pointInView(event.getX(), event.getY())) {
10140                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10141                mSendingHoverAccessibilityEvents = true;
10142            }
10143        } else {
10144            if (action == MotionEvent.ACTION_HOVER_EXIT
10145                    || (action == MotionEvent.ACTION_MOVE
10146                            && !pointInView(event.getX(), event.getY()))) {
10147                mSendingHoverAccessibilityEvents = false;
10148                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10149            }
10150        }
10151
10152        if (isHoverable()) {
10153            switch (action) {
10154                case MotionEvent.ACTION_HOVER_ENTER:
10155                    setHovered(true);
10156                    break;
10157                case MotionEvent.ACTION_HOVER_EXIT:
10158                    setHovered(false);
10159                    break;
10160            }
10161
10162            // Dispatch the event to onGenericMotionEvent before returning true.
10163            // This is to provide compatibility with existing applications that
10164            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10165            // break because of the new default handling for hoverable views
10166            // in onHoverEvent.
10167            // Note that onGenericMotionEvent will be called by default when
10168            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10169            dispatchGenericMotionEventInternal(event);
10170            // The event was already handled by calling setHovered(), so always
10171            // return true.
10172            return true;
10173        }
10174
10175        return false;
10176    }
10177
10178    /**
10179     * Returns true if the view should handle {@link #onHoverEvent}
10180     * by calling {@link #setHovered} to change its hovered state.
10181     *
10182     * @return True if the view is hoverable.
10183     */
10184    private boolean isHoverable() {
10185        final int viewFlags = mViewFlags;
10186        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10187            return false;
10188        }
10189
10190        return (viewFlags & CLICKABLE) == CLICKABLE
10191                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10192                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10193    }
10194
10195    /**
10196     * Returns true if the view is currently hovered.
10197     *
10198     * @return True if the view is currently hovered.
10199     *
10200     * @see #setHovered
10201     * @see #onHoverChanged
10202     */
10203    @ViewDebug.ExportedProperty
10204    public boolean isHovered() {
10205        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10206    }
10207
10208    /**
10209     * Sets whether the view is currently hovered.
10210     * <p>
10211     * Calling this method also changes the drawable state of the view.  This
10212     * enables the view to react to hover by using different drawable resources
10213     * to change its appearance.
10214     * </p><p>
10215     * The {@link #onHoverChanged} method is called when the hovered state changes.
10216     * </p>
10217     *
10218     * @param hovered True if the view is hovered.
10219     *
10220     * @see #isHovered
10221     * @see #onHoverChanged
10222     */
10223    public void setHovered(boolean hovered) {
10224        if (hovered) {
10225            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10226                mPrivateFlags |= PFLAG_HOVERED;
10227                refreshDrawableState();
10228                onHoverChanged(true);
10229            }
10230        } else {
10231            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10232                mPrivateFlags &= ~PFLAG_HOVERED;
10233                refreshDrawableState();
10234                onHoverChanged(false);
10235            }
10236        }
10237    }
10238
10239    /**
10240     * Implement this method to handle hover state changes.
10241     * <p>
10242     * This method is called whenever the hover state changes as a result of a
10243     * call to {@link #setHovered}.
10244     * </p>
10245     *
10246     * @param hovered The current hover state, as returned by {@link #isHovered}.
10247     *
10248     * @see #isHovered
10249     * @see #setHovered
10250     */
10251    public void onHoverChanged(boolean hovered) {
10252    }
10253
10254    /**
10255     * Implement this method to handle touch screen motion events.
10256     * <p>
10257     * If this method is used to detect click actions, it is recommended that
10258     * the actions be performed by implementing and calling
10259     * {@link #performClick()}. This will ensure consistent system behavior,
10260     * including:
10261     * <ul>
10262     * <li>obeying click sound preferences
10263     * <li>dispatching OnClickListener calls
10264     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10265     * accessibility features are enabled
10266     * </ul>
10267     *
10268     * @param event The motion event.
10269     * @return True if the event was handled, false otherwise.
10270     */
10271    public boolean onTouchEvent(MotionEvent event) {
10272        final float x = event.getX();
10273        final float y = event.getY();
10274        final int viewFlags = mViewFlags;
10275        final int action = event.getAction();
10276
10277        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10278            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10279                setPressed(false);
10280            }
10281            // A disabled view that is clickable still consumes the touch
10282            // events, it just doesn't respond to them.
10283            return (((viewFlags & CLICKABLE) == CLICKABLE
10284                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10285                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10286        }
10287
10288        if (mTouchDelegate != null) {
10289            if (mTouchDelegate.onTouchEvent(event)) {
10290                return true;
10291            }
10292        }
10293
10294        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10295                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10296                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10297            switch (action) {
10298                case MotionEvent.ACTION_UP:
10299                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10300                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10301                        // take focus if we don't have it already and we should in
10302                        // touch mode.
10303                        boolean focusTaken = false;
10304                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10305                            focusTaken = requestFocus();
10306                        }
10307
10308                        if (prepressed) {
10309                            // The button is being released before we actually
10310                            // showed it as pressed.  Make it show the pressed
10311                            // state now (before scheduling the click) to ensure
10312                            // the user sees it.
10313                            setPressed(true, x, y);
10314                       }
10315
10316                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10317                            // This is a tap, so remove the longpress check
10318                            removeLongPressCallback();
10319
10320                            // Only perform take click actions if we were in the pressed state
10321                            if (!focusTaken) {
10322                                // Use a Runnable and post this rather than calling
10323                                // performClick directly. This lets other visual state
10324                                // of the view update before click actions start.
10325                                if (mPerformClick == null) {
10326                                    mPerformClick = new PerformClick();
10327                                }
10328                                if (!post(mPerformClick)) {
10329                                    performClick();
10330                                }
10331                            }
10332                        }
10333
10334                        if (mUnsetPressedState == null) {
10335                            mUnsetPressedState = new UnsetPressedState();
10336                        }
10337
10338                        if (prepressed) {
10339                            postDelayed(mUnsetPressedState,
10340                                    ViewConfiguration.getPressedStateDuration());
10341                        } else if (!post(mUnsetPressedState)) {
10342                            // If the post failed, unpress right now
10343                            mUnsetPressedState.run();
10344                        }
10345
10346                        removeTapCallback();
10347                    }
10348                    mIgnoreNextUpEvent = false;
10349                    break;
10350
10351                case MotionEvent.ACTION_DOWN:
10352                    mHasPerformedLongPress = false;
10353
10354                    if (performButtonActionOnTouchDown(event)) {
10355                        break;
10356                    }
10357
10358                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10359                    boolean isInScrollingContainer = isInScrollingContainer();
10360
10361                    // For views inside a scrolling container, delay the pressed feedback for
10362                    // a short period in case this is a scroll.
10363                    if (isInScrollingContainer) {
10364                        mPrivateFlags |= PFLAG_PREPRESSED;
10365                        if (mPendingCheckForTap == null) {
10366                            mPendingCheckForTap = new CheckForTap();
10367                        }
10368                        mPendingCheckForTap.x = event.getX();
10369                        mPendingCheckForTap.y = event.getY();
10370                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10371                    } else {
10372                        // Not inside a scrolling container, so show the feedback right away
10373                        setPressed(true, x, y);
10374                        checkForLongClick(0);
10375                    }
10376                    break;
10377
10378                case MotionEvent.ACTION_CANCEL:
10379                    setPressed(false);
10380                    removeTapCallback();
10381                    removeLongPressCallback();
10382                    mInContextButtonPress = false;
10383                    mHasPerformedLongPress = false;
10384                    mIgnoreNextUpEvent = false;
10385                    break;
10386
10387                case MotionEvent.ACTION_MOVE:
10388                    drawableHotspotChanged(x, y);
10389
10390                    // Be lenient about moving outside of buttons
10391                    if (!pointInView(x, y, mTouchSlop)) {
10392                        // Outside button
10393                        removeTapCallback();
10394                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10395                            // Remove any future long press/tap checks
10396                            removeLongPressCallback();
10397
10398                            setPressed(false);
10399                        }
10400                    }
10401                    break;
10402            }
10403
10404            return true;
10405        }
10406
10407        return false;
10408    }
10409
10410    /**
10411     * @hide
10412     */
10413    public boolean isInScrollingContainer() {
10414        ViewParent p = getParent();
10415        while (p != null && p instanceof ViewGroup) {
10416            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10417                return true;
10418            }
10419            p = p.getParent();
10420        }
10421        return false;
10422    }
10423
10424    /**
10425     * Remove the longpress detection timer.
10426     */
10427    private void removeLongPressCallback() {
10428        if (mPendingCheckForLongPress != null) {
10429          removeCallbacks(mPendingCheckForLongPress);
10430        }
10431    }
10432
10433    /**
10434     * Remove the pending click action
10435     */
10436    private void removePerformClickCallback() {
10437        if (mPerformClick != null) {
10438            removeCallbacks(mPerformClick);
10439        }
10440    }
10441
10442    /**
10443     * Remove the prepress detection timer.
10444     */
10445    private void removeUnsetPressCallback() {
10446        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10447            setPressed(false);
10448            removeCallbacks(mUnsetPressedState);
10449        }
10450    }
10451
10452    /**
10453     * Remove the tap detection timer.
10454     */
10455    private void removeTapCallback() {
10456        if (mPendingCheckForTap != null) {
10457            mPrivateFlags &= ~PFLAG_PREPRESSED;
10458            removeCallbacks(mPendingCheckForTap);
10459        }
10460    }
10461
10462    /**
10463     * Cancels a pending long press.  Your subclass can use this if you
10464     * want the context menu to come up if the user presses and holds
10465     * at the same place, but you don't want it to come up if they press
10466     * and then move around enough to cause scrolling.
10467     */
10468    public void cancelLongPress() {
10469        removeLongPressCallback();
10470
10471        /*
10472         * The prepressed state handled by the tap callback is a display
10473         * construct, but the tap callback will post a long press callback
10474         * less its own timeout. Remove it here.
10475         */
10476        removeTapCallback();
10477    }
10478
10479    /**
10480     * Remove the pending callback for sending a
10481     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10482     */
10483    private void removeSendViewScrolledAccessibilityEventCallback() {
10484        if (mSendViewScrolledAccessibilityEvent != null) {
10485            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10486            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10487        }
10488    }
10489
10490    /**
10491     * Sets the TouchDelegate for this View.
10492     */
10493    public void setTouchDelegate(TouchDelegate delegate) {
10494        mTouchDelegate = delegate;
10495    }
10496
10497    /**
10498     * Gets the TouchDelegate for this View.
10499     */
10500    public TouchDelegate getTouchDelegate() {
10501        return mTouchDelegate;
10502    }
10503
10504    /**
10505     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10506     *
10507     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10508     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10509     * available. This method should only be called for touch events.
10510     *
10511     * <p class="note">This api is not intended for most applications. Buffered dispatch
10512     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10513     * streams will not improve your input latency. Side effects include: increased latency,
10514     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10515     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10516     * you.</p>
10517     */
10518    public final void requestUnbufferedDispatch(MotionEvent event) {
10519        final int action = event.getAction();
10520        if (mAttachInfo == null
10521                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10522                || !event.isTouchEvent()) {
10523            return;
10524        }
10525        mAttachInfo.mUnbufferedDispatchRequested = true;
10526    }
10527
10528    /**
10529     * Set flags controlling behavior of this view.
10530     *
10531     * @param flags Constant indicating the value which should be set
10532     * @param mask Constant indicating the bit range that should be changed
10533     */
10534    void setFlags(int flags, int mask) {
10535        final boolean accessibilityEnabled =
10536                AccessibilityManager.getInstance(mContext).isEnabled();
10537        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10538
10539        int old = mViewFlags;
10540        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10541
10542        int changed = mViewFlags ^ old;
10543        if (changed == 0) {
10544            return;
10545        }
10546        int privateFlags = mPrivateFlags;
10547
10548        /* Check if the FOCUSABLE bit has changed */
10549        if (((changed & FOCUSABLE_MASK) != 0) &&
10550                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10551            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10552                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10553                /* Give up focus if we are no longer focusable */
10554                clearFocus();
10555            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10556                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10557                /*
10558                 * Tell the view system that we are now available to take focus
10559                 * if no one else already has it.
10560                 */
10561                if (mParent != null) mParent.focusableViewAvailable(this);
10562            }
10563        }
10564
10565        final int newVisibility = flags & VISIBILITY_MASK;
10566        if (newVisibility == VISIBLE) {
10567            if ((changed & VISIBILITY_MASK) != 0) {
10568                /*
10569                 * If this view is becoming visible, invalidate it in case it changed while
10570                 * it was not visible. Marking it drawn ensures that the invalidation will
10571                 * go through.
10572                 */
10573                mPrivateFlags |= PFLAG_DRAWN;
10574                invalidate(true);
10575
10576                needGlobalAttributesUpdate(true);
10577
10578                // a view becoming visible is worth notifying the parent
10579                // about in case nothing has focus.  even if this specific view
10580                // isn't focusable, it may contain something that is, so let
10581                // the root view try to give this focus if nothing else does.
10582                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10583                    mParent.focusableViewAvailable(this);
10584                }
10585            }
10586        }
10587
10588        /* Check if the GONE bit has changed */
10589        if ((changed & GONE) != 0) {
10590            needGlobalAttributesUpdate(false);
10591            requestLayout();
10592
10593            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10594                if (hasFocus()) clearFocus();
10595                clearAccessibilityFocus();
10596                destroyDrawingCache();
10597                if (mParent instanceof View) {
10598                    // GONE views noop invalidation, so invalidate the parent
10599                    ((View) mParent).invalidate(true);
10600                }
10601                // Mark the view drawn to ensure that it gets invalidated properly the next
10602                // time it is visible and gets invalidated
10603                mPrivateFlags |= PFLAG_DRAWN;
10604            }
10605            if (mAttachInfo != null) {
10606                mAttachInfo.mViewVisibilityChanged = true;
10607            }
10608        }
10609
10610        /* Check if the VISIBLE bit has changed */
10611        if ((changed & INVISIBLE) != 0) {
10612            needGlobalAttributesUpdate(false);
10613            /*
10614             * If this view is becoming invisible, set the DRAWN flag so that
10615             * the next invalidate() will not be skipped.
10616             */
10617            mPrivateFlags |= PFLAG_DRAWN;
10618
10619            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10620                // root view becoming invisible shouldn't clear focus and accessibility focus
10621                if (getRootView() != this) {
10622                    if (hasFocus()) clearFocus();
10623                    clearAccessibilityFocus();
10624                }
10625            }
10626            if (mAttachInfo != null) {
10627                mAttachInfo.mViewVisibilityChanged = true;
10628            }
10629        }
10630
10631        if ((changed & VISIBILITY_MASK) != 0) {
10632            // If the view is invisible, cleanup its display list to free up resources
10633            if (newVisibility != VISIBLE && mAttachInfo != null) {
10634                cleanupDraw();
10635            }
10636
10637            if (mParent instanceof ViewGroup) {
10638                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10639                        (changed & VISIBILITY_MASK), newVisibility);
10640                ((View) mParent).invalidate(true);
10641            } else if (mParent != null) {
10642                mParent.invalidateChild(this, null);
10643            }
10644
10645            if (mAttachInfo != null) {
10646                dispatchVisibilityChanged(this, newVisibility);
10647                notifySubtreeAccessibilityStateChangedIfNeeded();
10648            }
10649        }
10650
10651        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10652            destroyDrawingCache();
10653        }
10654
10655        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10656            destroyDrawingCache();
10657            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10658            invalidateParentCaches();
10659        }
10660
10661        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10662            destroyDrawingCache();
10663            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10664        }
10665
10666        if ((changed & DRAW_MASK) != 0) {
10667            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10668                if (mBackground != null
10669                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10670                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10671                } else {
10672                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10673                }
10674            } else {
10675                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10676            }
10677            requestLayout();
10678            invalidate(true);
10679        }
10680
10681        if ((changed & KEEP_SCREEN_ON) != 0) {
10682            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10683                mParent.recomputeViewAttributes(this);
10684            }
10685        }
10686
10687        if (accessibilityEnabled) {
10688            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10689                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10690                    || (changed & CONTEXT_CLICKABLE) != 0) {
10691                if (oldIncludeForAccessibility != includeForAccessibility()) {
10692                    notifySubtreeAccessibilityStateChangedIfNeeded();
10693                } else {
10694                    notifyViewAccessibilityStateChangedIfNeeded(
10695                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10696                }
10697            } else if ((changed & ENABLED_MASK) != 0) {
10698                notifyViewAccessibilityStateChangedIfNeeded(
10699                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10700            }
10701        }
10702    }
10703
10704    /**
10705     * Change the view's z order in the tree, so it's on top of other sibling
10706     * views. This ordering change may affect layout, if the parent container
10707     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10708     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10709     * method should be followed by calls to {@link #requestLayout()} and
10710     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10711     * with the new child ordering.
10712     *
10713     * @see ViewGroup#bringChildToFront(View)
10714     */
10715    public void bringToFront() {
10716        if (mParent != null) {
10717            mParent.bringChildToFront(this);
10718        }
10719    }
10720
10721    /**
10722     * This is called in response to an internal scroll in this view (i.e., the
10723     * view scrolled its own contents). This is typically as a result of
10724     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10725     * called.
10726     *
10727     * @param l Current horizontal scroll origin.
10728     * @param t Current vertical scroll origin.
10729     * @param oldl Previous horizontal scroll origin.
10730     * @param oldt Previous vertical scroll origin.
10731     */
10732    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10733        notifySubtreeAccessibilityStateChangedIfNeeded();
10734
10735        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10736            postSendViewScrolledAccessibilityEventCallback();
10737        }
10738
10739        mBackgroundSizeChanged = true;
10740        if (mForegroundInfo != null) {
10741            mForegroundInfo.mBoundsChanged = true;
10742        }
10743
10744        final AttachInfo ai = mAttachInfo;
10745        if (ai != null) {
10746            ai.mViewScrollChanged = true;
10747        }
10748
10749        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
10750            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
10751        }
10752    }
10753
10754    /**
10755     * Interface definition for a callback to be invoked when the scroll
10756     * X or Y positions of a view change.
10757     * <p>
10758     * <b>Note:</b> Some views handle scrolling independently from View and may
10759     * have their own separate listeners for scroll-type events. For example,
10760     * {@link android.widget.ListView ListView} allows clients to register an
10761     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
10762     * to listen for changes in list scroll position.
10763     *
10764     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
10765     */
10766    public interface OnScrollChangeListener {
10767        /**
10768         * Called when the scroll position of a view changes.
10769         *
10770         * @param v The view whose scroll position has changed.
10771         * @param scrollX Current horizontal scroll origin.
10772         * @param scrollY Current vertical scroll origin.
10773         * @param oldScrollX Previous horizontal scroll origin.
10774         * @param oldScrollY Previous vertical scroll origin.
10775         */
10776        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
10777    }
10778
10779    /**
10780     * Interface definition for a callback to be invoked when the layout bounds of a view
10781     * changes due to layout processing.
10782     */
10783    public interface OnLayoutChangeListener {
10784        /**
10785         * Called when the layout bounds of a view changes due to layout processing.
10786         *
10787         * @param v The view whose bounds have changed.
10788         * @param left The new value of the view's left property.
10789         * @param top The new value of the view's top property.
10790         * @param right The new value of the view's right property.
10791         * @param bottom The new value of the view's bottom property.
10792         * @param oldLeft The previous value of the view's left property.
10793         * @param oldTop The previous value of the view's top property.
10794         * @param oldRight The previous value of the view's right property.
10795         * @param oldBottom The previous value of the view's bottom property.
10796         */
10797        void onLayoutChange(View v, int left, int top, int right, int bottom,
10798            int oldLeft, int oldTop, int oldRight, int oldBottom);
10799    }
10800
10801    /**
10802     * This is called during layout when the size of this view has changed. If
10803     * you were just added to the view hierarchy, you're called with the old
10804     * values of 0.
10805     *
10806     * @param w Current width of this view.
10807     * @param h Current height of this view.
10808     * @param oldw Old width of this view.
10809     * @param oldh Old height of this view.
10810     */
10811    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
10812    }
10813
10814    /**
10815     * Called by draw to draw the child views. This may be overridden
10816     * by derived classes to gain control just before its children are drawn
10817     * (but after its own view has been drawn).
10818     * @param canvas the canvas on which to draw the view
10819     */
10820    protected void dispatchDraw(Canvas canvas) {
10821
10822    }
10823
10824    /**
10825     * Gets the parent of this view. Note that the parent is a
10826     * ViewParent and not necessarily a View.
10827     *
10828     * @return Parent of this view.
10829     */
10830    public final ViewParent getParent() {
10831        return mParent;
10832    }
10833
10834    /**
10835     * Set the horizontal scrolled position of your view. This will cause a call to
10836     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10837     * invalidated.
10838     * @param value the x position to scroll to
10839     */
10840    public void setScrollX(int value) {
10841        scrollTo(value, mScrollY);
10842    }
10843
10844    /**
10845     * Set the vertical scrolled position of your view. This will cause a call to
10846     * {@link #onScrollChanged(int, int, int, int)} and the view will be
10847     * invalidated.
10848     * @param value the y position to scroll to
10849     */
10850    public void setScrollY(int value) {
10851        scrollTo(mScrollX, value);
10852    }
10853
10854    /**
10855     * Return the scrolled left position of this view. This is the left edge of
10856     * the displayed part of your view. You do not need to draw any pixels
10857     * farther left, since those are outside of the frame of your view on
10858     * screen.
10859     *
10860     * @return The left edge of the displayed part of your view, in pixels.
10861     */
10862    public final int getScrollX() {
10863        return mScrollX;
10864    }
10865
10866    /**
10867     * Return the scrolled top position of this view. This is the top edge of
10868     * the displayed part of your view. You do not need to draw any pixels above
10869     * it, since those are outside of the frame of your view on screen.
10870     *
10871     * @return The top edge of the displayed part of your view, in pixels.
10872     */
10873    public final int getScrollY() {
10874        return mScrollY;
10875    }
10876
10877    /**
10878     * Return the width of the your view.
10879     *
10880     * @return The width of your view, in pixels.
10881     */
10882    @ViewDebug.ExportedProperty(category = "layout")
10883    public final int getWidth() {
10884        return mRight - mLeft;
10885    }
10886
10887    /**
10888     * Return the height of your view.
10889     *
10890     * @return The height of your view, in pixels.
10891     */
10892    @ViewDebug.ExportedProperty(category = "layout")
10893    public final int getHeight() {
10894        return mBottom - mTop;
10895    }
10896
10897    /**
10898     * Return the visible drawing bounds of your view. Fills in the output
10899     * rectangle with the values from getScrollX(), getScrollY(),
10900     * getWidth(), and getHeight(). These bounds do not account for any
10901     * transformation properties currently set on the view, such as
10902     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
10903     *
10904     * @param outRect The (scrolled) drawing bounds of the view.
10905     */
10906    public void getDrawingRect(Rect outRect) {
10907        outRect.left = mScrollX;
10908        outRect.top = mScrollY;
10909        outRect.right = mScrollX + (mRight - mLeft);
10910        outRect.bottom = mScrollY + (mBottom - mTop);
10911    }
10912
10913    /**
10914     * Like {@link #getMeasuredWidthAndState()}, but only returns the
10915     * raw width component (that is the result is masked by
10916     * {@link #MEASURED_SIZE_MASK}).
10917     *
10918     * @return The raw measured width of this view.
10919     */
10920    public final int getMeasuredWidth() {
10921        return mMeasuredWidth & MEASURED_SIZE_MASK;
10922    }
10923
10924    /**
10925     * Return the full width measurement information for this view as computed
10926     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10927     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10928     * This should be used during measurement and layout calculations only. Use
10929     * {@link #getWidth()} to see how wide a view is after layout.
10930     *
10931     * @return The measured width of this view as a bit mask.
10932     */
10933    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10934            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10935                    name = "MEASURED_STATE_TOO_SMALL"),
10936    })
10937    public final int getMeasuredWidthAndState() {
10938        return mMeasuredWidth;
10939    }
10940
10941    /**
10942     * Like {@link #getMeasuredHeightAndState()}, but only returns the
10943     * raw width component (that is the result is masked by
10944     * {@link #MEASURED_SIZE_MASK}).
10945     *
10946     * @return The raw measured height of this view.
10947     */
10948    public final int getMeasuredHeight() {
10949        return mMeasuredHeight & MEASURED_SIZE_MASK;
10950    }
10951
10952    /**
10953     * Return the full height measurement information for this view as computed
10954     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
10955     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
10956     * This should be used during measurement and layout calculations only. Use
10957     * {@link #getHeight()} to see how wide a view is after layout.
10958     *
10959     * @return The measured width of this view as a bit mask.
10960     */
10961    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
10962            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
10963                    name = "MEASURED_STATE_TOO_SMALL"),
10964    })
10965    public final int getMeasuredHeightAndState() {
10966        return mMeasuredHeight;
10967    }
10968
10969    /**
10970     * Return only the state bits of {@link #getMeasuredWidthAndState()}
10971     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
10972     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
10973     * and the height component is at the shifted bits
10974     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
10975     */
10976    public final int getMeasuredState() {
10977        return (mMeasuredWidth&MEASURED_STATE_MASK)
10978                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
10979                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
10980    }
10981
10982    /**
10983     * The transform matrix of this view, which is calculated based on the current
10984     * rotation, scale, and pivot properties.
10985     *
10986     * @see #getRotation()
10987     * @see #getScaleX()
10988     * @see #getScaleY()
10989     * @see #getPivotX()
10990     * @see #getPivotY()
10991     * @return The current transform matrix for the view
10992     */
10993    public Matrix getMatrix() {
10994        ensureTransformationInfo();
10995        final Matrix matrix = mTransformationInfo.mMatrix;
10996        mRenderNode.getMatrix(matrix);
10997        return matrix;
10998    }
10999
11000    /**
11001     * Returns true if the transform matrix is the identity matrix.
11002     * Recomputes the matrix if necessary.
11003     *
11004     * @return True if the transform matrix is the identity matrix, false otherwise.
11005     */
11006    final boolean hasIdentityMatrix() {
11007        return mRenderNode.hasIdentityMatrix();
11008    }
11009
11010    void ensureTransformationInfo() {
11011        if (mTransformationInfo == null) {
11012            mTransformationInfo = new TransformationInfo();
11013        }
11014    }
11015
11016   /**
11017     * Utility method to retrieve the inverse of the current mMatrix property.
11018     * We cache the matrix to avoid recalculating it when transform properties
11019     * have not changed.
11020     *
11021     * @return The inverse of the current matrix of this view.
11022     * @hide
11023     */
11024    public final Matrix getInverseMatrix() {
11025        ensureTransformationInfo();
11026        if (mTransformationInfo.mInverseMatrix == null) {
11027            mTransformationInfo.mInverseMatrix = new Matrix();
11028        }
11029        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11030        mRenderNode.getInverseMatrix(matrix);
11031        return matrix;
11032    }
11033
11034    /**
11035     * Gets the distance along the Z axis from the camera to this view.
11036     *
11037     * @see #setCameraDistance(float)
11038     *
11039     * @return The distance along the Z axis.
11040     */
11041    public float getCameraDistance() {
11042        final float dpi = mResources.getDisplayMetrics().densityDpi;
11043        return -(mRenderNode.getCameraDistance() * dpi);
11044    }
11045
11046    /**
11047     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11048     * views are drawn) from the camera to this view. The camera's distance
11049     * affects 3D transformations, for instance rotations around the X and Y
11050     * axis. If the rotationX or rotationY properties are changed and this view is
11051     * large (more than half the size of the screen), it is recommended to always
11052     * use a camera distance that's greater than the height (X axis rotation) or
11053     * the width (Y axis rotation) of this view.</p>
11054     *
11055     * <p>The distance of the camera from the view plane can have an affect on the
11056     * perspective distortion of the view when it is rotated around the x or y axis.
11057     * For example, a large distance will result in a large viewing angle, and there
11058     * will not be much perspective distortion of the view as it rotates. A short
11059     * distance may cause much more perspective distortion upon rotation, and can
11060     * also result in some drawing artifacts if the rotated view ends up partially
11061     * behind the camera (which is why the recommendation is to use a distance at
11062     * least as far as the size of the view, if the view is to be rotated.)</p>
11063     *
11064     * <p>The distance is expressed in "depth pixels." The default distance depends
11065     * on the screen density. For instance, on a medium density display, the
11066     * default distance is 1280. On a high density display, the default distance
11067     * is 1920.</p>
11068     *
11069     * <p>If you want to specify a distance that leads to visually consistent
11070     * results across various densities, use the following formula:</p>
11071     * <pre>
11072     * float scale = context.getResources().getDisplayMetrics().density;
11073     * view.setCameraDistance(distance * scale);
11074     * </pre>
11075     *
11076     * <p>The density scale factor of a high density display is 1.5,
11077     * and 1920 = 1280 * 1.5.</p>
11078     *
11079     * @param distance The distance in "depth pixels", if negative the opposite
11080     *        value is used
11081     *
11082     * @see #setRotationX(float)
11083     * @see #setRotationY(float)
11084     */
11085    public void setCameraDistance(float distance) {
11086        final float dpi = mResources.getDisplayMetrics().densityDpi;
11087
11088        invalidateViewProperty(true, false);
11089        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11090        invalidateViewProperty(false, false);
11091
11092        invalidateParentIfNeededAndWasQuickRejected();
11093    }
11094
11095    /**
11096     * The degrees that the view is rotated around the pivot point.
11097     *
11098     * @see #setRotation(float)
11099     * @see #getPivotX()
11100     * @see #getPivotY()
11101     *
11102     * @return The degrees of rotation.
11103     */
11104    @ViewDebug.ExportedProperty(category = "drawing")
11105    public float getRotation() {
11106        return mRenderNode.getRotation();
11107    }
11108
11109    /**
11110     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11111     * result in clockwise rotation.
11112     *
11113     * @param rotation The degrees of rotation.
11114     *
11115     * @see #getRotation()
11116     * @see #getPivotX()
11117     * @see #getPivotY()
11118     * @see #setRotationX(float)
11119     * @see #setRotationY(float)
11120     *
11121     * @attr ref android.R.styleable#View_rotation
11122     */
11123    public void setRotation(float rotation) {
11124        if (rotation != getRotation()) {
11125            // Double-invalidation is necessary to capture view's old and new areas
11126            invalidateViewProperty(true, false);
11127            mRenderNode.setRotation(rotation);
11128            invalidateViewProperty(false, true);
11129
11130            invalidateParentIfNeededAndWasQuickRejected();
11131            notifySubtreeAccessibilityStateChangedIfNeeded();
11132        }
11133    }
11134
11135    /**
11136     * The degrees that the view is rotated around the vertical axis through the pivot point.
11137     *
11138     * @see #getPivotX()
11139     * @see #getPivotY()
11140     * @see #setRotationY(float)
11141     *
11142     * @return The degrees of Y rotation.
11143     */
11144    @ViewDebug.ExportedProperty(category = "drawing")
11145    public float getRotationY() {
11146        return mRenderNode.getRotationY();
11147    }
11148
11149    /**
11150     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11151     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11152     * down the y axis.
11153     *
11154     * When rotating large views, it is recommended to adjust the camera distance
11155     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11156     *
11157     * @param rotationY The degrees of Y rotation.
11158     *
11159     * @see #getRotationY()
11160     * @see #getPivotX()
11161     * @see #getPivotY()
11162     * @see #setRotation(float)
11163     * @see #setRotationX(float)
11164     * @see #setCameraDistance(float)
11165     *
11166     * @attr ref android.R.styleable#View_rotationY
11167     */
11168    public void setRotationY(float rotationY) {
11169        if (rotationY != getRotationY()) {
11170            invalidateViewProperty(true, false);
11171            mRenderNode.setRotationY(rotationY);
11172            invalidateViewProperty(false, true);
11173
11174            invalidateParentIfNeededAndWasQuickRejected();
11175            notifySubtreeAccessibilityStateChangedIfNeeded();
11176        }
11177    }
11178
11179    /**
11180     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11181     *
11182     * @see #getPivotX()
11183     * @see #getPivotY()
11184     * @see #setRotationX(float)
11185     *
11186     * @return The degrees of X rotation.
11187     */
11188    @ViewDebug.ExportedProperty(category = "drawing")
11189    public float getRotationX() {
11190        return mRenderNode.getRotationX();
11191    }
11192
11193    /**
11194     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11195     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11196     * x axis.
11197     *
11198     * When rotating large views, it is recommended to adjust the camera distance
11199     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11200     *
11201     * @param rotationX The degrees of X rotation.
11202     *
11203     * @see #getRotationX()
11204     * @see #getPivotX()
11205     * @see #getPivotY()
11206     * @see #setRotation(float)
11207     * @see #setRotationY(float)
11208     * @see #setCameraDistance(float)
11209     *
11210     * @attr ref android.R.styleable#View_rotationX
11211     */
11212    public void setRotationX(float rotationX) {
11213        if (rotationX != getRotationX()) {
11214            invalidateViewProperty(true, false);
11215            mRenderNode.setRotationX(rotationX);
11216            invalidateViewProperty(false, true);
11217
11218            invalidateParentIfNeededAndWasQuickRejected();
11219            notifySubtreeAccessibilityStateChangedIfNeeded();
11220        }
11221    }
11222
11223    /**
11224     * The amount that the view is scaled in x around the pivot point, as a proportion of
11225     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11226     *
11227     * <p>By default, this is 1.0f.
11228     *
11229     * @see #getPivotX()
11230     * @see #getPivotY()
11231     * @return The scaling factor.
11232     */
11233    @ViewDebug.ExportedProperty(category = "drawing")
11234    public float getScaleX() {
11235        return mRenderNode.getScaleX();
11236    }
11237
11238    /**
11239     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11240     * the view's unscaled width. A value of 1 means that no scaling is applied.
11241     *
11242     * @param scaleX The scaling factor.
11243     * @see #getPivotX()
11244     * @see #getPivotY()
11245     *
11246     * @attr ref android.R.styleable#View_scaleX
11247     */
11248    public void setScaleX(float scaleX) {
11249        if (scaleX != getScaleX()) {
11250            invalidateViewProperty(true, false);
11251            mRenderNode.setScaleX(scaleX);
11252            invalidateViewProperty(false, true);
11253
11254            invalidateParentIfNeededAndWasQuickRejected();
11255            notifySubtreeAccessibilityStateChangedIfNeeded();
11256        }
11257    }
11258
11259    /**
11260     * The amount that the view is scaled in y around the pivot point, as a proportion of
11261     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11262     *
11263     * <p>By default, this is 1.0f.
11264     *
11265     * @see #getPivotX()
11266     * @see #getPivotY()
11267     * @return The scaling factor.
11268     */
11269    @ViewDebug.ExportedProperty(category = "drawing")
11270    public float getScaleY() {
11271        return mRenderNode.getScaleY();
11272    }
11273
11274    /**
11275     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11276     * the view's unscaled width. A value of 1 means that no scaling is applied.
11277     *
11278     * @param scaleY The scaling factor.
11279     * @see #getPivotX()
11280     * @see #getPivotY()
11281     *
11282     * @attr ref android.R.styleable#View_scaleY
11283     */
11284    public void setScaleY(float scaleY) {
11285        if (scaleY != getScaleY()) {
11286            invalidateViewProperty(true, false);
11287            mRenderNode.setScaleY(scaleY);
11288            invalidateViewProperty(false, true);
11289
11290            invalidateParentIfNeededAndWasQuickRejected();
11291            notifySubtreeAccessibilityStateChangedIfNeeded();
11292        }
11293    }
11294
11295    /**
11296     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11297     * and {@link #setScaleX(float) scaled}.
11298     *
11299     * @see #getRotation()
11300     * @see #getScaleX()
11301     * @see #getScaleY()
11302     * @see #getPivotY()
11303     * @return The x location of the pivot point.
11304     *
11305     * @attr ref android.R.styleable#View_transformPivotX
11306     */
11307    @ViewDebug.ExportedProperty(category = "drawing")
11308    public float getPivotX() {
11309        return mRenderNode.getPivotX();
11310    }
11311
11312    /**
11313     * Sets the x location of the point around which the view is
11314     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11315     * By default, the pivot point is centered on the object.
11316     * Setting this property disables this behavior and causes the view to use only the
11317     * explicitly set pivotX and pivotY values.
11318     *
11319     * @param pivotX The x location of the pivot point.
11320     * @see #getRotation()
11321     * @see #getScaleX()
11322     * @see #getScaleY()
11323     * @see #getPivotY()
11324     *
11325     * @attr ref android.R.styleable#View_transformPivotX
11326     */
11327    public void setPivotX(float pivotX) {
11328        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11329            invalidateViewProperty(true, false);
11330            mRenderNode.setPivotX(pivotX);
11331            invalidateViewProperty(false, true);
11332
11333            invalidateParentIfNeededAndWasQuickRejected();
11334        }
11335    }
11336
11337    /**
11338     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11339     * and {@link #setScaleY(float) scaled}.
11340     *
11341     * @see #getRotation()
11342     * @see #getScaleX()
11343     * @see #getScaleY()
11344     * @see #getPivotY()
11345     * @return The y location of the pivot point.
11346     *
11347     * @attr ref android.R.styleable#View_transformPivotY
11348     */
11349    @ViewDebug.ExportedProperty(category = "drawing")
11350    public float getPivotY() {
11351        return mRenderNode.getPivotY();
11352    }
11353
11354    /**
11355     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11356     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11357     * Setting this property disables this behavior and causes the view to use only the
11358     * explicitly set pivotX and pivotY values.
11359     *
11360     * @param pivotY The y location of the pivot point.
11361     * @see #getRotation()
11362     * @see #getScaleX()
11363     * @see #getScaleY()
11364     * @see #getPivotY()
11365     *
11366     * @attr ref android.R.styleable#View_transformPivotY
11367     */
11368    public void setPivotY(float pivotY) {
11369        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11370            invalidateViewProperty(true, false);
11371            mRenderNode.setPivotY(pivotY);
11372            invalidateViewProperty(false, true);
11373
11374            invalidateParentIfNeededAndWasQuickRejected();
11375        }
11376    }
11377
11378    /**
11379     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11380     * completely transparent and 1 means the view is completely opaque.
11381     *
11382     * <p>By default this is 1.0f.
11383     * @return The opacity of the view.
11384     */
11385    @ViewDebug.ExportedProperty(category = "drawing")
11386    public float getAlpha() {
11387        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11388    }
11389
11390    /**
11391     * Returns whether this View has content which overlaps.
11392     *
11393     * <p>This function, intended to be overridden by specific View types, is an optimization when
11394     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11395     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11396     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11397     * directly. An example of overlapping rendering is a TextView with a background image, such as
11398     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11399     * ImageView with only the foreground image. The default implementation returns true; subclasses
11400     * should override if they have cases which can be optimized.</p>
11401     *
11402     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11403     * necessitates that a View return true if it uses the methods internally without passing the
11404     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11405     *
11406     * @return true if the content in this view might overlap, false otherwise.
11407     */
11408    @ViewDebug.ExportedProperty(category = "drawing")
11409    public boolean hasOverlappingRendering() {
11410        return true;
11411    }
11412
11413    /**
11414     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11415     * completely transparent and 1 means the view is completely opaque.
11416     *
11417     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11418     * can have significant performance implications, especially for large views. It is best to use
11419     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11420     *
11421     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11422     * strongly recommended for performance reasons to either override
11423     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11424     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11425     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11426     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11427     * of rendering cost, even for simple or small views. Starting with
11428     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11429     * applied to the view at the rendering level.</p>
11430     *
11431     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11432     * responsible for applying the opacity itself.</p>
11433     *
11434     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11435     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11436     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11437     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11438     *
11439     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11440     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11441     * {@link #hasOverlappingRendering}.</p>
11442     *
11443     * @param alpha The opacity of the view.
11444     *
11445     * @see #hasOverlappingRendering()
11446     * @see #setLayerType(int, android.graphics.Paint)
11447     *
11448     * @attr ref android.R.styleable#View_alpha
11449     */
11450    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11451        ensureTransformationInfo();
11452        if (mTransformationInfo.mAlpha != alpha) {
11453            mTransformationInfo.mAlpha = alpha;
11454            if (onSetAlpha((int) (alpha * 255))) {
11455                mPrivateFlags |= PFLAG_ALPHA_SET;
11456                // subclass is handling alpha - don't optimize rendering cache invalidation
11457                invalidateParentCaches();
11458                invalidate(true);
11459            } else {
11460                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11461                invalidateViewProperty(true, false);
11462                mRenderNode.setAlpha(getFinalAlpha());
11463                notifyViewAccessibilityStateChangedIfNeeded(
11464                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11465            }
11466        }
11467    }
11468
11469    /**
11470     * Faster version of setAlpha() which performs the same steps except there are
11471     * no calls to invalidate(). The caller of this function should perform proper invalidation
11472     * on the parent and this object. The return value indicates whether the subclass handles
11473     * alpha (the return value for onSetAlpha()).
11474     *
11475     * @param alpha The new value for the alpha property
11476     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11477     *         the new value for the alpha property is different from the old value
11478     */
11479    boolean setAlphaNoInvalidation(float alpha) {
11480        ensureTransformationInfo();
11481        if (mTransformationInfo.mAlpha != alpha) {
11482            mTransformationInfo.mAlpha = alpha;
11483            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11484            if (subclassHandlesAlpha) {
11485                mPrivateFlags |= PFLAG_ALPHA_SET;
11486                return true;
11487            } else {
11488                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11489                mRenderNode.setAlpha(getFinalAlpha());
11490            }
11491        }
11492        return false;
11493    }
11494
11495    /**
11496     * This property is hidden and intended only for use by the Fade transition, which
11497     * animates it to produce a visual translucency that does not side-effect (or get
11498     * affected by) the real alpha property. This value is composited with the other
11499     * alpha value (and the AlphaAnimation value, when that is present) to produce
11500     * a final visual translucency result, which is what is passed into the DisplayList.
11501     *
11502     * @hide
11503     */
11504    public void setTransitionAlpha(float alpha) {
11505        ensureTransformationInfo();
11506        if (mTransformationInfo.mTransitionAlpha != alpha) {
11507            mTransformationInfo.mTransitionAlpha = alpha;
11508            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11509            invalidateViewProperty(true, false);
11510            mRenderNode.setAlpha(getFinalAlpha());
11511        }
11512    }
11513
11514    /**
11515     * Calculates the visual alpha of this view, which is a combination of the actual
11516     * alpha value and the transitionAlpha value (if set).
11517     */
11518    private float getFinalAlpha() {
11519        if (mTransformationInfo != null) {
11520            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11521        }
11522        return 1;
11523    }
11524
11525    /**
11526     * This property is hidden and intended only for use by the Fade transition, which
11527     * animates it to produce a visual translucency that does not side-effect (or get
11528     * affected by) the real alpha property. This value is composited with the other
11529     * alpha value (and the AlphaAnimation value, when that is present) to produce
11530     * a final visual translucency result, which is what is passed into the DisplayList.
11531     *
11532     * @hide
11533     */
11534    @ViewDebug.ExportedProperty(category = "drawing")
11535    public float getTransitionAlpha() {
11536        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11537    }
11538
11539    /**
11540     * Top position of this view relative to its parent.
11541     *
11542     * @return The top of this view, in pixels.
11543     */
11544    @ViewDebug.CapturedViewProperty
11545    public final int getTop() {
11546        return mTop;
11547    }
11548
11549    /**
11550     * Sets the top position of this view relative to its parent. This method is meant to be called
11551     * by the layout system and should not generally be called otherwise, because the property
11552     * may be changed at any time by the layout.
11553     *
11554     * @param top The top of this view, in pixels.
11555     */
11556    public final void setTop(int top) {
11557        if (top != mTop) {
11558            final boolean matrixIsIdentity = hasIdentityMatrix();
11559            if (matrixIsIdentity) {
11560                if (mAttachInfo != null) {
11561                    int minTop;
11562                    int yLoc;
11563                    if (top < mTop) {
11564                        minTop = top;
11565                        yLoc = top - mTop;
11566                    } else {
11567                        minTop = mTop;
11568                        yLoc = 0;
11569                    }
11570                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11571                }
11572            } else {
11573                // Double-invalidation is necessary to capture view's old and new areas
11574                invalidate(true);
11575            }
11576
11577            int width = mRight - mLeft;
11578            int oldHeight = mBottom - mTop;
11579
11580            mTop = top;
11581            mRenderNode.setTop(mTop);
11582
11583            sizeChange(width, mBottom - mTop, width, oldHeight);
11584
11585            if (!matrixIsIdentity) {
11586                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11587                invalidate(true);
11588            }
11589            mBackgroundSizeChanged = true;
11590            if (mForegroundInfo != null) {
11591                mForegroundInfo.mBoundsChanged = true;
11592            }
11593            invalidateParentIfNeeded();
11594            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11595                // View was rejected last time it was drawn by its parent; this may have changed
11596                invalidateParentIfNeeded();
11597            }
11598        }
11599    }
11600
11601    /**
11602     * Bottom position of this view relative to its parent.
11603     *
11604     * @return The bottom of this view, in pixels.
11605     */
11606    @ViewDebug.CapturedViewProperty
11607    public final int getBottom() {
11608        return mBottom;
11609    }
11610
11611    /**
11612     * True if this view has changed since the last time being drawn.
11613     *
11614     * @return The dirty state of this view.
11615     */
11616    public boolean isDirty() {
11617        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11618    }
11619
11620    /**
11621     * Sets the bottom position of this view relative to its parent. This method is meant to be
11622     * called by the layout system and should not generally be called otherwise, because the
11623     * property may be changed at any time by the layout.
11624     *
11625     * @param bottom The bottom of this view, in pixels.
11626     */
11627    public final void setBottom(int bottom) {
11628        if (bottom != mBottom) {
11629            final boolean matrixIsIdentity = hasIdentityMatrix();
11630            if (matrixIsIdentity) {
11631                if (mAttachInfo != null) {
11632                    int maxBottom;
11633                    if (bottom < mBottom) {
11634                        maxBottom = mBottom;
11635                    } else {
11636                        maxBottom = bottom;
11637                    }
11638                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11639                }
11640            } else {
11641                // Double-invalidation is necessary to capture view's old and new areas
11642                invalidate(true);
11643            }
11644
11645            int width = mRight - mLeft;
11646            int oldHeight = mBottom - mTop;
11647
11648            mBottom = bottom;
11649            mRenderNode.setBottom(mBottom);
11650
11651            sizeChange(width, mBottom - mTop, width, oldHeight);
11652
11653            if (!matrixIsIdentity) {
11654                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11655                invalidate(true);
11656            }
11657            mBackgroundSizeChanged = true;
11658            if (mForegroundInfo != null) {
11659                mForegroundInfo.mBoundsChanged = true;
11660            }
11661            invalidateParentIfNeeded();
11662            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11663                // View was rejected last time it was drawn by its parent; this may have changed
11664                invalidateParentIfNeeded();
11665            }
11666        }
11667    }
11668
11669    /**
11670     * Left position of this view relative to its parent.
11671     *
11672     * @return The left edge of this view, in pixels.
11673     */
11674    @ViewDebug.CapturedViewProperty
11675    public final int getLeft() {
11676        return mLeft;
11677    }
11678
11679    /**
11680     * Sets the left position of this view relative to its parent. This method is meant to be called
11681     * by the layout system and should not generally be called otherwise, because the property
11682     * may be changed at any time by the layout.
11683     *
11684     * @param left The left of this view, in pixels.
11685     */
11686    public final void setLeft(int left) {
11687        if (left != mLeft) {
11688            final boolean matrixIsIdentity = hasIdentityMatrix();
11689            if (matrixIsIdentity) {
11690                if (mAttachInfo != null) {
11691                    int minLeft;
11692                    int xLoc;
11693                    if (left < mLeft) {
11694                        minLeft = left;
11695                        xLoc = left - mLeft;
11696                    } else {
11697                        minLeft = mLeft;
11698                        xLoc = 0;
11699                    }
11700                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11701                }
11702            } else {
11703                // Double-invalidation is necessary to capture view's old and new areas
11704                invalidate(true);
11705            }
11706
11707            int oldWidth = mRight - mLeft;
11708            int height = mBottom - mTop;
11709
11710            mLeft = left;
11711            mRenderNode.setLeft(left);
11712
11713            sizeChange(mRight - mLeft, height, oldWidth, height);
11714
11715            if (!matrixIsIdentity) {
11716                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11717                invalidate(true);
11718            }
11719            mBackgroundSizeChanged = true;
11720            if (mForegroundInfo != null) {
11721                mForegroundInfo.mBoundsChanged = true;
11722            }
11723            invalidateParentIfNeeded();
11724            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11725                // View was rejected last time it was drawn by its parent; this may have changed
11726                invalidateParentIfNeeded();
11727            }
11728        }
11729    }
11730
11731    /**
11732     * Right position of this view relative to its parent.
11733     *
11734     * @return The right edge of this view, in pixels.
11735     */
11736    @ViewDebug.CapturedViewProperty
11737    public final int getRight() {
11738        return mRight;
11739    }
11740
11741    /**
11742     * Sets the right position of this view relative to its parent. This method is meant to be called
11743     * by the layout system and should not generally be called otherwise, because the property
11744     * may be changed at any time by the layout.
11745     *
11746     * @param right The right of this view, in pixels.
11747     */
11748    public final void setRight(int right) {
11749        if (right != mRight) {
11750            final boolean matrixIsIdentity = hasIdentityMatrix();
11751            if (matrixIsIdentity) {
11752                if (mAttachInfo != null) {
11753                    int maxRight;
11754                    if (right < mRight) {
11755                        maxRight = mRight;
11756                    } else {
11757                        maxRight = right;
11758                    }
11759                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
11760                }
11761            } else {
11762                // Double-invalidation is necessary to capture view's old and new areas
11763                invalidate(true);
11764            }
11765
11766            int oldWidth = mRight - mLeft;
11767            int height = mBottom - mTop;
11768
11769            mRight = right;
11770            mRenderNode.setRight(mRight);
11771
11772            sizeChange(mRight - mLeft, height, oldWidth, height);
11773
11774            if (!matrixIsIdentity) {
11775                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11776                invalidate(true);
11777            }
11778            mBackgroundSizeChanged = true;
11779            if (mForegroundInfo != null) {
11780                mForegroundInfo.mBoundsChanged = true;
11781            }
11782            invalidateParentIfNeeded();
11783            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11784                // View was rejected last time it was drawn by its parent; this may have changed
11785                invalidateParentIfNeeded();
11786            }
11787        }
11788    }
11789
11790    /**
11791     * The visual x position of this view, in pixels. This is equivalent to the
11792     * {@link #setTranslationX(float) translationX} property plus the current
11793     * {@link #getLeft() left} property.
11794     *
11795     * @return The visual x position of this view, in pixels.
11796     */
11797    @ViewDebug.ExportedProperty(category = "drawing")
11798    public float getX() {
11799        return mLeft + getTranslationX();
11800    }
11801
11802    /**
11803     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
11804     * {@link #setTranslationX(float) translationX} property to be the difference between
11805     * the x value passed in and the current {@link #getLeft() left} property.
11806     *
11807     * @param x The visual x position of this view, in pixels.
11808     */
11809    public void setX(float x) {
11810        setTranslationX(x - mLeft);
11811    }
11812
11813    /**
11814     * The visual y position of this view, in pixels. This is equivalent to the
11815     * {@link #setTranslationY(float) translationY} property plus the current
11816     * {@link #getTop() top} property.
11817     *
11818     * @return The visual y position of this view, in pixels.
11819     */
11820    @ViewDebug.ExportedProperty(category = "drawing")
11821    public float getY() {
11822        return mTop + getTranslationY();
11823    }
11824
11825    /**
11826     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
11827     * {@link #setTranslationY(float) translationY} property to be the difference between
11828     * the y value passed in and the current {@link #getTop() top} property.
11829     *
11830     * @param y The visual y position of this view, in pixels.
11831     */
11832    public void setY(float y) {
11833        setTranslationY(y - mTop);
11834    }
11835
11836    /**
11837     * The visual z position of this view, in pixels. This is equivalent to the
11838     * {@link #setTranslationZ(float) translationZ} property plus the current
11839     * {@link #getElevation() elevation} property.
11840     *
11841     * @return The visual z position of this view, in pixels.
11842     */
11843    @ViewDebug.ExportedProperty(category = "drawing")
11844    public float getZ() {
11845        return getElevation() + getTranslationZ();
11846    }
11847
11848    /**
11849     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
11850     * {@link #setTranslationZ(float) translationZ} property to be the difference between
11851     * the x value passed in and the current {@link #getElevation() elevation} property.
11852     *
11853     * @param z The visual z position of this view, in pixels.
11854     */
11855    public void setZ(float z) {
11856        setTranslationZ(z - getElevation());
11857    }
11858
11859    /**
11860     * The base elevation of this view relative to its parent, in pixels.
11861     *
11862     * @return The base depth position of the view, in pixels.
11863     */
11864    @ViewDebug.ExportedProperty(category = "drawing")
11865    public float getElevation() {
11866        return mRenderNode.getElevation();
11867    }
11868
11869    /**
11870     * Sets the base elevation of this view, in pixels.
11871     *
11872     * @attr ref android.R.styleable#View_elevation
11873     */
11874    public void setElevation(float elevation) {
11875        if (elevation != getElevation()) {
11876            invalidateViewProperty(true, false);
11877            mRenderNode.setElevation(elevation);
11878            invalidateViewProperty(false, true);
11879
11880            invalidateParentIfNeededAndWasQuickRejected();
11881        }
11882    }
11883
11884    /**
11885     * The horizontal location of this view relative to its {@link #getLeft() left} position.
11886     * This position is post-layout, in addition to wherever the object's
11887     * layout placed it.
11888     *
11889     * @return The horizontal position of this view relative to its left position, in pixels.
11890     */
11891    @ViewDebug.ExportedProperty(category = "drawing")
11892    public float getTranslationX() {
11893        return mRenderNode.getTranslationX();
11894    }
11895
11896    /**
11897     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
11898     * This effectively positions the object post-layout, in addition to wherever the object's
11899     * layout placed it.
11900     *
11901     * @param translationX The horizontal position of this view relative to its left position,
11902     * in pixels.
11903     *
11904     * @attr ref android.R.styleable#View_translationX
11905     */
11906    public void setTranslationX(float translationX) {
11907        if (translationX != getTranslationX()) {
11908            invalidateViewProperty(true, false);
11909            mRenderNode.setTranslationX(translationX);
11910            invalidateViewProperty(false, true);
11911
11912            invalidateParentIfNeededAndWasQuickRejected();
11913            notifySubtreeAccessibilityStateChangedIfNeeded();
11914        }
11915    }
11916
11917    /**
11918     * The vertical location of this view relative to its {@link #getTop() top} position.
11919     * This position is post-layout, in addition to wherever the object's
11920     * layout placed it.
11921     *
11922     * @return The vertical position of this view relative to its top position,
11923     * in pixels.
11924     */
11925    @ViewDebug.ExportedProperty(category = "drawing")
11926    public float getTranslationY() {
11927        return mRenderNode.getTranslationY();
11928    }
11929
11930    /**
11931     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
11932     * This effectively positions the object post-layout, in addition to wherever the object's
11933     * layout placed it.
11934     *
11935     * @param translationY The vertical position of this view relative to its top position,
11936     * in pixels.
11937     *
11938     * @attr ref android.R.styleable#View_translationY
11939     */
11940    public void setTranslationY(float translationY) {
11941        if (translationY != getTranslationY()) {
11942            invalidateViewProperty(true, false);
11943            mRenderNode.setTranslationY(translationY);
11944            invalidateViewProperty(false, true);
11945
11946            invalidateParentIfNeededAndWasQuickRejected();
11947            notifySubtreeAccessibilityStateChangedIfNeeded();
11948        }
11949    }
11950
11951    /**
11952     * The depth location of this view relative to its {@link #getElevation() elevation}.
11953     *
11954     * @return The depth of this view relative to its elevation.
11955     */
11956    @ViewDebug.ExportedProperty(category = "drawing")
11957    public float getTranslationZ() {
11958        return mRenderNode.getTranslationZ();
11959    }
11960
11961    /**
11962     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
11963     *
11964     * @attr ref android.R.styleable#View_translationZ
11965     */
11966    public void setTranslationZ(float translationZ) {
11967        if (translationZ != getTranslationZ()) {
11968            invalidateViewProperty(true, false);
11969            mRenderNode.setTranslationZ(translationZ);
11970            invalidateViewProperty(false, true);
11971
11972            invalidateParentIfNeededAndWasQuickRejected();
11973        }
11974    }
11975
11976    /** @hide */
11977    public void setAnimationMatrix(Matrix matrix) {
11978        invalidateViewProperty(true, false);
11979        mRenderNode.setAnimationMatrix(matrix);
11980        invalidateViewProperty(false, true);
11981
11982        invalidateParentIfNeededAndWasQuickRejected();
11983    }
11984
11985    /**
11986     * Returns the current StateListAnimator if exists.
11987     *
11988     * @return StateListAnimator or null if it does not exists
11989     * @see    #setStateListAnimator(android.animation.StateListAnimator)
11990     */
11991    public StateListAnimator getStateListAnimator() {
11992        return mStateListAnimator;
11993    }
11994
11995    /**
11996     * Attaches the provided StateListAnimator to this View.
11997     * <p>
11998     * Any previously attached StateListAnimator will be detached.
11999     *
12000     * @param stateListAnimator The StateListAnimator to update the view
12001     * @see {@link android.animation.StateListAnimator}
12002     */
12003    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12004        if (mStateListAnimator == stateListAnimator) {
12005            return;
12006        }
12007        if (mStateListAnimator != null) {
12008            mStateListAnimator.setTarget(null);
12009        }
12010        mStateListAnimator = stateListAnimator;
12011        if (stateListAnimator != null) {
12012            stateListAnimator.setTarget(this);
12013            if (isAttachedToWindow()) {
12014                stateListAnimator.setState(getDrawableState());
12015            }
12016        }
12017    }
12018
12019    /**
12020     * Returns whether the Outline should be used to clip the contents of the View.
12021     * <p>
12022     * Note that this flag will only be respected if the View's Outline returns true from
12023     * {@link Outline#canClip()}.
12024     *
12025     * @see #setOutlineProvider(ViewOutlineProvider)
12026     * @see #setClipToOutline(boolean)
12027     */
12028    public final boolean getClipToOutline() {
12029        return mRenderNode.getClipToOutline();
12030    }
12031
12032    /**
12033     * Sets whether the View's Outline should be used to clip the contents of the View.
12034     * <p>
12035     * Only a single non-rectangular clip can be applied on a View at any time.
12036     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12037     * circular reveal} animation take priority over Outline clipping, and
12038     * child Outline clipping takes priority over Outline clipping done by a
12039     * parent.
12040     * <p>
12041     * Note that this flag will only be respected if the View's Outline returns true from
12042     * {@link Outline#canClip()}.
12043     *
12044     * @see #setOutlineProvider(ViewOutlineProvider)
12045     * @see #getClipToOutline()
12046     */
12047    public void setClipToOutline(boolean clipToOutline) {
12048        damageInParent();
12049        if (getClipToOutline() != clipToOutline) {
12050            mRenderNode.setClipToOutline(clipToOutline);
12051        }
12052    }
12053
12054    // correspond to the enum values of View_outlineProvider
12055    private static final int PROVIDER_BACKGROUND = 0;
12056    private static final int PROVIDER_NONE = 1;
12057    private static final int PROVIDER_BOUNDS = 2;
12058    private static final int PROVIDER_PADDED_BOUNDS = 3;
12059    private void setOutlineProviderFromAttribute(int providerInt) {
12060        switch (providerInt) {
12061            case PROVIDER_BACKGROUND:
12062                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12063                break;
12064            case PROVIDER_NONE:
12065                setOutlineProvider(null);
12066                break;
12067            case PROVIDER_BOUNDS:
12068                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12069                break;
12070            case PROVIDER_PADDED_BOUNDS:
12071                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12072                break;
12073        }
12074    }
12075
12076    /**
12077     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12078     * the shape of the shadow it casts, and enables outline clipping.
12079     * <p>
12080     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12081     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12082     * outline provider with this method allows this behavior to be overridden.
12083     * <p>
12084     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12085     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12086     * <p>
12087     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12088     *
12089     * @see #setClipToOutline(boolean)
12090     * @see #getClipToOutline()
12091     * @see #getOutlineProvider()
12092     */
12093    public void setOutlineProvider(ViewOutlineProvider provider) {
12094        mOutlineProvider = provider;
12095        invalidateOutline();
12096    }
12097
12098    /**
12099     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12100     * that defines the shape of the shadow it casts, and enables outline clipping.
12101     *
12102     * @see #setOutlineProvider(ViewOutlineProvider)
12103     */
12104    public ViewOutlineProvider getOutlineProvider() {
12105        return mOutlineProvider;
12106    }
12107
12108    /**
12109     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12110     *
12111     * @see #setOutlineProvider(ViewOutlineProvider)
12112     */
12113    public void invalidateOutline() {
12114        rebuildOutline();
12115
12116        notifySubtreeAccessibilityStateChangedIfNeeded();
12117        invalidateViewProperty(false, false);
12118    }
12119
12120    /**
12121     * Internal version of {@link #invalidateOutline()} which invalidates the
12122     * outline without invalidating the view itself. This is intended to be called from
12123     * within methods in the View class itself which are the result of the view being
12124     * invalidated already. For example, when we are drawing the background of a View,
12125     * we invalidate the outline in case it changed in the meantime, but we do not
12126     * need to invalidate the view because we're already drawing the background as part
12127     * of drawing the view in response to an earlier invalidation of the view.
12128     */
12129    private void rebuildOutline() {
12130        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12131        if (mAttachInfo == null) return;
12132
12133        if (mOutlineProvider == null) {
12134            // no provider, remove outline
12135            mRenderNode.setOutline(null);
12136        } else {
12137            final Outline outline = mAttachInfo.mTmpOutline;
12138            outline.setEmpty();
12139            outline.setAlpha(1.0f);
12140
12141            mOutlineProvider.getOutline(this, outline);
12142            mRenderNode.setOutline(outline);
12143        }
12144    }
12145
12146    /**
12147     * HierarchyViewer only
12148     *
12149     * @hide
12150     */
12151    @ViewDebug.ExportedProperty(category = "drawing")
12152    public boolean hasShadow() {
12153        return mRenderNode.hasShadow();
12154    }
12155
12156
12157    /** @hide */
12158    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12159        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12160        invalidateViewProperty(false, false);
12161    }
12162
12163    /**
12164     * Hit rectangle in parent's coordinates
12165     *
12166     * @param outRect The hit rectangle of the view.
12167     */
12168    public void getHitRect(Rect outRect) {
12169        if (hasIdentityMatrix() || mAttachInfo == null) {
12170            outRect.set(mLeft, mTop, mRight, mBottom);
12171        } else {
12172            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12173            tmpRect.set(0, 0, getWidth(), getHeight());
12174            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12175            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12176                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12177        }
12178    }
12179
12180    /**
12181     * Determines whether the given point, in local coordinates is inside the view.
12182     */
12183    /*package*/ final boolean pointInView(float localX, float localY) {
12184        return localX >= 0 && localX < (mRight - mLeft)
12185                && localY >= 0 && localY < (mBottom - mTop);
12186    }
12187
12188    /**
12189     * Utility method to determine whether the given point, in local coordinates,
12190     * is inside the view, where the area of the view is expanded by the slop factor.
12191     * This method is called while processing touch-move events to determine if the event
12192     * is still within the view.
12193     *
12194     * @hide
12195     */
12196    public boolean pointInView(float localX, float localY, float slop) {
12197        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12198                localY < ((mBottom - mTop) + slop);
12199    }
12200
12201    /**
12202     * When a view has focus and the user navigates away from it, the next view is searched for
12203     * starting from the rectangle filled in by this method.
12204     *
12205     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12206     * of the view.  However, if your view maintains some idea of internal selection,
12207     * such as a cursor, or a selected row or column, you should override this method and
12208     * fill in a more specific rectangle.
12209     *
12210     * @param r The rectangle to fill in, in this view's coordinates.
12211     */
12212    public void getFocusedRect(Rect r) {
12213        getDrawingRect(r);
12214    }
12215
12216    /**
12217     * If some part of this view is not clipped by any of its parents, then
12218     * return that area in r in global (root) coordinates. To convert r to local
12219     * coordinates (without taking possible View rotations into account), offset
12220     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12221     * If the view is completely clipped or translated out, return false.
12222     *
12223     * @param r If true is returned, r holds the global coordinates of the
12224     *        visible portion of this view.
12225     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12226     *        between this view and its root. globalOffet may be null.
12227     * @return true if r is non-empty (i.e. part of the view is visible at the
12228     *         root level.
12229     */
12230    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12231        int width = mRight - mLeft;
12232        int height = mBottom - mTop;
12233        if (width > 0 && height > 0) {
12234            r.set(0, 0, width, height);
12235            if (globalOffset != null) {
12236                globalOffset.set(-mScrollX, -mScrollY);
12237            }
12238            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12239        }
12240        return false;
12241    }
12242
12243    public final boolean getGlobalVisibleRect(Rect r) {
12244        return getGlobalVisibleRect(r, null);
12245    }
12246
12247    public final boolean getLocalVisibleRect(Rect r) {
12248        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12249        if (getGlobalVisibleRect(r, offset)) {
12250            r.offset(-offset.x, -offset.y); // make r local
12251            return true;
12252        }
12253        return false;
12254    }
12255
12256    /**
12257     * Offset this view's vertical location by the specified number of pixels.
12258     *
12259     * @param offset the number of pixels to offset the view by
12260     */
12261    public void offsetTopAndBottom(int offset) {
12262        if (offset != 0) {
12263            final boolean matrixIsIdentity = hasIdentityMatrix();
12264            if (matrixIsIdentity) {
12265                if (isHardwareAccelerated()) {
12266                    invalidateViewProperty(false, false);
12267                } else {
12268                    final ViewParent p = mParent;
12269                    if (p != null && mAttachInfo != null) {
12270                        final Rect r = mAttachInfo.mTmpInvalRect;
12271                        int minTop;
12272                        int maxBottom;
12273                        int yLoc;
12274                        if (offset < 0) {
12275                            minTop = mTop + offset;
12276                            maxBottom = mBottom;
12277                            yLoc = offset;
12278                        } else {
12279                            minTop = mTop;
12280                            maxBottom = mBottom + offset;
12281                            yLoc = 0;
12282                        }
12283                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12284                        p.invalidateChild(this, r);
12285                    }
12286                }
12287            } else {
12288                invalidateViewProperty(false, false);
12289            }
12290
12291            mTop += offset;
12292            mBottom += offset;
12293            mRenderNode.offsetTopAndBottom(offset);
12294            if (isHardwareAccelerated()) {
12295                invalidateViewProperty(false, false);
12296                invalidateParentIfNeededAndWasQuickRejected();
12297            } else {
12298                if (!matrixIsIdentity) {
12299                    invalidateViewProperty(false, true);
12300                }
12301                invalidateParentIfNeeded();
12302            }
12303            notifySubtreeAccessibilityStateChangedIfNeeded();
12304        }
12305    }
12306
12307    /**
12308     * Offset this view's horizontal location by the specified amount of pixels.
12309     *
12310     * @param offset the number of pixels to offset the view by
12311     */
12312    public void offsetLeftAndRight(int offset) {
12313        if (offset != 0) {
12314            final boolean matrixIsIdentity = hasIdentityMatrix();
12315            if (matrixIsIdentity) {
12316                if (isHardwareAccelerated()) {
12317                    invalidateViewProperty(false, false);
12318                } else {
12319                    final ViewParent p = mParent;
12320                    if (p != null && mAttachInfo != null) {
12321                        final Rect r = mAttachInfo.mTmpInvalRect;
12322                        int minLeft;
12323                        int maxRight;
12324                        if (offset < 0) {
12325                            minLeft = mLeft + offset;
12326                            maxRight = mRight;
12327                        } else {
12328                            minLeft = mLeft;
12329                            maxRight = mRight + offset;
12330                        }
12331                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12332                        p.invalidateChild(this, r);
12333                    }
12334                }
12335            } else {
12336                invalidateViewProperty(false, false);
12337            }
12338
12339            mLeft += offset;
12340            mRight += offset;
12341            mRenderNode.offsetLeftAndRight(offset);
12342            if (isHardwareAccelerated()) {
12343                invalidateViewProperty(false, false);
12344                invalidateParentIfNeededAndWasQuickRejected();
12345            } else {
12346                if (!matrixIsIdentity) {
12347                    invalidateViewProperty(false, true);
12348                }
12349                invalidateParentIfNeeded();
12350            }
12351            notifySubtreeAccessibilityStateChangedIfNeeded();
12352        }
12353    }
12354
12355    /**
12356     * Get the LayoutParams associated with this view. All views should have
12357     * layout parameters. These supply parameters to the <i>parent</i> of this
12358     * view specifying how it should be arranged. There are many subclasses of
12359     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12360     * of ViewGroup that are responsible for arranging their children.
12361     *
12362     * This method may return null if this View is not attached to a parent
12363     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12364     * was not invoked successfully. When a View is attached to a parent
12365     * ViewGroup, this method must not return null.
12366     *
12367     * @return The LayoutParams associated with this view, or null if no
12368     *         parameters have been set yet
12369     */
12370    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12371    public ViewGroup.LayoutParams getLayoutParams() {
12372        return mLayoutParams;
12373    }
12374
12375    /**
12376     * Set the layout parameters associated with this view. These supply
12377     * parameters to the <i>parent</i> of this view specifying how it should be
12378     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12379     * correspond to the different subclasses of ViewGroup that are responsible
12380     * for arranging their children.
12381     *
12382     * @param params The layout parameters for this view, cannot be null
12383     */
12384    public void setLayoutParams(ViewGroup.LayoutParams params) {
12385        if (params == null) {
12386            throw new NullPointerException("Layout parameters cannot be null");
12387        }
12388        mLayoutParams = params;
12389        resolveLayoutParams();
12390        if (mParent instanceof ViewGroup) {
12391            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12392        }
12393        requestLayout();
12394    }
12395
12396    /**
12397     * Resolve the layout parameters depending on the resolved layout direction
12398     *
12399     * @hide
12400     */
12401    public void resolveLayoutParams() {
12402        if (mLayoutParams != null) {
12403            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12404        }
12405    }
12406
12407    /**
12408     * Set the scrolled position of your view. This will cause a call to
12409     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12410     * invalidated.
12411     * @param x the x position to scroll to
12412     * @param y the y position to scroll to
12413     */
12414    public void scrollTo(int x, int y) {
12415        if (mScrollX != x || mScrollY != y) {
12416            int oldX = mScrollX;
12417            int oldY = mScrollY;
12418            mScrollX = x;
12419            mScrollY = y;
12420            invalidateParentCaches();
12421            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12422            if (!awakenScrollBars()) {
12423                postInvalidateOnAnimation();
12424            }
12425        }
12426    }
12427
12428    /**
12429     * Move the scrolled position of your view. This will cause a call to
12430     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12431     * invalidated.
12432     * @param x the amount of pixels to scroll by horizontally
12433     * @param y the amount of pixels to scroll by vertically
12434     */
12435    public void scrollBy(int x, int y) {
12436        scrollTo(mScrollX + x, mScrollY + y);
12437    }
12438
12439    /**
12440     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12441     * animation to fade the scrollbars out after a default delay. If a subclass
12442     * provides animated scrolling, the start delay should equal the duration
12443     * of the scrolling animation.</p>
12444     *
12445     * <p>The animation starts only if at least one of the scrollbars is
12446     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12447     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12448     * this method returns true, and false otherwise. If the animation is
12449     * started, this method calls {@link #invalidate()}; in that case the
12450     * caller should not call {@link #invalidate()}.</p>
12451     *
12452     * <p>This method should be invoked every time a subclass directly updates
12453     * the scroll parameters.</p>
12454     *
12455     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12456     * and {@link #scrollTo(int, int)}.</p>
12457     *
12458     * @return true if the animation is played, false otherwise
12459     *
12460     * @see #awakenScrollBars(int)
12461     * @see #scrollBy(int, int)
12462     * @see #scrollTo(int, int)
12463     * @see #isHorizontalScrollBarEnabled()
12464     * @see #isVerticalScrollBarEnabled()
12465     * @see #setHorizontalScrollBarEnabled(boolean)
12466     * @see #setVerticalScrollBarEnabled(boolean)
12467     */
12468    protected boolean awakenScrollBars() {
12469        return mScrollCache != null &&
12470                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12471    }
12472
12473    /**
12474     * Trigger the scrollbars to draw.
12475     * This method differs from awakenScrollBars() only in its default duration.
12476     * initialAwakenScrollBars() will show the scroll bars for longer than
12477     * usual to give the user more of a chance to notice them.
12478     *
12479     * @return true if the animation is played, false otherwise.
12480     */
12481    private boolean initialAwakenScrollBars() {
12482        return mScrollCache != null &&
12483                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12484    }
12485
12486    /**
12487     * <p>
12488     * Trigger the scrollbars to draw. When invoked this method starts an
12489     * animation to fade the scrollbars out after a fixed delay. If a subclass
12490     * provides animated scrolling, the start delay should equal the duration of
12491     * the scrolling animation.
12492     * </p>
12493     *
12494     * <p>
12495     * The animation starts only if at least one of the scrollbars is enabled,
12496     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12497     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12498     * this method returns true, and false otherwise. If the animation is
12499     * started, this method calls {@link #invalidate()}; in that case the caller
12500     * should not call {@link #invalidate()}.
12501     * </p>
12502     *
12503     * <p>
12504     * This method should be invoked every time a subclass directly updates the
12505     * scroll parameters.
12506     * </p>
12507     *
12508     * @param startDelay the delay, in milliseconds, after which the animation
12509     *        should start; when the delay is 0, the animation starts
12510     *        immediately
12511     * @return true if the animation is played, false otherwise
12512     *
12513     * @see #scrollBy(int, int)
12514     * @see #scrollTo(int, int)
12515     * @see #isHorizontalScrollBarEnabled()
12516     * @see #isVerticalScrollBarEnabled()
12517     * @see #setHorizontalScrollBarEnabled(boolean)
12518     * @see #setVerticalScrollBarEnabled(boolean)
12519     */
12520    protected boolean awakenScrollBars(int startDelay) {
12521        return awakenScrollBars(startDelay, true);
12522    }
12523
12524    /**
12525     * <p>
12526     * Trigger the scrollbars to draw. When invoked this method starts an
12527     * animation to fade the scrollbars out after a fixed delay. If a subclass
12528     * provides animated scrolling, the start delay should equal the duration of
12529     * the scrolling animation.
12530     * </p>
12531     *
12532     * <p>
12533     * The animation starts only if at least one of the scrollbars is enabled,
12534     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12535     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12536     * this method returns true, and false otherwise. If the animation is
12537     * started, this method calls {@link #invalidate()} if the invalidate parameter
12538     * is set to true; in that case the caller
12539     * should not call {@link #invalidate()}.
12540     * </p>
12541     *
12542     * <p>
12543     * This method should be invoked every time a subclass directly updates the
12544     * scroll parameters.
12545     * </p>
12546     *
12547     * @param startDelay the delay, in milliseconds, after which the animation
12548     *        should start; when the delay is 0, the animation starts
12549     *        immediately
12550     *
12551     * @param invalidate Whether this method should call invalidate
12552     *
12553     * @return true if the animation is played, false otherwise
12554     *
12555     * @see #scrollBy(int, int)
12556     * @see #scrollTo(int, int)
12557     * @see #isHorizontalScrollBarEnabled()
12558     * @see #isVerticalScrollBarEnabled()
12559     * @see #setHorizontalScrollBarEnabled(boolean)
12560     * @see #setVerticalScrollBarEnabled(boolean)
12561     */
12562    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12563        final ScrollabilityCache scrollCache = mScrollCache;
12564
12565        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12566            return false;
12567        }
12568
12569        if (scrollCache.scrollBar == null) {
12570            scrollCache.scrollBar = new ScrollBarDrawable();
12571            scrollCache.scrollBar.setCallback(this);
12572            scrollCache.scrollBar.setState(getDrawableState());
12573        }
12574
12575        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12576
12577            if (invalidate) {
12578                // Invalidate to show the scrollbars
12579                postInvalidateOnAnimation();
12580            }
12581
12582            if (scrollCache.state == ScrollabilityCache.OFF) {
12583                // FIXME: this is copied from WindowManagerService.
12584                // We should get this value from the system when it
12585                // is possible to do so.
12586                final int KEY_REPEAT_FIRST_DELAY = 750;
12587                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12588            }
12589
12590            // Tell mScrollCache when we should start fading. This may
12591            // extend the fade start time if one was already scheduled
12592            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12593            scrollCache.fadeStartTime = fadeStartTime;
12594            scrollCache.state = ScrollabilityCache.ON;
12595
12596            // Schedule our fader to run, unscheduling any old ones first
12597            if (mAttachInfo != null) {
12598                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12599                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12600            }
12601
12602            return true;
12603        }
12604
12605        return false;
12606    }
12607
12608    /**
12609     * Do not invalidate views which are not visible and which are not running an animation. They
12610     * will not get drawn and they should not set dirty flags as if they will be drawn
12611     */
12612    private boolean skipInvalidate() {
12613        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12614                (!(mParent instanceof ViewGroup) ||
12615                        !((ViewGroup) mParent).isViewTransitioning(this));
12616    }
12617
12618    /**
12619     * Mark the area defined by dirty as needing to be drawn. If the view is
12620     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12621     * point in the future.
12622     * <p>
12623     * This must be called from a UI thread. To call from a non-UI thread, call
12624     * {@link #postInvalidate()}.
12625     * <p>
12626     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12627     * {@code dirty}.
12628     *
12629     * @param dirty the rectangle representing the bounds of the dirty region
12630     */
12631    public void invalidate(Rect dirty) {
12632        final int scrollX = mScrollX;
12633        final int scrollY = mScrollY;
12634        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12635                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12636    }
12637
12638    /**
12639     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12640     * coordinates of the dirty rect are relative to the view. If the view is
12641     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12642     * point in the future.
12643     * <p>
12644     * This must be called from a UI thread. To call from a non-UI thread, call
12645     * {@link #postInvalidate()}.
12646     *
12647     * @param l the left position of the dirty region
12648     * @param t the top position of the dirty region
12649     * @param r the right position of the dirty region
12650     * @param b the bottom position of the dirty region
12651     */
12652    public void invalidate(int l, int t, int r, int b) {
12653        final int scrollX = mScrollX;
12654        final int scrollY = mScrollY;
12655        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12656    }
12657
12658    /**
12659     * Invalidate the whole view. If the view is visible,
12660     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12661     * the future.
12662     * <p>
12663     * This must be called from a UI thread. To call from a non-UI thread, call
12664     * {@link #postInvalidate()}.
12665     */
12666    public void invalidate() {
12667        invalidate(true);
12668    }
12669
12670    /**
12671     * This is where the invalidate() work actually happens. A full invalidate()
12672     * causes the drawing cache to be invalidated, but this function can be
12673     * called with invalidateCache set to false to skip that invalidation step
12674     * for cases that do not need it (for example, a component that remains at
12675     * the same dimensions with the same content).
12676     *
12677     * @param invalidateCache Whether the drawing cache for this view should be
12678     *            invalidated as well. This is usually true for a full
12679     *            invalidate, but may be set to false if the View's contents or
12680     *            dimensions have not changed.
12681     */
12682    void invalidate(boolean invalidateCache) {
12683        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12684    }
12685
12686    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12687            boolean fullInvalidate) {
12688        if (mGhostView != null) {
12689            mGhostView.invalidate(true);
12690            return;
12691        }
12692
12693        if (skipInvalidate()) {
12694            return;
12695        }
12696
12697        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12698                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12699                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12700                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12701            if (fullInvalidate) {
12702                mLastIsOpaque = isOpaque();
12703                mPrivateFlags &= ~PFLAG_DRAWN;
12704            }
12705
12706            mPrivateFlags |= PFLAG_DIRTY;
12707
12708            if (invalidateCache) {
12709                mPrivateFlags |= PFLAG_INVALIDATED;
12710                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12711            }
12712
12713            // Propagate the damage rectangle to the parent view.
12714            final AttachInfo ai = mAttachInfo;
12715            final ViewParent p = mParent;
12716            if (p != null && ai != null && l < r && t < b) {
12717                final Rect damage = ai.mTmpInvalRect;
12718                damage.set(l, t, r, b);
12719                p.invalidateChild(this, damage);
12720            }
12721
12722            // Damage the entire projection receiver, if necessary.
12723            if (mBackground != null && mBackground.isProjected()) {
12724                final View receiver = getProjectionReceiver();
12725                if (receiver != null) {
12726                    receiver.damageInParent();
12727                }
12728            }
12729
12730            // Damage the entire IsolatedZVolume receiving this view's shadow.
12731            if (isHardwareAccelerated() && getZ() != 0) {
12732                damageShadowReceiver();
12733            }
12734        }
12735    }
12736
12737    /**
12738     * @return this view's projection receiver, or {@code null} if none exists
12739     */
12740    private View getProjectionReceiver() {
12741        ViewParent p = getParent();
12742        while (p != null && p instanceof View) {
12743            final View v = (View) p;
12744            if (v.isProjectionReceiver()) {
12745                return v;
12746            }
12747            p = p.getParent();
12748        }
12749
12750        return null;
12751    }
12752
12753    /**
12754     * @return whether the view is a projection receiver
12755     */
12756    private boolean isProjectionReceiver() {
12757        return mBackground != null;
12758    }
12759
12760    /**
12761     * Damage area of the screen that can be covered by this View's shadow.
12762     *
12763     * This method will guarantee that any changes to shadows cast by a View
12764     * are damaged on the screen for future redraw.
12765     */
12766    private void damageShadowReceiver() {
12767        final AttachInfo ai = mAttachInfo;
12768        if (ai != null) {
12769            ViewParent p = getParent();
12770            if (p != null && p instanceof ViewGroup) {
12771                final ViewGroup vg = (ViewGroup) p;
12772                vg.damageInParent();
12773            }
12774        }
12775    }
12776
12777    /**
12778     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
12779     * set any flags or handle all of the cases handled by the default invalidation methods.
12780     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
12781     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
12782     * walk up the hierarchy, transforming the dirty rect as necessary.
12783     *
12784     * The method also handles normal invalidation logic if display list properties are not
12785     * being used in this view. The invalidateParent and forceRedraw flags are used by that
12786     * backup approach, to handle these cases used in the various property-setting methods.
12787     *
12788     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
12789     * are not being used in this view
12790     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
12791     * list properties are not being used in this view
12792     */
12793    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
12794        if (!isHardwareAccelerated()
12795                || !mRenderNode.isValid()
12796                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
12797            if (invalidateParent) {
12798                invalidateParentCaches();
12799            }
12800            if (forceRedraw) {
12801                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12802            }
12803            invalidate(false);
12804        } else {
12805            damageInParent();
12806        }
12807        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
12808            damageShadowReceiver();
12809        }
12810    }
12811
12812    /**
12813     * Tells the parent view to damage this view's bounds.
12814     *
12815     * @hide
12816     */
12817    protected void damageInParent() {
12818        final AttachInfo ai = mAttachInfo;
12819        final ViewParent p = mParent;
12820        if (p != null && ai != null) {
12821            final Rect r = ai.mTmpInvalRect;
12822            r.set(0, 0, mRight - mLeft, mBottom - mTop);
12823            if (mParent instanceof ViewGroup) {
12824                ((ViewGroup) mParent).damageChild(this, r);
12825            } else {
12826                mParent.invalidateChild(this, r);
12827            }
12828        }
12829    }
12830
12831    /**
12832     * Utility method to transform a given Rect by the current matrix of this view.
12833     */
12834    void transformRect(final Rect rect) {
12835        if (!getMatrix().isIdentity()) {
12836            RectF boundingRect = mAttachInfo.mTmpTransformRect;
12837            boundingRect.set(rect);
12838            getMatrix().mapRect(boundingRect);
12839            rect.set((int) Math.floor(boundingRect.left),
12840                    (int) Math.floor(boundingRect.top),
12841                    (int) Math.ceil(boundingRect.right),
12842                    (int) Math.ceil(boundingRect.bottom));
12843        }
12844    }
12845
12846    /**
12847     * Used to indicate that the parent of this view should clear its caches. This functionality
12848     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12849     * which is necessary when various parent-managed properties of the view change, such as
12850     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
12851     * clears the parent caches and does not causes an invalidate event.
12852     *
12853     * @hide
12854     */
12855    protected void invalidateParentCaches() {
12856        if (mParent instanceof View) {
12857            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
12858        }
12859    }
12860
12861    /**
12862     * Used to indicate that the parent of this view should be invalidated. This functionality
12863     * is used to force the parent to rebuild its display list (when hardware-accelerated),
12864     * which is necessary when various parent-managed properties of the view change, such as
12865     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
12866     * an invalidation event to the parent.
12867     *
12868     * @hide
12869     */
12870    protected void invalidateParentIfNeeded() {
12871        if (isHardwareAccelerated() && mParent instanceof View) {
12872            ((View) mParent).invalidate(true);
12873        }
12874    }
12875
12876    /**
12877     * @hide
12878     */
12879    protected void invalidateParentIfNeededAndWasQuickRejected() {
12880        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
12881            // View was rejected last time it was drawn by its parent; this may have changed
12882            invalidateParentIfNeeded();
12883        }
12884    }
12885
12886    /**
12887     * Indicates whether this View is opaque. An opaque View guarantees that it will
12888     * draw all the pixels overlapping its bounds using a fully opaque color.
12889     *
12890     * Subclasses of View should override this method whenever possible to indicate
12891     * whether an instance is opaque. Opaque Views are treated in a special way by
12892     * the View hierarchy, possibly allowing it to perform optimizations during
12893     * invalidate/draw passes.
12894     *
12895     * @return True if this View is guaranteed to be fully opaque, false otherwise.
12896     */
12897    @ViewDebug.ExportedProperty(category = "drawing")
12898    public boolean isOpaque() {
12899        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
12900                getFinalAlpha() >= 1.0f;
12901    }
12902
12903    /**
12904     * @hide
12905     */
12906    protected void computeOpaqueFlags() {
12907        // Opaque if:
12908        //   - Has a background
12909        //   - Background is opaque
12910        //   - Doesn't have scrollbars or scrollbars overlay
12911
12912        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
12913            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
12914        } else {
12915            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
12916        }
12917
12918        final int flags = mViewFlags;
12919        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
12920                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
12921                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
12922            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
12923        } else {
12924            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
12925        }
12926    }
12927
12928    /**
12929     * @hide
12930     */
12931    protected boolean hasOpaqueScrollbars() {
12932        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
12933    }
12934
12935    /**
12936     * @return A handler associated with the thread running the View. This
12937     * handler can be used to pump events in the UI events queue.
12938     */
12939    public Handler getHandler() {
12940        final AttachInfo attachInfo = mAttachInfo;
12941        if (attachInfo != null) {
12942            return attachInfo.mHandler;
12943        }
12944        return null;
12945    }
12946
12947    /**
12948     * Gets the view root associated with the View.
12949     * @return The view root, or null if none.
12950     * @hide
12951     */
12952    public ViewRootImpl getViewRootImpl() {
12953        if (mAttachInfo != null) {
12954            return mAttachInfo.mViewRootImpl;
12955        }
12956        return null;
12957    }
12958
12959    /**
12960     * @hide
12961     */
12962    public HardwareRenderer getHardwareRenderer() {
12963        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
12964    }
12965
12966    /**
12967     * <p>Causes the Runnable to be added to the message queue.
12968     * The runnable will be run on the user interface thread.</p>
12969     *
12970     * @param action The Runnable that will be executed.
12971     *
12972     * @return Returns true if the Runnable was successfully placed in to the
12973     *         message queue.  Returns false on failure, usually because the
12974     *         looper processing the message queue is exiting.
12975     *
12976     * @see #postDelayed
12977     * @see #removeCallbacks
12978     */
12979    public boolean post(Runnable action) {
12980        final AttachInfo attachInfo = mAttachInfo;
12981        if (attachInfo != null) {
12982            return attachInfo.mHandler.post(action);
12983        }
12984        // Assume that post will succeed later
12985        ViewRootImpl.getRunQueue().post(action);
12986        return true;
12987    }
12988
12989    /**
12990     * <p>Causes the Runnable to be added to the message queue, to be run
12991     * after the specified amount of time elapses.
12992     * The runnable will be run on the user interface thread.</p>
12993     *
12994     * @param action The Runnable that will be executed.
12995     * @param delayMillis The delay (in milliseconds) until the Runnable
12996     *        will be executed.
12997     *
12998     * @return true if the Runnable was successfully placed in to the
12999     *         message queue.  Returns false on failure, usually because the
13000     *         looper processing the message queue is exiting.  Note that a
13001     *         result of true does not mean the Runnable will be processed --
13002     *         if the looper is quit before the delivery time of the message
13003     *         occurs then the message will be dropped.
13004     *
13005     * @see #post
13006     * @see #removeCallbacks
13007     */
13008    public boolean postDelayed(Runnable action, long delayMillis) {
13009        final AttachInfo attachInfo = mAttachInfo;
13010        if (attachInfo != null) {
13011            return attachInfo.mHandler.postDelayed(action, delayMillis);
13012        }
13013        // Assume that post will succeed later
13014        ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13015        return true;
13016    }
13017
13018    /**
13019     * <p>Causes the Runnable to execute on the next animation time step.
13020     * The runnable will be run on the user interface thread.</p>
13021     *
13022     * @param action The Runnable that will be executed.
13023     *
13024     * @see #postOnAnimationDelayed
13025     * @see #removeCallbacks
13026     */
13027    public void postOnAnimation(Runnable action) {
13028        final AttachInfo attachInfo = mAttachInfo;
13029        if (attachInfo != null) {
13030            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13031                    Choreographer.CALLBACK_ANIMATION, action, null);
13032        } else {
13033            // Assume that post will succeed later
13034            ViewRootImpl.getRunQueue().post(action);
13035        }
13036    }
13037
13038    /**
13039     * <p>Causes the Runnable to execute on the next animation time step,
13040     * after the specified amount of time elapses.
13041     * The runnable will be run on the user interface thread.</p>
13042     *
13043     * @param action The Runnable that will be executed.
13044     * @param delayMillis The delay (in milliseconds) until the Runnable
13045     *        will be executed.
13046     *
13047     * @see #postOnAnimation
13048     * @see #removeCallbacks
13049     */
13050    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13051        final AttachInfo attachInfo = mAttachInfo;
13052        if (attachInfo != null) {
13053            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13054                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13055        } else {
13056            // Assume that post will succeed later
13057            ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
13058        }
13059    }
13060
13061    /**
13062     * <p>Removes the specified Runnable from the message queue.</p>
13063     *
13064     * @param action The Runnable to remove from the message handling queue
13065     *
13066     * @return true if this view could ask the Handler to remove the Runnable,
13067     *         false otherwise. When the returned value is true, the Runnable
13068     *         may or may not have been actually removed from the message queue
13069     *         (for instance, if the Runnable was not in the queue already.)
13070     *
13071     * @see #post
13072     * @see #postDelayed
13073     * @see #postOnAnimation
13074     * @see #postOnAnimationDelayed
13075     */
13076    public boolean removeCallbacks(Runnable action) {
13077        if (action != null) {
13078            final AttachInfo attachInfo = mAttachInfo;
13079            if (attachInfo != null) {
13080                attachInfo.mHandler.removeCallbacks(action);
13081                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13082                        Choreographer.CALLBACK_ANIMATION, action, null);
13083            }
13084            // Assume that post will succeed later
13085            ViewRootImpl.getRunQueue().removeCallbacks(action);
13086        }
13087        return true;
13088    }
13089
13090    /**
13091     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13092     * Use this to invalidate the View from a non-UI thread.</p>
13093     *
13094     * <p>This method can be invoked from outside of the UI thread
13095     * only when this View is attached to a window.</p>
13096     *
13097     * @see #invalidate()
13098     * @see #postInvalidateDelayed(long)
13099     */
13100    public void postInvalidate() {
13101        postInvalidateDelayed(0);
13102    }
13103
13104    /**
13105     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13106     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13107     *
13108     * <p>This method can be invoked from outside of the UI thread
13109     * only when this View is attached to a window.</p>
13110     *
13111     * @param left The left coordinate of the rectangle to invalidate.
13112     * @param top The top coordinate of the rectangle to invalidate.
13113     * @param right The right coordinate of the rectangle to invalidate.
13114     * @param bottom The bottom coordinate of the rectangle to invalidate.
13115     *
13116     * @see #invalidate(int, int, int, int)
13117     * @see #invalidate(Rect)
13118     * @see #postInvalidateDelayed(long, int, int, int, int)
13119     */
13120    public void postInvalidate(int left, int top, int right, int bottom) {
13121        postInvalidateDelayed(0, left, top, right, bottom);
13122    }
13123
13124    /**
13125     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13126     * loop. Waits for the specified amount of time.</p>
13127     *
13128     * <p>This method can be invoked from outside of the UI thread
13129     * only when this View is attached to a window.</p>
13130     *
13131     * @param delayMilliseconds the duration in milliseconds to delay the
13132     *         invalidation by
13133     *
13134     * @see #invalidate()
13135     * @see #postInvalidate()
13136     */
13137    public void postInvalidateDelayed(long delayMilliseconds) {
13138        // We try only with the AttachInfo because there's no point in invalidating
13139        // if we are not attached to our window
13140        final AttachInfo attachInfo = mAttachInfo;
13141        if (attachInfo != null) {
13142            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13143        }
13144    }
13145
13146    /**
13147     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13148     * through the event loop. Waits for the specified amount of time.</p>
13149     *
13150     * <p>This method can be invoked from outside of the UI thread
13151     * only when this View is attached to a window.</p>
13152     *
13153     * @param delayMilliseconds the duration in milliseconds to delay the
13154     *         invalidation by
13155     * @param left The left coordinate of the rectangle to invalidate.
13156     * @param top The top coordinate of the rectangle to invalidate.
13157     * @param right The right coordinate of the rectangle to invalidate.
13158     * @param bottom The bottom coordinate of the rectangle to invalidate.
13159     *
13160     * @see #invalidate(int, int, int, int)
13161     * @see #invalidate(Rect)
13162     * @see #postInvalidate(int, int, int, int)
13163     */
13164    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13165            int right, int bottom) {
13166
13167        // We try only with the AttachInfo because there's no point in invalidating
13168        // if we are not attached to our window
13169        final AttachInfo attachInfo = mAttachInfo;
13170        if (attachInfo != null) {
13171            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13172            info.target = this;
13173            info.left = left;
13174            info.top = top;
13175            info.right = right;
13176            info.bottom = bottom;
13177
13178            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13179        }
13180    }
13181
13182    /**
13183     * <p>Cause an invalidate to happen on the next animation time step, typically the
13184     * next display frame.</p>
13185     *
13186     * <p>This method can be invoked from outside of the UI thread
13187     * only when this View is attached to a window.</p>
13188     *
13189     * @see #invalidate()
13190     */
13191    public void postInvalidateOnAnimation() {
13192        // We try only with the AttachInfo because there's no point in invalidating
13193        // if we are not attached to our window
13194        final AttachInfo attachInfo = mAttachInfo;
13195        if (attachInfo != null) {
13196            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13197        }
13198    }
13199
13200    /**
13201     * <p>Cause an invalidate of the specified area to happen on the next animation
13202     * time step, typically the next display frame.</p>
13203     *
13204     * <p>This method can be invoked from outside of the UI thread
13205     * only when this View is attached to a window.</p>
13206     *
13207     * @param left The left coordinate of the rectangle to invalidate.
13208     * @param top The top coordinate of the rectangle to invalidate.
13209     * @param right The right coordinate of the rectangle to invalidate.
13210     * @param bottom The bottom coordinate of the rectangle to invalidate.
13211     *
13212     * @see #invalidate(int, int, int, int)
13213     * @see #invalidate(Rect)
13214     */
13215    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13216        // We try only with the AttachInfo because there's no point in invalidating
13217        // if we are not attached to our window
13218        final AttachInfo attachInfo = mAttachInfo;
13219        if (attachInfo != null) {
13220            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13221            info.target = this;
13222            info.left = left;
13223            info.top = top;
13224            info.right = right;
13225            info.bottom = bottom;
13226
13227            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13228        }
13229    }
13230
13231    /**
13232     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13233     * This event is sent at most once every
13234     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13235     */
13236    private void postSendViewScrolledAccessibilityEventCallback() {
13237        if (mSendViewScrolledAccessibilityEvent == null) {
13238            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13239        }
13240        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13241            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13242            postDelayed(mSendViewScrolledAccessibilityEvent,
13243                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13244        }
13245    }
13246
13247    /**
13248     * Called by a parent to request that a child update its values for mScrollX
13249     * and mScrollY if necessary. This will typically be done if the child is
13250     * animating a scroll using a {@link android.widget.Scroller Scroller}
13251     * object.
13252     */
13253    public void computeScroll() {
13254    }
13255
13256    /**
13257     * <p>Indicate whether the horizontal edges are faded when the view is
13258     * scrolled horizontally.</p>
13259     *
13260     * @return true if the horizontal edges should are faded on scroll, false
13261     *         otherwise
13262     *
13263     * @see #setHorizontalFadingEdgeEnabled(boolean)
13264     *
13265     * @attr ref android.R.styleable#View_requiresFadingEdge
13266     */
13267    public boolean isHorizontalFadingEdgeEnabled() {
13268        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13269    }
13270
13271    /**
13272     * <p>Define whether the horizontal edges should be faded when this view
13273     * is scrolled horizontally.</p>
13274     *
13275     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13276     *                                    be faded when the view is scrolled
13277     *                                    horizontally
13278     *
13279     * @see #isHorizontalFadingEdgeEnabled()
13280     *
13281     * @attr ref android.R.styleable#View_requiresFadingEdge
13282     */
13283    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13284        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13285            if (horizontalFadingEdgeEnabled) {
13286                initScrollCache();
13287            }
13288
13289            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13290        }
13291    }
13292
13293    /**
13294     * <p>Indicate whether the vertical edges are faded when the view is
13295     * scrolled horizontally.</p>
13296     *
13297     * @return true if the vertical edges should are faded on scroll, false
13298     *         otherwise
13299     *
13300     * @see #setVerticalFadingEdgeEnabled(boolean)
13301     *
13302     * @attr ref android.R.styleable#View_requiresFadingEdge
13303     */
13304    public boolean isVerticalFadingEdgeEnabled() {
13305        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13306    }
13307
13308    /**
13309     * <p>Define whether the vertical edges should be faded when this view
13310     * is scrolled vertically.</p>
13311     *
13312     * @param verticalFadingEdgeEnabled true if the vertical edges should
13313     *                                  be faded when the view is scrolled
13314     *                                  vertically
13315     *
13316     * @see #isVerticalFadingEdgeEnabled()
13317     *
13318     * @attr ref android.R.styleable#View_requiresFadingEdge
13319     */
13320    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13321        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13322            if (verticalFadingEdgeEnabled) {
13323                initScrollCache();
13324            }
13325
13326            mViewFlags ^= FADING_EDGE_VERTICAL;
13327        }
13328    }
13329
13330    /**
13331     * Returns the strength, or intensity, of the top faded edge. The strength is
13332     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13333     * returns 0.0 or 1.0 but no value in between.
13334     *
13335     * Subclasses should override this method to provide a smoother fade transition
13336     * when scrolling occurs.
13337     *
13338     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13339     */
13340    protected float getTopFadingEdgeStrength() {
13341        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13342    }
13343
13344    /**
13345     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13346     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13347     * returns 0.0 or 1.0 but no value in between.
13348     *
13349     * Subclasses should override this method to provide a smoother fade transition
13350     * when scrolling occurs.
13351     *
13352     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13353     */
13354    protected float getBottomFadingEdgeStrength() {
13355        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13356                computeVerticalScrollRange() ? 1.0f : 0.0f;
13357    }
13358
13359    /**
13360     * Returns the strength, or intensity, of the left faded edge. The strength is
13361     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13362     * returns 0.0 or 1.0 but no value in between.
13363     *
13364     * Subclasses should override this method to provide a smoother fade transition
13365     * when scrolling occurs.
13366     *
13367     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13368     */
13369    protected float getLeftFadingEdgeStrength() {
13370        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13371    }
13372
13373    /**
13374     * Returns the strength, or intensity, of the right faded edge. The strength is
13375     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13376     * returns 0.0 or 1.0 but no value in between.
13377     *
13378     * Subclasses should override this method to provide a smoother fade transition
13379     * when scrolling occurs.
13380     *
13381     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13382     */
13383    protected float getRightFadingEdgeStrength() {
13384        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13385                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13386    }
13387
13388    /**
13389     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13390     * scrollbar is not drawn by default.</p>
13391     *
13392     * @return true if the horizontal scrollbar should be painted, false
13393     *         otherwise
13394     *
13395     * @see #setHorizontalScrollBarEnabled(boolean)
13396     */
13397    public boolean isHorizontalScrollBarEnabled() {
13398        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13399    }
13400
13401    /**
13402     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13403     * scrollbar is not drawn by default.</p>
13404     *
13405     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13406     *                                   be painted
13407     *
13408     * @see #isHorizontalScrollBarEnabled()
13409     */
13410    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13411        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13412            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13413            computeOpaqueFlags();
13414            resolvePadding();
13415        }
13416    }
13417
13418    /**
13419     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13420     * scrollbar is not drawn by default.</p>
13421     *
13422     * @return true if the vertical scrollbar should be painted, false
13423     *         otherwise
13424     *
13425     * @see #setVerticalScrollBarEnabled(boolean)
13426     */
13427    public boolean isVerticalScrollBarEnabled() {
13428        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13429    }
13430
13431    /**
13432     * <p>Define whether the vertical scrollbar should be drawn or not. The
13433     * scrollbar is not drawn by default.</p>
13434     *
13435     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13436     *                                 be painted
13437     *
13438     * @see #isVerticalScrollBarEnabled()
13439     */
13440    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13441        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13442            mViewFlags ^= SCROLLBARS_VERTICAL;
13443            computeOpaqueFlags();
13444            resolvePadding();
13445        }
13446    }
13447
13448    /**
13449     * @hide
13450     */
13451    protected void recomputePadding() {
13452        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13453    }
13454
13455    /**
13456     * Define whether scrollbars will fade when the view is not scrolling.
13457     *
13458     * @param fadeScrollbars whether to enable fading
13459     *
13460     * @attr ref android.R.styleable#View_fadeScrollbars
13461     */
13462    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13463        initScrollCache();
13464        final ScrollabilityCache scrollabilityCache = mScrollCache;
13465        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13466        if (fadeScrollbars) {
13467            scrollabilityCache.state = ScrollabilityCache.OFF;
13468        } else {
13469            scrollabilityCache.state = ScrollabilityCache.ON;
13470        }
13471    }
13472
13473    /**
13474     *
13475     * Returns true if scrollbars will fade when this view is not scrolling
13476     *
13477     * @return true if scrollbar fading is enabled
13478     *
13479     * @attr ref android.R.styleable#View_fadeScrollbars
13480     */
13481    public boolean isScrollbarFadingEnabled() {
13482        return mScrollCache != null && mScrollCache.fadeScrollBars;
13483    }
13484
13485    /**
13486     *
13487     * Returns the delay before scrollbars fade.
13488     *
13489     * @return the delay before scrollbars fade
13490     *
13491     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13492     */
13493    public int getScrollBarDefaultDelayBeforeFade() {
13494        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13495                mScrollCache.scrollBarDefaultDelayBeforeFade;
13496    }
13497
13498    /**
13499     * Define the delay before scrollbars fade.
13500     *
13501     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13502     *
13503     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13504     */
13505    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13506        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13507    }
13508
13509    /**
13510     *
13511     * Returns the scrollbar fade duration.
13512     *
13513     * @return the scrollbar fade duration
13514     *
13515     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13516     */
13517    public int getScrollBarFadeDuration() {
13518        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13519                mScrollCache.scrollBarFadeDuration;
13520    }
13521
13522    /**
13523     * Define the scrollbar fade duration.
13524     *
13525     * @param scrollBarFadeDuration - the scrollbar fade duration
13526     *
13527     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13528     */
13529    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13530        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13531    }
13532
13533    /**
13534     *
13535     * Returns the scrollbar size.
13536     *
13537     * @return the scrollbar size
13538     *
13539     * @attr ref android.R.styleable#View_scrollbarSize
13540     */
13541    public int getScrollBarSize() {
13542        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13543                mScrollCache.scrollBarSize;
13544    }
13545
13546    /**
13547     * Define the scrollbar size.
13548     *
13549     * @param scrollBarSize - the scrollbar size
13550     *
13551     * @attr ref android.R.styleable#View_scrollbarSize
13552     */
13553    public void setScrollBarSize(int scrollBarSize) {
13554        getScrollCache().scrollBarSize = scrollBarSize;
13555    }
13556
13557    /**
13558     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13559     * inset. When inset, they add to the padding of the view. And the scrollbars
13560     * can be drawn inside the padding area or on the edge of the view. For example,
13561     * if a view has a background drawable and you want to draw the scrollbars
13562     * inside the padding specified by the drawable, you can use
13563     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13564     * appear at the edge of the view, ignoring the padding, then you can use
13565     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13566     * @param style the style of the scrollbars. Should be one of
13567     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13568     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13569     * @see #SCROLLBARS_INSIDE_OVERLAY
13570     * @see #SCROLLBARS_INSIDE_INSET
13571     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13572     * @see #SCROLLBARS_OUTSIDE_INSET
13573     *
13574     * @attr ref android.R.styleable#View_scrollbarStyle
13575     */
13576    public void setScrollBarStyle(@ScrollBarStyle int style) {
13577        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13578            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13579            computeOpaqueFlags();
13580            resolvePadding();
13581        }
13582    }
13583
13584    /**
13585     * <p>Returns the current scrollbar style.</p>
13586     * @return the current scrollbar style
13587     * @see #SCROLLBARS_INSIDE_OVERLAY
13588     * @see #SCROLLBARS_INSIDE_INSET
13589     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13590     * @see #SCROLLBARS_OUTSIDE_INSET
13591     *
13592     * @attr ref android.R.styleable#View_scrollbarStyle
13593     */
13594    @ViewDebug.ExportedProperty(mapping = {
13595            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13596            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13597            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13598            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13599    })
13600    @ScrollBarStyle
13601    public int getScrollBarStyle() {
13602        return mViewFlags & SCROLLBARS_STYLE_MASK;
13603    }
13604
13605    /**
13606     * <p>Compute the horizontal range that the horizontal scrollbar
13607     * represents.</p>
13608     *
13609     * <p>The range is expressed in arbitrary units that must be the same as the
13610     * units used by {@link #computeHorizontalScrollExtent()} and
13611     * {@link #computeHorizontalScrollOffset()}.</p>
13612     *
13613     * <p>The default range is the drawing width of this view.</p>
13614     *
13615     * @return the total horizontal range represented by the horizontal
13616     *         scrollbar
13617     *
13618     * @see #computeHorizontalScrollExtent()
13619     * @see #computeHorizontalScrollOffset()
13620     * @see android.widget.ScrollBarDrawable
13621     */
13622    protected int computeHorizontalScrollRange() {
13623        return getWidth();
13624    }
13625
13626    /**
13627     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13628     * within the horizontal range. This value is used to compute the position
13629     * of the thumb within the scrollbar's track.</p>
13630     *
13631     * <p>The range is expressed in arbitrary units that must be the same as the
13632     * units used by {@link #computeHorizontalScrollRange()} and
13633     * {@link #computeHorizontalScrollExtent()}.</p>
13634     *
13635     * <p>The default offset is the scroll offset of this view.</p>
13636     *
13637     * @return the horizontal offset of the scrollbar's thumb
13638     *
13639     * @see #computeHorizontalScrollRange()
13640     * @see #computeHorizontalScrollExtent()
13641     * @see android.widget.ScrollBarDrawable
13642     */
13643    protected int computeHorizontalScrollOffset() {
13644        return mScrollX;
13645    }
13646
13647    /**
13648     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13649     * within the horizontal range. This value is used to compute the length
13650     * of the thumb within the scrollbar's track.</p>
13651     *
13652     * <p>The range is expressed in arbitrary units that must be the same as the
13653     * units used by {@link #computeHorizontalScrollRange()} and
13654     * {@link #computeHorizontalScrollOffset()}.</p>
13655     *
13656     * <p>The default extent is the drawing width of this view.</p>
13657     *
13658     * @return the horizontal extent of the scrollbar's thumb
13659     *
13660     * @see #computeHorizontalScrollRange()
13661     * @see #computeHorizontalScrollOffset()
13662     * @see android.widget.ScrollBarDrawable
13663     */
13664    protected int computeHorizontalScrollExtent() {
13665        return getWidth();
13666    }
13667
13668    /**
13669     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13670     *
13671     * <p>The range is expressed in arbitrary units that must be the same as the
13672     * units used by {@link #computeVerticalScrollExtent()} and
13673     * {@link #computeVerticalScrollOffset()}.</p>
13674     *
13675     * @return the total vertical range represented by the vertical scrollbar
13676     *
13677     * <p>The default range is the drawing height of this view.</p>
13678     *
13679     * @see #computeVerticalScrollExtent()
13680     * @see #computeVerticalScrollOffset()
13681     * @see android.widget.ScrollBarDrawable
13682     */
13683    protected int computeVerticalScrollRange() {
13684        return getHeight();
13685    }
13686
13687    /**
13688     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13689     * within the horizontal range. This value is used to compute the position
13690     * of the thumb within the scrollbar's track.</p>
13691     *
13692     * <p>The range is expressed in arbitrary units that must be the same as the
13693     * units used by {@link #computeVerticalScrollRange()} and
13694     * {@link #computeVerticalScrollExtent()}.</p>
13695     *
13696     * <p>The default offset is the scroll offset of this view.</p>
13697     *
13698     * @return the vertical offset of the scrollbar's thumb
13699     *
13700     * @see #computeVerticalScrollRange()
13701     * @see #computeVerticalScrollExtent()
13702     * @see android.widget.ScrollBarDrawable
13703     */
13704    protected int computeVerticalScrollOffset() {
13705        return mScrollY;
13706    }
13707
13708    /**
13709     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13710     * within the vertical range. This value is used to compute the length
13711     * of the thumb within the scrollbar's track.</p>
13712     *
13713     * <p>The range is expressed in arbitrary units that must be the same as the
13714     * units used by {@link #computeVerticalScrollRange()} and
13715     * {@link #computeVerticalScrollOffset()}.</p>
13716     *
13717     * <p>The default extent is the drawing height of this view.</p>
13718     *
13719     * @return the vertical extent of the scrollbar's thumb
13720     *
13721     * @see #computeVerticalScrollRange()
13722     * @see #computeVerticalScrollOffset()
13723     * @see android.widget.ScrollBarDrawable
13724     */
13725    protected int computeVerticalScrollExtent() {
13726        return getHeight();
13727    }
13728
13729    /**
13730     * Check if this view can be scrolled horizontally in a certain direction.
13731     *
13732     * @param direction Negative to check scrolling left, positive to check scrolling right.
13733     * @return true if this view can be scrolled in the specified direction, false otherwise.
13734     */
13735    public boolean canScrollHorizontally(int direction) {
13736        final int offset = computeHorizontalScrollOffset();
13737        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
13738        if (range == 0) return false;
13739        if (direction < 0) {
13740            return offset > 0;
13741        } else {
13742            return offset < range - 1;
13743        }
13744    }
13745
13746    /**
13747     * Check if this view can be scrolled vertically in a certain direction.
13748     *
13749     * @param direction Negative to check scrolling up, positive to check scrolling down.
13750     * @return true if this view can be scrolled in the specified direction, false otherwise.
13751     */
13752    public boolean canScrollVertically(int direction) {
13753        final int offset = computeVerticalScrollOffset();
13754        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
13755        if (range == 0) return false;
13756        if (direction < 0) {
13757            return offset > 0;
13758        } else {
13759            return offset < range - 1;
13760        }
13761    }
13762
13763    void getScrollIndicatorBounds(@NonNull Rect out) {
13764        out.left = mScrollX;
13765        out.right = mScrollX + mRight - mLeft;
13766        out.top = mScrollY;
13767        out.bottom = mScrollY + mBottom - mTop;
13768    }
13769
13770    private void onDrawScrollIndicators(Canvas c) {
13771        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
13772            // No scroll indicators enabled.
13773            return;
13774        }
13775
13776        final Drawable dr = mScrollIndicatorDrawable;
13777        if (dr == null) {
13778            // Scroll indicators aren't supported here.
13779            return;
13780        }
13781
13782        final int h = dr.getIntrinsicHeight();
13783        final int w = dr.getIntrinsicWidth();
13784        final Rect rect = mAttachInfo.mTmpInvalRect;
13785        getScrollIndicatorBounds(rect);
13786
13787        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
13788            final boolean canScrollUp = canScrollVertically(-1);
13789            if (canScrollUp) {
13790                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
13791                dr.draw(c);
13792            }
13793        }
13794
13795        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
13796            final boolean canScrollDown = canScrollVertically(1);
13797            if (canScrollDown) {
13798                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
13799                dr.draw(c);
13800            }
13801        }
13802
13803        final int leftRtl;
13804        final int rightRtl;
13805        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
13806            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
13807            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
13808        } else {
13809            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
13810            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
13811        }
13812
13813        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
13814        if ((mPrivateFlags3 & leftMask) != 0) {
13815            final boolean canScrollLeft = canScrollHorizontally(-1);
13816            if (canScrollLeft) {
13817                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
13818                dr.draw(c);
13819            }
13820        }
13821
13822        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
13823        if ((mPrivateFlags3 & rightMask) != 0) {
13824            final boolean canScrollRight = canScrollHorizontally(1);
13825            if (canScrollRight) {
13826                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
13827                dr.draw(c);
13828            }
13829        }
13830    }
13831
13832    /**
13833     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
13834     * scrollbars are painted only if they have been awakened first.</p>
13835     *
13836     * @param canvas the canvas on which to draw the scrollbars
13837     *
13838     * @see #awakenScrollBars(int)
13839     */
13840    protected final void onDrawScrollBars(Canvas canvas) {
13841        // scrollbars are drawn only when the animation is running
13842        final ScrollabilityCache cache = mScrollCache;
13843        if (cache != null) {
13844
13845            int state = cache.state;
13846
13847            if (state == ScrollabilityCache.OFF) {
13848                return;
13849            }
13850
13851            boolean invalidate = false;
13852
13853            if (state == ScrollabilityCache.FADING) {
13854                // We're fading -- get our fade interpolation
13855                if (cache.interpolatorValues == null) {
13856                    cache.interpolatorValues = new float[1];
13857                }
13858
13859                float[] values = cache.interpolatorValues;
13860
13861                // Stops the animation if we're done
13862                if (cache.scrollBarInterpolator.timeToValues(values) ==
13863                        Interpolator.Result.FREEZE_END) {
13864                    cache.state = ScrollabilityCache.OFF;
13865                } else {
13866                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
13867                }
13868
13869                // This will make the scroll bars inval themselves after
13870                // drawing. We only want this when we're fading so that
13871                // we prevent excessive redraws
13872                invalidate = true;
13873            } else {
13874                // We're just on -- but we may have been fading before so
13875                // reset alpha
13876                cache.scrollBar.mutate().setAlpha(255);
13877            }
13878
13879
13880            final int viewFlags = mViewFlags;
13881
13882            final boolean drawHorizontalScrollBar =
13883                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13884            final boolean drawVerticalScrollBar =
13885                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
13886                && !isVerticalScrollBarHidden();
13887
13888            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
13889                final int width = mRight - mLeft;
13890                final int height = mBottom - mTop;
13891
13892                final ScrollBarDrawable scrollBar = cache.scrollBar;
13893
13894                final int scrollX = mScrollX;
13895                final int scrollY = mScrollY;
13896                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
13897
13898                int left;
13899                int top;
13900                int right;
13901                int bottom;
13902
13903                if (drawHorizontalScrollBar) {
13904                    int size = scrollBar.getSize(false);
13905                    if (size <= 0) {
13906                        size = cache.scrollBarSize;
13907                    }
13908
13909                    scrollBar.setParameters(computeHorizontalScrollRange(),
13910                                            computeHorizontalScrollOffset(),
13911                                            computeHorizontalScrollExtent(), false);
13912                    final int verticalScrollBarGap = drawVerticalScrollBar ?
13913                            getVerticalScrollbarWidth() : 0;
13914                    top = scrollY + height - size - (mUserPaddingBottom & inside);
13915                    left = scrollX + (mPaddingLeft & inside);
13916                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
13917                    bottom = top + size;
13918                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
13919                    if (invalidate) {
13920                        invalidate(left, top, right, bottom);
13921                    }
13922                }
13923
13924                if (drawVerticalScrollBar) {
13925                    int size = scrollBar.getSize(true);
13926                    if (size <= 0) {
13927                        size = cache.scrollBarSize;
13928                    }
13929
13930                    scrollBar.setParameters(computeVerticalScrollRange(),
13931                                            computeVerticalScrollOffset(),
13932                                            computeVerticalScrollExtent(), true);
13933                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
13934                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
13935                        verticalScrollbarPosition = isLayoutRtl() ?
13936                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
13937                    }
13938                    switch (verticalScrollbarPosition) {
13939                        default:
13940                        case SCROLLBAR_POSITION_RIGHT:
13941                            left = scrollX + width - size - (mUserPaddingRight & inside);
13942                            break;
13943                        case SCROLLBAR_POSITION_LEFT:
13944                            left = scrollX + (mUserPaddingLeft & inside);
13945                            break;
13946                    }
13947                    top = scrollY + (mPaddingTop & inside);
13948                    right = left + size;
13949                    bottom = scrollY + height - (mUserPaddingBottom & inside);
13950                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
13951                    if (invalidate) {
13952                        invalidate(left, top, right, bottom);
13953                    }
13954                }
13955            }
13956        }
13957    }
13958
13959    /**
13960     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
13961     * FastScroller is visible.
13962     * @return whether to temporarily hide the vertical scrollbar
13963     * @hide
13964     */
13965    protected boolean isVerticalScrollBarHidden() {
13966        return false;
13967    }
13968
13969    /**
13970     * <p>Draw the horizontal scrollbar if
13971     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
13972     *
13973     * @param canvas the canvas on which to draw the scrollbar
13974     * @param scrollBar the scrollbar's drawable
13975     *
13976     * @see #isHorizontalScrollBarEnabled()
13977     * @see #computeHorizontalScrollRange()
13978     * @see #computeHorizontalScrollExtent()
13979     * @see #computeHorizontalScrollOffset()
13980     * @see android.widget.ScrollBarDrawable
13981     * @hide
13982     */
13983    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
13984            int l, int t, int r, int b) {
13985        scrollBar.setBounds(l, t, r, b);
13986        scrollBar.draw(canvas);
13987    }
13988
13989    /**
13990     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
13991     * returns true.</p>
13992     *
13993     * @param canvas the canvas on which to draw the scrollbar
13994     * @param scrollBar the scrollbar's drawable
13995     *
13996     * @see #isVerticalScrollBarEnabled()
13997     * @see #computeVerticalScrollRange()
13998     * @see #computeVerticalScrollExtent()
13999     * @see #computeVerticalScrollOffset()
14000     * @see android.widget.ScrollBarDrawable
14001     * @hide
14002     */
14003    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14004            int l, int t, int r, int b) {
14005        scrollBar.setBounds(l, t, r, b);
14006        scrollBar.draw(canvas);
14007    }
14008
14009    /**
14010     * Implement this to do your drawing.
14011     *
14012     * @param canvas the canvas on which the background will be drawn
14013     */
14014    protected void onDraw(Canvas canvas) {
14015    }
14016
14017    /*
14018     * Caller is responsible for calling requestLayout if necessary.
14019     * (This allows addViewInLayout to not request a new layout.)
14020     */
14021    void assignParent(ViewParent parent) {
14022        if (mParent == null) {
14023            mParent = parent;
14024        } else if (parent == null) {
14025            mParent = null;
14026        } else {
14027            throw new RuntimeException("view " + this + " being added, but"
14028                    + " it already has a parent");
14029        }
14030    }
14031
14032    /**
14033     * This is called when the view is attached to a window.  At this point it
14034     * has a Surface and will start drawing.  Note that this function is
14035     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14036     * however it may be called any time before the first onDraw -- including
14037     * before or after {@link #onMeasure(int, int)}.
14038     *
14039     * @see #onDetachedFromWindow()
14040     */
14041    @CallSuper
14042    protected void onAttachedToWindow() {
14043        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14044            mParent.requestTransparentRegion(this);
14045        }
14046
14047        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14048
14049        jumpDrawablesToCurrentState();
14050
14051        resetSubtreeAccessibilityStateChanged();
14052
14053        // rebuild, since Outline not maintained while View is detached
14054        rebuildOutline();
14055
14056        if (isFocused()) {
14057            InputMethodManager imm = InputMethodManager.peekInstance();
14058            if (imm != null) {
14059                imm.focusIn(this);
14060            }
14061        }
14062    }
14063
14064    /**
14065     * Resolve all RTL related properties.
14066     *
14067     * @return true if resolution of RTL properties has been done
14068     *
14069     * @hide
14070     */
14071    public boolean resolveRtlPropertiesIfNeeded() {
14072        if (!needRtlPropertiesResolution()) return false;
14073
14074        // Order is important here: LayoutDirection MUST be resolved first
14075        if (!isLayoutDirectionResolved()) {
14076            resolveLayoutDirection();
14077            resolveLayoutParams();
14078        }
14079        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14080        if (!isTextDirectionResolved()) {
14081            resolveTextDirection();
14082        }
14083        if (!isTextAlignmentResolved()) {
14084            resolveTextAlignment();
14085        }
14086        // Should resolve Drawables before Padding because we need the layout direction of the
14087        // Drawable to correctly resolve Padding.
14088        if (!areDrawablesResolved()) {
14089            resolveDrawables();
14090        }
14091        if (!isPaddingResolved()) {
14092            resolvePadding();
14093        }
14094        onRtlPropertiesChanged(getLayoutDirection());
14095        return true;
14096    }
14097
14098    /**
14099     * Reset resolution of all RTL related properties.
14100     *
14101     * @hide
14102     */
14103    public void resetRtlProperties() {
14104        resetResolvedLayoutDirection();
14105        resetResolvedTextDirection();
14106        resetResolvedTextAlignment();
14107        resetResolvedPadding();
14108        resetResolvedDrawables();
14109    }
14110
14111    /**
14112     * @see #onScreenStateChanged(int)
14113     */
14114    void dispatchScreenStateChanged(int screenState) {
14115        onScreenStateChanged(screenState);
14116    }
14117
14118    /**
14119     * This method is called whenever the state of the screen this view is
14120     * attached to changes. A state change will usually occurs when the screen
14121     * turns on or off (whether it happens automatically or the user does it
14122     * manually.)
14123     *
14124     * @param screenState The new state of the screen. Can be either
14125     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14126     */
14127    public void onScreenStateChanged(int screenState) {
14128    }
14129
14130    /**
14131     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14132     */
14133    private boolean hasRtlSupport() {
14134        return mContext.getApplicationInfo().hasRtlSupport();
14135    }
14136
14137    /**
14138     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14139     * RTL not supported)
14140     */
14141    private boolean isRtlCompatibilityMode() {
14142        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14143        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14144    }
14145
14146    /**
14147     * @return true if RTL properties need resolution.
14148     *
14149     */
14150    private boolean needRtlPropertiesResolution() {
14151        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14152    }
14153
14154    /**
14155     * Called when any RTL property (layout direction or text direction or text alignment) has
14156     * been changed.
14157     *
14158     * Subclasses need to override this method to take care of cached information that depends on the
14159     * resolved layout direction, or to inform child views that inherit their layout direction.
14160     *
14161     * The default implementation does nothing.
14162     *
14163     * @param layoutDirection the direction of the layout
14164     *
14165     * @see #LAYOUT_DIRECTION_LTR
14166     * @see #LAYOUT_DIRECTION_RTL
14167     */
14168    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14169    }
14170
14171    /**
14172     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14173     * that the parent directionality can and will be resolved before its children.
14174     *
14175     * @return true if resolution has been done, false otherwise.
14176     *
14177     * @hide
14178     */
14179    public boolean resolveLayoutDirection() {
14180        // Clear any previous layout direction resolution
14181        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14182
14183        if (hasRtlSupport()) {
14184            // Set resolved depending on layout direction
14185            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14186                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14187                case LAYOUT_DIRECTION_INHERIT:
14188                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14189                    // later to get the correct resolved value
14190                    if (!canResolveLayoutDirection()) return false;
14191
14192                    // Parent has not yet resolved, LTR is still the default
14193                    try {
14194                        if (!mParent.isLayoutDirectionResolved()) return false;
14195
14196                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14197                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14198                        }
14199                    } catch (AbstractMethodError e) {
14200                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14201                                " does not fully implement ViewParent", e);
14202                    }
14203                    break;
14204                case LAYOUT_DIRECTION_RTL:
14205                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14206                    break;
14207                case LAYOUT_DIRECTION_LOCALE:
14208                    if((LAYOUT_DIRECTION_RTL ==
14209                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14210                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14211                    }
14212                    break;
14213                default:
14214                    // Nothing to do, LTR by default
14215            }
14216        }
14217
14218        // Set to resolved
14219        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14220        return true;
14221    }
14222
14223    /**
14224     * Check if layout direction resolution can be done.
14225     *
14226     * @return true if layout direction resolution can be done otherwise return false.
14227     */
14228    public boolean canResolveLayoutDirection() {
14229        switch (getRawLayoutDirection()) {
14230            case LAYOUT_DIRECTION_INHERIT:
14231                if (mParent != null) {
14232                    try {
14233                        return mParent.canResolveLayoutDirection();
14234                    } catch (AbstractMethodError e) {
14235                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14236                                " does not fully implement ViewParent", e);
14237                    }
14238                }
14239                return false;
14240
14241            default:
14242                return true;
14243        }
14244    }
14245
14246    /**
14247     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14248     * {@link #onMeasure(int, int)}.
14249     *
14250     * @hide
14251     */
14252    public void resetResolvedLayoutDirection() {
14253        // Reset the current resolved bits
14254        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14255    }
14256
14257    /**
14258     * @return true if the layout direction is inherited.
14259     *
14260     * @hide
14261     */
14262    public boolean isLayoutDirectionInherited() {
14263        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14264    }
14265
14266    /**
14267     * @return true if layout direction has been resolved.
14268     */
14269    public boolean isLayoutDirectionResolved() {
14270        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14271    }
14272
14273    /**
14274     * Return if padding has been resolved
14275     *
14276     * @hide
14277     */
14278    boolean isPaddingResolved() {
14279        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14280    }
14281
14282    /**
14283     * Resolves padding depending on layout direction, if applicable, and
14284     * recomputes internal padding values to adjust for scroll bars.
14285     *
14286     * @hide
14287     */
14288    public void resolvePadding() {
14289        final int resolvedLayoutDirection = getLayoutDirection();
14290
14291        if (!isRtlCompatibilityMode()) {
14292            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14293            // If start / end padding are defined, they will be resolved (hence overriding) to
14294            // left / right or right / left depending on the resolved layout direction.
14295            // If start / end padding are not defined, use the left / right ones.
14296            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14297                Rect padding = sThreadLocal.get();
14298                if (padding == null) {
14299                    padding = new Rect();
14300                    sThreadLocal.set(padding);
14301                }
14302                mBackground.getPadding(padding);
14303                if (!mLeftPaddingDefined) {
14304                    mUserPaddingLeftInitial = padding.left;
14305                }
14306                if (!mRightPaddingDefined) {
14307                    mUserPaddingRightInitial = padding.right;
14308                }
14309            }
14310            switch (resolvedLayoutDirection) {
14311                case LAYOUT_DIRECTION_RTL:
14312                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14313                        mUserPaddingRight = mUserPaddingStart;
14314                    } else {
14315                        mUserPaddingRight = mUserPaddingRightInitial;
14316                    }
14317                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14318                        mUserPaddingLeft = mUserPaddingEnd;
14319                    } else {
14320                        mUserPaddingLeft = mUserPaddingLeftInitial;
14321                    }
14322                    break;
14323                case LAYOUT_DIRECTION_LTR:
14324                default:
14325                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14326                        mUserPaddingLeft = mUserPaddingStart;
14327                    } else {
14328                        mUserPaddingLeft = mUserPaddingLeftInitial;
14329                    }
14330                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14331                        mUserPaddingRight = mUserPaddingEnd;
14332                    } else {
14333                        mUserPaddingRight = mUserPaddingRightInitial;
14334                    }
14335            }
14336
14337            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14338        }
14339
14340        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14341        onRtlPropertiesChanged(resolvedLayoutDirection);
14342
14343        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14344    }
14345
14346    /**
14347     * Reset the resolved layout direction.
14348     *
14349     * @hide
14350     */
14351    public void resetResolvedPadding() {
14352        resetResolvedPaddingInternal();
14353    }
14354
14355    /**
14356     * Used when we only want to reset *this* view's padding and not trigger overrides
14357     * in ViewGroup that reset children too.
14358     */
14359    void resetResolvedPaddingInternal() {
14360        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14361    }
14362
14363    /**
14364     * This is called when the view is detached from a window.  At this point it
14365     * no longer has a surface for drawing.
14366     *
14367     * @see #onAttachedToWindow()
14368     */
14369    @CallSuper
14370    protected void onDetachedFromWindow() {
14371    }
14372
14373    /**
14374     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14375     * after onDetachedFromWindow().
14376     *
14377     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14378     * The super method should be called at the end of the overridden method to ensure
14379     * subclasses are destroyed first
14380     *
14381     * @hide
14382     */
14383    @CallSuper
14384    protected void onDetachedFromWindowInternal() {
14385        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14386        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14387
14388        removeUnsetPressCallback();
14389        removeLongPressCallback();
14390        removePerformClickCallback();
14391        removeSendViewScrolledAccessibilityEventCallback();
14392        stopNestedScroll();
14393
14394        // Anything that started animating right before detach should already
14395        // be in its final state when re-attached.
14396        jumpDrawablesToCurrentState();
14397
14398        destroyDrawingCache();
14399
14400        cleanupDraw();
14401        mCurrentAnimation = null;
14402    }
14403
14404    private void cleanupDraw() {
14405        resetDisplayList();
14406        if (mAttachInfo != null) {
14407            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14408        }
14409    }
14410
14411    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14412    }
14413
14414    /**
14415     * @return The number of times this view has been attached to a window
14416     */
14417    protected int getWindowAttachCount() {
14418        return mWindowAttachCount;
14419    }
14420
14421    /**
14422     * Retrieve a unique token identifying the window this view is attached to.
14423     * @return Return the window's token for use in
14424     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14425     */
14426    public IBinder getWindowToken() {
14427        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14428    }
14429
14430    /**
14431     * Retrieve the {@link WindowId} for the window this view is
14432     * currently attached to.
14433     */
14434    public WindowId getWindowId() {
14435        if (mAttachInfo == null) {
14436            return null;
14437        }
14438        if (mAttachInfo.mWindowId == null) {
14439            try {
14440                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14441                        mAttachInfo.mWindowToken);
14442                mAttachInfo.mWindowId = new WindowId(
14443                        mAttachInfo.mIWindowId);
14444            } catch (RemoteException e) {
14445            }
14446        }
14447        return mAttachInfo.mWindowId;
14448    }
14449
14450    /**
14451     * Retrieve a unique token identifying the top-level "real" window of
14452     * the window that this view is attached to.  That is, this is like
14453     * {@link #getWindowToken}, except if the window this view in is a panel
14454     * window (attached to another containing window), then the token of
14455     * the containing window is returned instead.
14456     *
14457     * @return Returns the associated window token, either
14458     * {@link #getWindowToken()} or the containing window's token.
14459     */
14460    public IBinder getApplicationWindowToken() {
14461        AttachInfo ai = mAttachInfo;
14462        if (ai != null) {
14463            IBinder appWindowToken = ai.mPanelParentWindowToken;
14464            if (appWindowToken == null) {
14465                appWindowToken = ai.mWindowToken;
14466            }
14467            return appWindowToken;
14468        }
14469        return null;
14470    }
14471
14472    /**
14473     * Gets the logical display to which the view's window has been attached.
14474     *
14475     * @return The logical display, or null if the view is not currently attached to a window.
14476     */
14477    public Display getDisplay() {
14478        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14479    }
14480
14481    /**
14482     * Retrieve private session object this view hierarchy is using to
14483     * communicate with the window manager.
14484     * @return the session object to communicate with the window manager
14485     */
14486    /*package*/ IWindowSession getWindowSession() {
14487        return mAttachInfo != null ? mAttachInfo.mSession : null;
14488    }
14489
14490    /**
14491     * Return the visibility value of the least visible component passed.
14492     */
14493    int combineVisibility(int vis1, int vis2) {
14494        // This works because VISIBLE < INVISIBLE < GONE.
14495        return Math.max(vis1, vis2);
14496    }
14497
14498    /**
14499     * @param info the {@link android.view.View.AttachInfo} to associated with
14500     *        this view
14501     */
14502    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14503        //System.out.println("Attached! " + this);
14504        mAttachInfo = info;
14505        if (mOverlay != null) {
14506            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14507        }
14508        mWindowAttachCount++;
14509        // We will need to evaluate the drawable state at least once.
14510        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14511        if (mFloatingTreeObserver != null) {
14512            info.mTreeObserver.merge(mFloatingTreeObserver);
14513            mFloatingTreeObserver = null;
14514        }
14515        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14516            mAttachInfo.mScrollContainers.add(this);
14517            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14518        }
14519        performCollectViewAttributes(mAttachInfo, visibility);
14520        onAttachedToWindow();
14521
14522        ListenerInfo li = mListenerInfo;
14523        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14524                li != null ? li.mOnAttachStateChangeListeners : null;
14525        if (listeners != null && listeners.size() > 0) {
14526            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14527            // perform the dispatching. The iterator is a safe guard against listeners that
14528            // could mutate the list by calling the various add/remove methods. This prevents
14529            // the array from being modified while we iterate it.
14530            for (OnAttachStateChangeListener listener : listeners) {
14531                listener.onViewAttachedToWindow(this);
14532            }
14533        }
14534
14535        int vis = info.mWindowVisibility;
14536        if (vis != GONE) {
14537            onWindowVisibilityChanged(vis);
14538        }
14539
14540        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14541        // As all views in the subtree will already receive dispatchAttachedToWindow
14542        // traversing the subtree again here is not desired.
14543        onVisibilityChanged(this, visibility);
14544
14545        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14546            // If nobody has evaluated the drawable state yet, then do it now.
14547            refreshDrawableState();
14548        }
14549        needGlobalAttributesUpdate(false);
14550    }
14551
14552    void dispatchDetachedFromWindow() {
14553        AttachInfo info = mAttachInfo;
14554        if (info != null) {
14555            int vis = info.mWindowVisibility;
14556            if (vis != GONE) {
14557                onWindowVisibilityChanged(GONE);
14558            }
14559        }
14560
14561        onDetachedFromWindow();
14562        onDetachedFromWindowInternal();
14563
14564        InputMethodManager imm = InputMethodManager.peekInstance();
14565        if (imm != null) {
14566            imm.onViewDetachedFromWindow(this);
14567        }
14568
14569        ListenerInfo li = mListenerInfo;
14570        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14571                li != null ? li.mOnAttachStateChangeListeners : null;
14572        if (listeners != null && listeners.size() > 0) {
14573            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14574            // perform the dispatching. The iterator is a safe guard against listeners that
14575            // could mutate the list by calling the various add/remove methods. This prevents
14576            // the array from being modified while we iterate it.
14577            for (OnAttachStateChangeListener listener : listeners) {
14578                listener.onViewDetachedFromWindow(this);
14579            }
14580        }
14581
14582        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14583            mAttachInfo.mScrollContainers.remove(this);
14584            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14585        }
14586
14587        mAttachInfo = null;
14588        if (mOverlay != null) {
14589            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14590        }
14591    }
14592
14593    /**
14594     * Cancel any deferred high-level input events that were previously posted to the event queue.
14595     *
14596     * <p>Many views post high-level events such as click handlers to the event queue
14597     * to run deferred in order to preserve a desired user experience - clearing visible
14598     * pressed states before executing, etc. This method will abort any events of this nature
14599     * that are currently in flight.</p>
14600     *
14601     * <p>Custom views that generate their own high-level deferred input events should override
14602     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14603     *
14604     * <p>This will also cancel pending input events for any child views.</p>
14605     *
14606     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14607     * This will not impact newer events posted after this call that may occur as a result of
14608     * lower-level input events still waiting in the queue. If you are trying to prevent
14609     * double-submitted  events for the duration of some sort of asynchronous transaction
14610     * you should also take other steps to protect against unexpected double inputs e.g. calling
14611     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14612     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14613     */
14614    public final void cancelPendingInputEvents() {
14615        dispatchCancelPendingInputEvents();
14616    }
14617
14618    /**
14619     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14620     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14621     */
14622    void dispatchCancelPendingInputEvents() {
14623        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14624        onCancelPendingInputEvents();
14625        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14626            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14627                    " did not call through to super.onCancelPendingInputEvents()");
14628        }
14629    }
14630
14631    /**
14632     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14633     * a parent view.
14634     *
14635     * <p>This method is responsible for removing any pending high-level input events that were
14636     * posted to the event queue to run later. Custom view classes that post their own deferred
14637     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14638     * {@link android.os.Handler} should override this method, call
14639     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14640     * </p>
14641     */
14642    public void onCancelPendingInputEvents() {
14643        removePerformClickCallback();
14644        cancelLongPress();
14645        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14646    }
14647
14648    /**
14649     * Store this view hierarchy's frozen state into the given container.
14650     *
14651     * @param container The SparseArray in which to save the view's state.
14652     *
14653     * @see #restoreHierarchyState(android.util.SparseArray)
14654     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14655     * @see #onSaveInstanceState()
14656     */
14657    public void saveHierarchyState(SparseArray<Parcelable> container) {
14658        dispatchSaveInstanceState(container);
14659    }
14660
14661    /**
14662     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14663     * this view and its children. May be overridden to modify how freezing happens to a
14664     * view's children; for example, some views may want to not store state for their children.
14665     *
14666     * @param container The SparseArray in which to save the view's state.
14667     *
14668     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14669     * @see #saveHierarchyState(android.util.SparseArray)
14670     * @see #onSaveInstanceState()
14671     */
14672    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14673        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14674            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14675            Parcelable state = onSaveInstanceState();
14676            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14677                throw new IllegalStateException(
14678                        "Derived class did not call super.onSaveInstanceState()");
14679            }
14680            if (state != null) {
14681                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14682                // + ": " + state);
14683                container.put(mID, state);
14684            }
14685        }
14686    }
14687
14688    /**
14689     * Hook allowing a view to generate a representation of its internal state
14690     * that can later be used to create a new instance with that same state.
14691     * This state should only contain information that is not persistent or can
14692     * not be reconstructed later. For example, you will never store your
14693     * current position on screen because that will be computed again when a
14694     * new instance of the view is placed in its view hierarchy.
14695     * <p>
14696     * Some examples of things you may store here: the current cursor position
14697     * in a text view (but usually not the text itself since that is stored in a
14698     * content provider or other persistent storage), the currently selected
14699     * item in a list view.
14700     *
14701     * @return Returns a Parcelable object containing the view's current dynamic
14702     *         state, or null if there is nothing interesting to save. The
14703     *         default implementation returns null.
14704     * @see #onRestoreInstanceState(android.os.Parcelable)
14705     * @see #saveHierarchyState(android.util.SparseArray)
14706     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14707     * @see #setSaveEnabled(boolean)
14708     */
14709    @CallSuper
14710    protected Parcelable onSaveInstanceState() {
14711        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14712        if (mStartActivityRequestWho != null) {
14713            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14714            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14715            return state;
14716        }
14717        return BaseSavedState.EMPTY_STATE;
14718    }
14719
14720    /**
14721     * Restore this view hierarchy's frozen state from the given container.
14722     *
14723     * @param container The SparseArray which holds previously frozen states.
14724     *
14725     * @see #saveHierarchyState(android.util.SparseArray)
14726     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14727     * @see #onRestoreInstanceState(android.os.Parcelable)
14728     */
14729    public void restoreHierarchyState(SparseArray<Parcelable> container) {
14730        dispatchRestoreInstanceState(container);
14731    }
14732
14733    /**
14734     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
14735     * state for this view and its children. May be overridden to modify how restoring
14736     * happens to a view's children; for example, some views may want to not store state
14737     * for their children.
14738     *
14739     * @param container The SparseArray which holds previously saved state.
14740     *
14741     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14742     * @see #restoreHierarchyState(android.util.SparseArray)
14743     * @see #onRestoreInstanceState(android.os.Parcelable)
14744     */
14745    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
14746        if (mID != NO_ID) {
14747            Parcelable state = container.get(mID);
14748            if (state != null) {
14749                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
14750                // + ": " + state);
14751                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14752                onRestoreInstanceState(state);
14753                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14754                    throw new IllegalStateException(
14755                            "Derived class did not call super.onRestoreInstanceState()");
14756                }
14757            }
14758        }
14759    }
14760
14761    /**
14762     * Hook allowing a view to re-apply a representation of its internal state that had previously
14763     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
14764     * null state.
14765     *
14766     * @param state The frozen state that had previously been returned by
14767     *        {@link #onSaveInstanceState}.
14768     *
14769     * @see #onSaveInstanceState()
14770     * @see #restoreHierarchyState(android.util.SparseArray)
14771     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14772     */
14773    @CallSuper
14774    protected void onRestoreInstanceState(Parcelable state) {
14775        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14776        if (state != null && !(state instanceof AbsSavedState)) {
14777            throw new IllegalArgumentException("Wrong state class, expecting View State but "
14778                    + "received " + state.getClass().toString() + " instead. This usually happens "
14779                    + "when two views of different type have the same id in the same hierarchy. "
14780                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
14781                    + "other views do not use the same id.");
14782        }
14783        if (state != null && state instanceof BaseSavedState) {
14784            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
14785        }
14786    }
14787
14788    /**
14789     * <p>Return the time at which the drawing of the view hierarchy started.</p>
14790     *
14791     * @return the drawing start time in milliseconds
14792     */
14793    public long getDrawingTime() {
14794        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
14795    }
14796
14797    /**
14798     * <p>Enables or disables the duplication of the parent's state into this view. When
14799     * duplication is enabled, this view gets its drawable state from its parent rather
14800     * than from its own internal properties.</p>
14801     *
14802     * <p>Note: in the current implementation, setting this property to true after the
14803     * view was added to a ViewGroup might have no effect at all. This property should
14804     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
14805     *
14806     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
14807     * property is enabled, an exception will be thrown.</p>
14808     *
14809     * <p>Note: if the child view uses and updates additional states which are unknown to the
14810     * parent, these states should not be affected by this method.</p>
14811     *
14812     * @param enabled True to enable duplication of the parent's drawable state, false
14813     *                to disable it.
14814     *
14815     * @see #getDrawableState()
14816     * @see #isDuplicateParentStateEnabled()
14817     */
14818    public void setDuplicateParentStateEnabled(boolean enabled) {
14819        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
14820    }
14821
14822    /**
14823     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
14824     *
14825     * @return True if this view's drawable state is duplicated from the parent,
14826     *         false otherwise
14827     *
14828     * @see #getDrawableState()
14829     * @see #setDuplicateParentStateEnabled(boolean)
14830     */
14831    public boolean isDuplicateParentStateEnabled() {
14832        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
14833    }
14834
14835    /**
14836     * <p>Specifies the type of layer backing this view. The layer can be
14837     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14838     * {@link #LAYER_TYPE_HARDWARE}.</p>
14839     *
14840     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14841     * instance that controls how the layer is composed on screen. The following
14842     * properties of the paint are taken into account when composing the layer:</p>
14843     * <ul>
14844     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14845     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14846     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14847     * </ul>
14848     *
14849     * <p>If this view has an alpha value set to < 1.0 by calling
14850     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
14851     * by this view's alpha value.</p>
14852     *
14853     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
14854     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
14855     * for more information on when and how to use layers.</p>
14856     *
14857     * @param layerType The type of layer to use with this view, must be one of
14858     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14859     *        {@link #LAYER_TYPE_HARDWARE}
14860     * @param paint The paint used to compose the layer. This argument is optional
14861     *        and can be null. It is ignored when the layer type is
14862     *        {@link #LAYER_TYPE_NONE}
14863     *
14864     * @see #getLayerType()
14865     * @see #LAYER_TYPE_NONE
14866     * @see #LAYER_TYPE_SOFTWARE
14867     * @see #LAYER_TYPE_HARDWARE
14868     * @see #setAlpha(float)
14869     *
14870     * @attr ref android.R.styleable#View_layerType
14871     */
14872    public void setLayerType(int layerType, Paint paint) {
14873        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
14874            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
14875                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
14876        }
14877
14878        boolean typeChanged = mRenderNode.setLayerType(layerType);
14879
14880        if (!typeChanged) {
14881            setLayerPaint(paint);
14882            return;
14883        }
14884
14885        // Destroy any previous software drawing cache if needed
14886        if (mLayerType == LAYER_TYPE_SOFTWARE) {
14887            destroyDrawingCache();
14888        }
14889
14890        mLayerType = layerType;
14891        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
14892        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
14893        mRenderNode.setLayerPaint(mLayerPaint);
14894
14895        // draw() behaves differently if we are on a layer, so we need to
14896        // invalidate() here
14897        invalidateParentCaches();
14898        invalidate(true);
14899    }
14900
14901    /**
14902     * Updates the {@link Paint} object used with the current layer (used only if the current
14903     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
14904     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
14905     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
14906     * ensure that the view gets redrawn immediately.
14907     *
14908     * <p>A layer is associated with an optional {@link android.graphics.Paint}
14909     * instance that controls how the layer is composed on screen. The following
14910     * properties of the paint are taken into account when composing the layer:</p>
14911     * <ul>
14912     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
14913     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
14914     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
14915     * </ul>
14916     *
14917     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
14918     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
14919     *
14920     * @param paint The paint used to compose the layer. This argument is optional
14921     *        and can be null. It is ignored when the layer type is
14922     *        {@link #LAYER_TYPE_NONE}
14923     *
14924     * @see #setLayerType(int, android.graphics.Paint)
14925     */
14926    public void setLayerPaint(Paint paint) {
14927        int layerType = getLayerType();
14928        if (layerType != LAYER_TYPE_NONE) {
14929            mLayerPaint = paint == null ? new Paint() : paint;
14930            if (layerType == LAYER_TYPE_HARDWARE) {
14931                if (mRenderNode.setLayerPaint(mLayerPaint)) {
14932                    invalidateViewProperty(false, false);
14933                }
14934            } else {
14935                invalidate();
14936            }
14937        }
14938    }
14939
14940    /**
14941     * Indicates what type of layer is currently associated with this view. By default
14942     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
14943     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
14944     * for more information on the different types of layers.
14945     *
14946     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
14947     *         {@link #LAYER_TYPE_HARDWARE}
14948     *
14949     * @see #setLayerType(int, android.graphics.Paint)
14950     * @see #buildLayer()
14951     * @see #LAYER_TYPE_NONE
14952     * @see #LAYER_TYPE_SOFTWARE
14953     * @see #LAYER_TYPE_HARDWARE
14954     */
14955    public int getLayerType() {
14956        return mLayerType;
14957    }
14958
14959    /**
14960     * Forces this view's layer to be created and this view to be rendered
14961     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
14962     * invoking this method will have no effect.
14963     *
14964     * This method can for instance be used to render a view into its layer before
14965     * starting an animation. If this view is complex, rendering into the layer
14966     * before starting the animation will avoid skipping frames.
14967     *
14968     * @throws IllegalStateException If this view is not attached to a window
14969     *
14970     * @see #setLayerType(int, android.graphics.Paint)
14971     */
14972    public void buildLayer() {
14973        if (mLayerType == LAYER_TYPE_NONE) return;
14974
14975        final AttachInfo attachInfo = mAttachInfo;
14976        if (attachInfo == null) {
14977            throw new IllegalStateException("This view must be attached to a window first");
14978        }
14979
14980        if (getWidth() == 0 || getHeight() == 0) {
14981            return;
14982        }
14983
14984        switch (mLayerType) {
14985            case LAYER_TYPE_HARDWARE:
14986                updateDisplayListIfDirty();
14987                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
14988                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
14989                }
14990                break;
14991            case LAYER_TYPE_SOFTWARE:
14992                buildDrawingCache(true);
14993                break;
14994        }
14995    }
14996
14997    /**
14998     * If this View draws with a HardwareLayer, returns it.
14999     * Otherwise returns null
15000     *
15001     * TODO: Only TextureView uses this, can we eliminate it?
15002     */
15003    HardwareLayer getHardwareLayer() {
15004        return null;
15005    }
15006
15007    /**
15008     * Destroys all hardware rendering resources. This method is invoked
15009     * when the system needs to reclaim resources. Upon execution of this
15010     * method, you should free any OpenGL resources created by the view.
15011     *
15012     * Note: you <strong>must</strong> call
15013     * <code>super.destroyHardwareResources()</code> when overriding
15014     * this method.
15015     *
15016     * @hide
15017     */
15018    @CallSuper
15019    protected void destroyHardwareResources() {
15020        // Although the Layer will be destroyed by RenderNode, we want to release
15021        // the staging display list, which is also a signal to RenderNode that it's
15022        // safe to free its copy of the display list as it knows that we will
15023        // push an updated DisplayList if we try to draw again
15024        resetDisplayList();
15025    }
15026
15027    /**
15028     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15029     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15030     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15031     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15032     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15033     * null.</p>
15034     *
15035     * <p>Enabling the drawing cache is similar to
15036     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15037     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15038     * drawing cache has no effect on rendering because the system uses a different mechanism
15039     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15040     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15041     * for information on how to enable software and hardware layers.</p>
15042     *
15043     * <p>This API can be used to manually generate
15044     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15045     * {@link #getDrawingCache()}.</p>
15046     *
15047     * @param enabled true to enable the drawing cache, false otherwise
15048     *
15049     * @see #isDrawingCacheEnabled()
15050     * @see #getDrawingCache()
15051     * @see #buildDrawingCache()
15052     * @see #setLayerType(int, android.graphics.Paint)
15053     */
15054    public void setDrawingCacheEnabled(boolean enabled) {
15055        mCachingFailed = false;
15056        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15057    }
15058
15059    /**
15060     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15061     *
15062     * @return true if the drawing cache is enabled
15063     *
15064     * @see #setDrawingCacheEnabled(boolean)
15065     * @see #getDrawingCache()
15066     */
15067    @ViewDebug.ExportedProperty(category = "drawing")
15068    public boolean isDrawingCacheEnabled() {
15069        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15070    }
15071
15072    /**
15073     * Debugging utility which recursively outputs the dirty state of a view and its
15074     * descendants.
15075     *
15076     * @hide
15077     */
15078    @SuppressWarnings({"UnusedDeclaration"})
15079    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15080        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15081                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15082                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15083                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15084        if (clear) {
15085            mPrivateFlags &= clearMask;
15086        }
15087        if (this instanceof ViewGroup) {
15088            ViewGroup parent = (ViewGroup) this;
15089            final int count = parent.getChildCount();
15090            for (int i = 0; i < count; i++) {
15091                final View child = parent.getChildAt(i);
15092                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15093            }
15094        }
15095    }
15096
15097    /**
15098     * This method is used by ViewGroup to cause its children to restore or recreate their
15099     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15100     * to recreate its own display list, which would happen if it went through the normal
15101     * draw/dispatchDraw mechanisms.
15102     *
15103     * @hide
15104     */
15105    protected void dispatchGetDisplayList() {}
15106
15107    /**
15108     * A view that is not attached or hardware accelerated cannot create a display list.
15109     * This method checks these conditions and returns the appropriate result.
15110     *
15111     * @return true if view has the ability to create a display list, false otherwise.
15112     *
15113     * @hide
15114     */
15115    public boolean canHaveDisplayList() {
15116        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15117    }
15118
15119    /**
15120     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15121     * @hide
15122     */
15123    @NonNull
15124    public RenderNode updateDisplayListIfDirty() {
15125        final RenderNode renderNode = mRenderNode;
15126        if (!canHaveDisplayList()) {
15127            // can't populate RenderNode, don't try
15128            return renderNode;
15129        }
15130
15131        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15132                || !renderNode.isValid()
15133                || (mRecreateDisplayList)) {
15134            // Don't need to recreate the display list, just need to tell our
15135            // children to restore/recreate theirs
15136            if (renderNode.isValid()
15137                    && !mRecreateDisplayList) {
15138                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15139                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15140                dispatchGetDisplayList();
15141
15142                return renderNode; // no work needed
15143            }
15144
15145            // If we got here, we're recreating it. Mark it as such to ensure that
15146            // we copy in child display lists into ours in drawChild()
15147            mRecreateDisplayList = true;
15148
15149            int width = mRight - mLeft;
15150            int height = mBottom - mTop;
15151            int layerType = getLayerType();
15152
15153            final DisplayListCanvas canvas = renderNode.start(width, height);
15154            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15155
15156            try {
15157                final HardwareLayer layer = getHardwareLayer();
15158                if (layer != null && layer.isValid()) {
15159                    canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
15160                } else if (layerType == LAYER_TYPE_SOFTWARE) {
15161                    buildDrawingCache(true);
15162                    Bitmap cache = getDrawingCache(true);
15163                    if (cache != null) {
15164                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15165                    }
15166                } else {
15167                    computeScroll();
15168
15169                    canvas.translate(-mScrollX, -mScrollY);
15170                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15171                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15172
15173                    // Fast path for layouts with no backgrounds
15174                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15175                        dispatchDraw(canvas);
15176                        if (mOverlay != null && !mOverlay.isEmpty()) {
15177                            mOverlay.getOverlayView().draw(canvas);
15178                        }
15179                    } else {
15180                        draw(canvas);
15181                    }
15182                }
15183            } finally {
15184                renderNode.end(canvas);
15185                setDisplayListProperties(renderNode);
15186            }
15187        } else {
15188            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15189            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15190        }
15191        return renderNode;
15192    }
15193
15194    private void resetDisplayList() {
15195        if (mRenderNode.isValid()) {
15196            mRenderNode.destroyDisplayListData();
15197        }
15198
15199        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15200            mBackgroundRenderNode.destroyDisplayListData();
15201        }
15202    }
15203
15204    /**
15205     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15206     *
15207     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15208     *
15209     * @see #getDrawingCache(boolean)
15210     */
15211    public Bitmap getDrawingCache() {
15212        return getDrawingCache(false);
15213    }
15214
15215    /**
15216     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15217     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15218     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15219     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15220     * request the drawing cache by calling this method and draw it on screen if the
15221     * returned bitmap is not null.</p>
15222     *
15223     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15224     * this method will create a bitmap of the same size as this view. Because this bitmap
15225     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15226     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15227     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15228     * size than the view. This implies that your application must be able to handle this
15229     * size.</p>
15230     *
15231     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15232     *        the current density of the screen when the application is in compatibility
15233     *        mode.
15234     *
15235     * @return A bitmap representing this view or null if cache is disabled.
15236     *
15237     * @see #setDrawingCacheEnabled(boolean)
15238     * @see #isDrawingCacheEnabled()
15239     * @see #buildDrawingCache(boolean)
15240     * @see #destroyDrawingCache()
15241     */
15242    public Bitmap getDrawingCache(boolean autoScale) {
15243        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15244            return null;
15245        }
15246        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15247            buildDrawingCache(autoScale);
15248        }
15249        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15250    }
15251
15252    /**
15253     * <p>Frees the resources used by the drawing cache. If you call
15254     * {@link #buildDrawingCache()} manually without calling
15255     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15256     * should cleanup the cache with this method afterwards.</p>
15257     *
15258     * @see #setDrawingCacheEnabled(boolean)
15259     * @see #buildDrawingCache()
15260     * @see #getDrawingCache()
15261     */
15262    public void destroyDrawingCache() {
15263        if (mDrawingCache != null) {
15264            mDrawingCache.recycle();
15265            mDrawingCache = null;
15266        }
15267        if (mUnscaledDrawingCache != null) {
15268            mUnscaledDrawingCache.recycle();
15269            mUnscaledDrawingCache = null;
15270        }
15271    }
15272
15273    /**
15274     * Setting a solid background color for the drawing cache's bitmaps will improve
15275     * performance and memory usage. Note, though that this should only be used if this
15276     * view will always be drawn on top of a solid color.
15277     *
15278     * @param color The background color to use for the drawing cache's bitmap
15279     *
15280     * @see #setDrawingCacheEnabled(boolean)
15281     * @see #buildDrawingCache()
15282     * @see #getDrawingCache()
15283     */
15284    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15285        if (color != mDrawingCacheBackgroundColor) {
15286            mDrawingCacheBackgroundColor = color;
15287            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15288        }
15289    }
15290
15291    /**
15292     * @see #setDrawingCacheBackgroundColor(int)
15293     *
15294     * @return The background color to used for the drawing cache's bitmap
15295     */
15296    @ColorInt
15297    public int getDrawingCacheBackgroundColor() {
15298        return mDrawingCacheBackgroundColor;
15299    }
15300
15301    /**
15302     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15303     *
15304     * @see #buildDrawingCache(boolean)
15305     */
15306    public void buildDrawingCache() {
15307        buildDrawingCache(false);
15308    }
15309
15310    /**
15311     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15312     *
15313     * <p>If you call {@link #buildDrawingCache()} manually without calling
15314     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15315     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15316     *
15317     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15318     * this method will create a bitmap of the same size as this view. Because this bitmap
15319     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15320     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15321     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15322     * size than the view. This implies that your application must be able to handle this
15323     * size.</p>
15324     *
15325     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15326     * you do not need the drawing cache bitmap, calling this method will increase memory
15327     * usage and cause the view to be rendered in software once, thus negatively impacting
15328     * performance.</p>
15329     *
15330     * @see #getDrawingCache()
15331     * @see #destroyDrawingCache()
15332     */
15333    public void buildDrawingCache(boolean autoScale) {
15334        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15335                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15336            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15337                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15338                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15339            }
15340            try {
15341                buildDrawingCacheImpl(autoScale);
15342            } finally {
15343                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15344            }
15345        }
15346    }
15347
15348    /**
15349     * private, internal implementation of buildDrawingCache, used to enable tracing
15350     */
15351    private void buildDrawingCacheImpl(boolean autoScale) {
15352        mCachingFailed = false;
15353
15354        int width = mRight - mLeft;
15355        int height = mBottom - mTop;
15356
15357        final AttachInfo attachInfo = mAttachInfo;
15358        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15359
15360        if (autoScale && scalingRequired) {
15361            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15362            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15363        }
15364
15365        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15366        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15367        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15368
15369        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15370        final long drawingCacheSize =
15371                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15372        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15373            if (width > 0 && height > 0) {
15374                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15375                        + " too large to fit into a software layer (or drawing cache), needs "
15376                        + projectedBitmapSize + " bytes, only "
15377                        + drawingCacheSize + " available");
15378            }
15379            destroyDrawingCache();
15380            mCachingFailed = true;
15381            return;
15382        }
15383
15384        boolean clear = true;
15385        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15386
15387        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15388            Bitmap.Config quality;
15389            if (!opaque) {
15390                // Never pick ARGB_4444 because it looks awful
15391                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15392                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15393                    case DRAWING_CACHE_QUALITY_AUTO:
15394                    case DRAWING_CACHE_QUALITY_LOW:
15395                    case DRAWING_CACHE_QUALITY_HIGH:
15396                    default:
15397                        quality = Bitmap.Config.ARGB_8888;
15398                        break;
15399                }
15400            } else {
15401                // Optimization for translucent windows
15402                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15403                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15404            }
15405
15406            // Try to cleanup memory
15407            if (bitmap != null) bitmap.recycle();
15408
15409            try {
15410                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15411                        width, height, quality);
15412                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15413                if (autoScale) {
15414                    mDrawingCache = bitmap;
15415                } else {
15416                    mUnscaledDrawingCache = bitmap;
15417                }
15418                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15419            } catch (OutOfMemoryError e) {
15420                // If there is not enough memory to create the bitmap cache, just
15421                // ignore the issue as bitmap caches are not required to draw the
15422                // view hierarchy
15423                if (autoScale) {
15424                    mDrawingCache = null;
15425                } else {
15426                    mUnscaledDrawingCache = null;
15427                }
15428                mCachingFailed = true;
15429                return;
15430            }
15431
15432            clear = drawingCacheBackgroundColor != 0;
15433        }
15434
15435        Canvas canvas;
15436        if (attachInfo != null) {
15437            canvas = attachInfo.mCanvas;
15438            if (canvas == null) {
15439                canvas = new Canvas();
15440            }
15441            canvas.setBitmap(bitmap);
15442            // Temporarily clobber the cached Canvas in case one of our children
15443            // is also using a drawing cache. Without this, the children would
15444            // steal the canvas by attaching their own bitmap to it and bad, bad
15445            // thing would happen (invisible views, corrupted drawings, etc.)
15446            attachInfo.mCanvas = null;
15447        } else {
15448            // This case should hopefully never or seldom happen
15449            canvas = new Canvas(bitmap);
15450        }
15451
15452        if (clear) {
15453            bitmap.eraseColor(drawingCacheBackgroundColor);
15454        }
15455
15456        computeScroll();
15457        final int restoreCount = canvas.save();
15458
15459        if (autoScale && scalingRequired) {
15460            final float scale = attachInfo.mApplicationScale;
15461            canvas.scale(scale, scale);
15462        }
15463
15464        canvas.translate(-mScrollX, -mScrollY);
15465
15466        mPrivateFlags |= PFLAG_DRAWN;
15467        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15468                mLayerType != LAYER_TYPE_NONE) {
15469            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15470        }
15471
15472        // Fast path for layouts with no backgrounds
15473        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15474            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15475            dispatchDraw(canvas);
15476            if (mOverlay != null && !mOverlay.isEmpty()) {
15477                mOverlay.getOverlayView().draw(canvas);
15478            }
15479        } else {
15480            draw(canvas);
15481        }
15482
15483        canvas.restoreToCount(restoreCount);
15484        canvas.setBitmap(null);
15485
15486        if (attachInfo != null) {
15487            // Restore the cached Canvas for our siblings
15488            attachInfo.mCanvas = canvas;
15489        }
15490    }
15491
15492    /**
15493     * Create a snapshot of the view into a bitmap.  We should probably make
15494     * some form of this public, but should think about the API.
15495     */
15496    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15497        int width = mRight - mLeft;
15498        int height = mBottom - mTop;
15499
15500        final AttachInfo attachInfo = mAttachInfo;
15501        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15502        width = (int) ((width * scale) + 0.5f);
15503        height = (int) ((height * scale) + 0.5f);
15504
15505        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15506                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15507        if (bitmap == null) {
15508            throw new OutOfMemoryError();
15509        }
15510
15511        Resources resources = getResources();
15512        if (resources != null) {
15513            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15514        }
15515
15516        Canvas canvas;
15517        if (attachInfo != null) {
15518            canvas = attachInfo.mCanvas;
15519            if (canvas == null) {
15520                canvas = new Canvas();
15521            }
15522            canvas.setBitmap(bitmap);
15523            // Temporarily clobber the cached Canvas in case one of our children
15524            // is also using a drawing cache. Without this, the children would
15525            // steal the canvas by attaching their own bitmap to it and bad, bad
15526            // things would happen (invisible views, corrupted drawings, etc.)
15527            attachInfo.mCanvas = null;
15528        } else {
15529            // This case should hopefully never or seldom happen
15530            canvas = new Canvas(bitmap);
15531        }
15532
15533        if ((backgroundColor & 0xff000000) != 0) {
15534            bitmap.eraseColor(backgroundColor);
15535        }
15536
15537        computeScroll();
15538        final int restoreCount = canvas.save();
15539        canvas.scale(scale, scale);
15540        canvas.translate(-mScrollX, -mScrollY);
15541
15542        // Temporarily remove the dirty mask
15543        int flags = mPrivateFlags;
15544        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15545
15546        // Fast path for layouts with no backgrounds
15547        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15548            dispatchDraw(canvas);
15549            if (mOverlay != null && !mOverlay.isEmpty()) {
15550                mOverlay.getOverlayView().draw(canvas);
15551            }
15552        } else {
15553            draw(canvas);
15554        }
15555
15556        mPrivateFlags = flags;
15557
15558        canvas.restoreToCount(restoreCount);
15559        canvas.setBitmap(null);
15560
15561        if (attachInfo != null) {
15562            // Restore the cached Canvas for our siblings
15563            attachInfo.mCanvas = canvas;
15564        }
15565
15566        return bitmap;
15567    }
15568
15569    /**
15570     * Indicates whether this View is currently in edit mode. A View is usually
15571     * in edit mode when displayed within a developer tool. For instance, if
15572     * this View is being drawn by a visual user interface builder, this method
15573     * should return true.
15574     *
15575     * Subclasses should check the return value of this method to provide
15576     * different behaviors if their normal behavior might interfere with the
15577     * host environment. For instance: the class spawns a thread in its
15578     * constructor, the drawing code relies on device-specific features, etc.
15579     *
15580     * This method is usually checked in the drawing code of custom widgets.
15581     *
15582     * @return True if this View is in edit mode, false otherwise.
15583     */
15584    public boolean isInEditMode() {
15585        return false;
15586    }
15587
15588    /**
15589     * If the View draws content inside its padding and enables fading edges,
15590     * it needs to support padding offsets. Padding offsets are added to the
15591     * fading edges to extend the length of the fade so that it covers pixels
15592     * drawn inside the padding.
15593     *
15594     * Subclasses of this class should override this method if they need
15595     * to draw content inside the padding.
15596     *
15597     * @return True if padding offset must be applied, false otherwise.
15598     *
15599     * @see #getLeftPaddingOffset()
15600     * @see #getRightPaddingOffset()
15601     * @see #getTopPaddingOffset()
15602     * @see #getBottomPaddingOffset()
15603     *
15604     * @since CURRENT
15605     */
15606    protected boolean isPaddingOffsetRequired() {
15607        return false;
15608    }
15609
15610    /**
15611     * Amount by which to extend the left fading region. Called only when
15612     * {@link #isPaddingOffsetRequired()} returns true.
15613     *
15614     * @return The left padding offset in pixels.
15615     *
15616     * @see #isPaddingOffsetRequired()
15617     *
15618     * @since CURRENT
15619     */
15620    protected int getLeftPaddingOffset() {
15621        return 0;
15622    }
15623
15624    /**
15625     * Amount by which to extend the right fading region. Called only when
15626     * {@link #isPaddingOffsetRequired()} returns true.
15627     *
15628     * @return The right padding offset in pixels.
15629     *
15630     * @see #isPaddingOffsetRequired()
15631     *
15632     * @since CURRENT
15633     */
15634    protected int getRightPaddingOffset() {
15635        return 0;
15636    }
15637
15638    /**
15639     * Amount by which to extend the top fading region. Called only when
15640     * {@link #isPaddingOffsetRequired()} returns true.
15641     *
15642     * @return The top padding offset in pixels.
15643     *
15644     * @see #isPaddingOffsetRequired()
15645     *
15646     * @since CURRENT
15647     */
15648    protected int getTopPaddingOffset() {
15649        return 0;
15650    }
15651
15652    /**
15653     * Amount by which to extend the bottom fading region. Called only when
15654     * {@link #isPaddingOffsetRequired()} returns true.
15655     *
15656     * @return The bottom padding offset in pixels.
15657     *
15658     * @see #isPaddingOffsetRequired()
15659     *
15660     * @since CURRENT
15661     */
15662    protected int getBottomPaddingOffset() {
15663        return 0;
15664    }
15665
15666    /**
15667     * @hide
15668     * @param offsetRequired
15669     */
15670    protected int getFadeTop(boolean offsetRequired) {
15671        int top = mPaddingTop;
15672        if (offsetRequired) top += getTopPaddingOffset();
15673        return top;
15674    }
15675
15676    /**
15677     * @hide
15678     * @param offsetRequired
15679     */
15680    protected int getFadeHeight(boolean offsetRequired) {
15681        int padding = mPaddingTop;
15682        if (offsetRequired) padding += getTopPaddingOffset();
15683        return mBottom - mTop - mPaddingBottom - padding;
15684    }
15685
15686    /**
15687     * <p>Indicates whether this view is attached to a hardware accelerated
15688     * window or not.</p>
15689     *
15690     * <p>Even if this method returns true, it does not mean that every call
15691     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15692     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15693     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15694     * window is hardware accelerated,
15695     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15696     * return false, and this method will return true.</p>
15697     *
15698     * @return True if the view is attached to a window and the window is
15699     *         hardware accelerated; false in any other case.
15700     */
15701    @ViewDebug.ExportedProperty(category = "drawing")
15702    public boolean isHardwareAccelerated() {
15703        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15704    }
15705
15706    /**
15707     * Sets a rectangular area on this view to which the view will be clipped
15708     * when it is drawn. Setting the value to null will remove the clip bounds
15709     * and the view will draw normally, using its full bounds.
15710     *
15711     * @param clipBounds The rectangular area, in the local coordinates of
15712     * this view, to which future drawing operations will be clipped.
15713     */
15714    public void setClipBounds(Rect clipBounds) {
15715        if (clipBounds == mClipBounds
15716                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15717            return;
15718        }
15719        if (clipBounds != null) {
15720            if (mClipBounds == null) {
15721                mClipBounds = new Rect(clipBounds);
15722            } else {
15723                mClipBounds.set(clipBounds);
15724            }
15725        } else {
15726            mClipBounds = null;
15727        }
15728        mRenderNode.setClipBounds(mClipBounds);
15729        invalidateViewProperty(false, false);
15730    }
15731
15732    /**
15733     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
15734     *
15735     * @return A copy of the current clip bounds if clip bounds are set,
15736     * otherwise null.
15737     */
15738    public Rect getClipBounds() {
15739        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
15740    }
15741
15742
15743    /**
15744     * Populates an output rectangle with the clip bounds of the view,
15745     * returning {@code true} if successful or {@code false} if the view's
15746     * clip bounds are {@code null}.
15747     *
15748     * @param outRect rectangle in which to place the clip bounds of the view
15749     * @return {@code true} if successful or {@code false} if the view's
15750     *         clip bounds are {@code null}
15751     */
15752    public boolean getClipBounds(Rect outRect) {
15753        if (mClipBounds != null) {
15754            outRect.set(mClipBounds);
15755            return true;
15756        }
15757        return false;
15758    }
15759
15760    /**
15761     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
15762     * case of an active Animation being run on the view.
15763     */
15764    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
15765            Animation a, boolean scalingRequired) {
15766        Transformation invalidationTransform;
15767        final int flags = parent.mGroupFlags;
15768        final boolean initialized = a.isInitialized();
15769        if (!initialized) {
15770            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
15771            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
15772            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
15773            onAnimationStart();
15774        }
15775
15776        final Transformation t = parent.getChildTransformation();
15777        boolean more = a.getTransformation(drawingTime, t, 1f);
15778        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
15779            if (parent.mInvalidationTransformation == null) {
15780                parent.mInvalidationTransformation = new Transformation();
15781            }
15782            invalidationTransform = parent.mInvalidationTransformation;
15783            a.getTransformation(drawingTime, invalidationTransform, 1f);
15784        } else {
15785            invalidationTransform = t;
15786        }
15787
15788        if (more) {
15789            if (!a.willChangeBounds()) {
15790                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
15791                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
15792                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
15793                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
15794                    // The child need to draw an animation, potentially offscreen, so
15795                    // make sure we do not cancel invalidate requests
15796                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15797                    parent.invalidate(mLeft, mTop, mRight, mBottom);
15798                }
15799            } else {
15800                if (parent.mInvalidateRegion == null) {
15801                    parent.mInvalidateRegion = new RectF();
15802                }
15803                final RectF region = parent.mInvalidateRegion;
15804                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
15805                        invalidationTransform);
15806
15807                // The child need to draw an animation, potentially offscreen, so
15808                // make sure we do not cancel invalidate requests
15809                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
15810
15811                final int left = mLeft + (int) region.left;
15812                final int top = mTop + (int) region.top;
15813                parent.invalidate(left, top, left + (int) (region.width() + .5f),
15814                        top + (int) (region.height() + .5f));
15815            }
15816        }
15817        return more;
15818    }
15819
15820    /**
15821     * This method is called by getDisplayList() when a display list is recorded for a View.
15822     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
15823     */
15824    void setDisplayListProperties(RenderNode renderNode) {
15825        if (renderNode != null) {
15826            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
15827            renderNode.setClipToBounds(mParent instanceof ViewGroup
15828                    && ((ViewGroup) mParent).getClipChildren());
15829
15830            float alpha = 1;
15831            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
15832                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15833                ViewGroup parentVG = (ViewGroup) mParent;
15834                final Transformation t = parentVG.getChildTransformation();
15835                if (parentVG.getChildStaticTransformation(this, t)) {
15836                    final int transformType = t.getTransformationType();
15837                    if (transformType != Transformation.TYPE_IDENTITY) {
15838                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
15839                            alpha = t.getAlpha();
15840                        }
15841                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
15842                            renderNode.setStaticMatrix(t.getMatrix());
15843                        }
15844                    }
15845                }
15846            }
15847            if (mTransformationInfo != null) {
15848                alpha *= getFinalAlpha();
15849                if (alpha < 1) {
15850                    final int multipliedAlpha = (int) (255 * alpha);
15851                    if (onSetAlpha(multipliedAlpha)) {
15852                        alpha = 1;
15853                    }
15854                }
15855                renderNode.setAlpha(alpha);
15856            } else if (alpha < 1) {
15857                renderNode.setAlpha(alpha);
15858            }
15859        }
15860    }
15861
15862    /**
15863     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
15864     *
15865     * This is where the View specializes rendering behavior based on layer type,
15866     * and hardware acceleration.
15867     */
15868    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
15869        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
15870        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
15871         *
15872         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
15873         * HW accelerated, it can't handle drawing RenderNodes.
15874         */
15875        boolean drawingWithRenderNode = mAttachInfo != null
15876                && mAttachInfo.mHardwareAccelerated
15877                && hardwareAcceleratedCanvas;
15878
15879        boolean more = false;
15880        final boolean childHasIdentityMatrix = hasIdentityMatrix();
15881        final int parentFlags = parent.mGroupFlags;
15882
15883        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
15884            parent.getChildTransformation().clear();
15885            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
15886        }
15887
15888        Transformation transformToApply = null;
15889        boolean concatMatrix = false;
15890        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
15891        final Animation a = getAnimation();
15892        if (a != null) {
15893            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
15894            concatMatrix = a.willChangeTransformationMatrix();
15895            if (concatMatrix) {
15896                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15897            }
15898            transformToApply = parent.getChildTransformation();
15899        } else {
15900            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
15901                // No longer animating: clear out old animation matrix
15902                mRenderNode.setAnimationMatrix(null);
15903                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
15904            }
15905            if (!drawingWithRenderNode
15906                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
15907                final Transformation t = parent.getChildTransformation();
15908                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
15909                if (hasTransform) {
15910                    final int transformType = t.getTransformationType();
15911                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
15912                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
15913                }
15914            }
15915        }
15916
15917        concatMatrix |= !childHasIdentityMatrix;
15918
15919        // Sets the flag as early as possible to allow draw() implementations
15920        // to call invalidate() successfully when doing animations
15921        mPrivateFlags |= PFLAG_DRAWN;
15922
15923        if (!concatMatrix &&
15924                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
15925                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
15926                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
15927                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
15928            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
15929            return more;
15930        }
15931        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
15932
15933        if (hardwareAcceleratedCanvas) {
15934            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
15935            // retain the flag's value temporarily in the mRecreateDisplayList flag
15936            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
15937            mPrivateFlags &= ~PFLAG_INVALIDATED;
15938        }
15939
15940        RenderNode renderNode = null;
15941        Bitmap cache = null;
15942        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
15943        if (layerType == LAYER_TYPE_SOFTWARE
15944                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
15945            // If not drawing with RenderNode, treat HW layers as SW
15946            layerType = LAYER_TYPE_SOFTWARE;
15947            buildDrawingCache(true);
15948            cache = getDrawingCache(true);
15949        }
15950
15951        if (drawingWithRenderNode) {
15952            // Delay getting the display list until animation-driven alpha values are
15953            // set up and possibly passed on to the view
15954            renderNode = updateDisplayListIfDirty();
15955            if (!renderNode.isValid()) {
15956                // Uncommon, but possible. If a view is removed from the hierarchy during the call
15957                // to getDisplayList(), the display list will be marked invalid and we should not
15958                // try to use it again.
15959                renderNode = null;
15960                drawingWithRenderNode = false;
15961            }
15962        }
15963
15964        int sx = 0;
15965        int sy = 0;
15966        if (!drawingWithRenderNode) {
15967            computeScroll();
15968            sx = mScrollX;
15969            sy = mScrollY;
15970        }
15971
15972        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
15973        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
15974
15975        int restoreTo = -1;
15976        if (!drawingWithRenderNode || transformToApply != null) {
15977            restoreTo = canvas.save();
15978        }
15979        if (offsetForScroll) {
15980            canvas.translate(mLeft - sx, mTop - sy);
15981        } else {
15982            if (!drawingWithRenderNode) {
15983                canvas.translate(mLeft, mTop);
15984            }
15985            if (scalingRequired) {
15986                if (drawingWithRenderNode) {
15987                    // TODO: Might not need this if we put everything inside the DL
15988                    restoreTo = canvas.save();
15989                }
15990                // mAttachInfo cannot be null, otherwise scalingRequired == false
15991                final float scale = 1.0f / mAttachInfo.mApplicationScale;
15992                canvas.scale(scale, scale);
15993            }
15994        }
15995
15996        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
15997        if (transformToApply != null
15998                || alpha < 1
15999                || !hasIdentityMatrix()
16000                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16001            if (transformToApply != null || !childHasIdentityMatrix) {
16002                int transX = 0;
16003                int transY = 0;
16004
16005                if (offsetForScroll) {
16006                    transX = -sx;
16007                    transY = -sy;
16008                }
16009
16010                if (transformToApply != null) {
16011                    if (concatMatrix) {
16012                        if (drawingWithRenderNode) {
16013                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16014                        } else {
16015                            // Undo the scroll translation, apply the transformation matrix,
16016                            // then redo the scroll translate to get the correct result.
16017                            canvas.translate(-transX, -transY);
16018                            canvas.concat(transformToApply.getMatrix());
16019                            canvas.translate(transX, transY);
16020                        }
16021                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16022                    }
16023
16024                    float transformAlpha = transformToApply.getAlpha();
16025                    if (transformAlpha < 1) {
16026                        alpha *= transformAlpha;
16027                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16028                    }
16029                }
16030
16031                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16032                    canvas.translate(-transX, -transY);
16033                    canvas.concat(getMatrix());
16034                    canvas.translate(transX, transY);
16035                }
16036            }
16037
16038            // Deal with alpha if it is or used to be <1
16039            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16040                if (alpha < 1) {
16041                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16042                } else {
16043                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16044                }
16045                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16046                if (!drawingWithDrawingCache) {
16047                    final int multipliedAlpha = (int) (255 * alpha);
16048                    if (!onSetAlpha(multipliedAlpha)) {
16049                        if (drawingWithRenderNode) {
16050                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16051                        } else if (layerType == LAYER_TYPE_NONE) {
16052                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16053                                    multipliedAlpha);
16054                        }
16055                    } else {
16056                        // Alpha is handled by the child directly, clobber the layer's alpha
16057                        mPrivateFlags |= PFLAG_ALPHA_SET;
16058                    }
16059                }
16060            }
16061        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16062            onSetAlpha(255);
16063            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16064        }
16065
16066        if (!drawingWithRenderNode) {
16067            // apply clips directly, since RenderNode won't do it for this draw
16068            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16069                if (offsetForScroll) {
16070                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16071                } else {
16072                    if (!scalingRequired || cache == null) {
16073                        canvas.clipRect(0, 0, getWidth(), getHeight());
16074                    } else {
16075                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16076                    }
16077                }
16078            }
16079
16080            if (mClipBounds != null) {
16081                // clip bounds ignore scroll
16082                canvas.clipRect(mClipBounds);
16083            }
16084        }
16085
16086        if (!drawingWithDrawingCache) {
16087            if (drawingWithRenderNode) {
16088                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16089                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16090            } else {
16091                // Fast path for layouts with no backgrounds
16092                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16093                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16094                    dispatchDraw(canvas);
16095                } else {
16096                    draw(canvas);
16097                }
16098            }
16099        } else if (cache != null) {
16100            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16101            if (layerType == LAYER_TYPE_NONE) {
16102                // no layer paint, use temporary paint to draw bitmap
16103                Paint cachePaint = parent.mCachePaint;
16104                if (cachePaint == null) {
16105                    cachePaint = new Paint();
16106                    cachePaint.setDither(false);
16107                    parent.mCachePaint = cachePaint;
16108                }
16109                cachePaint.setAlpha((int) (alpha * 255));
16110                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16111            } else {
16112                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16113                int layerPaintAlpha = mLayerPaint.getAlpha();
16114                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16115                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16116                mLayerPaint.setAlpha(layerPaintAlpha);
16117            }
16118        }
16119
16120        if (restoreTo >= 0) {
16121            canvas.restoreToCount(restoreTo);
16122        }
16123
16124        if (a != null && !more) {
16125            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16126                onSetAlpha(255);
16127            }
16128            parent.finishAnimatingView(this, a);
16129        }
16130
16131        if (more && hardwareAcceleratedCanvas) {
16132            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16133                // alpha animations should cause the child to recreate its display list
16134                invalidate(true);
16135            }
16136        }
16137
16138        mRecreateDisplayList = false;
16139
16140        return more;
16141    }
16142
16143    /**
16144     * Manually render this view (and all of its children) to the given Canvas.
16145     * The view must have already done a full layout before this function is
16146     * called.  When implementing a view, implement
16147     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16148     * If you do need to override this method, call the superclass version.
16149     *
16150     * @param canvas The Canvas to which the View is rendered.
16151     */
16152    @CallSuper
16153    public void draw(Canvas canvas) {
16154        final int privateFlags = mPrivateFlags;
16155        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16156                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16157        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16158
16159        /*
16160         * Draw traversal performs several drawing steps which must be executed
16161         * in the appropriate order:
16162         *
16163         *      1. Draw the background
16164         *      2. If necessary, save the canvas' layers to prepare for fading
16165         *      3. Draw view's content
16166         *      4. Draw children
16167         *      5. If necessary, draw the fading edges and restore layers
16168         *      6. Draw decorations (scrollbars for instance)
16169         */
16170
16171        // Step 1, draw the background, if needed
16172        int saveCount;
16173
16174        if (!dirtyOpaque) {
16175            drawBackground(canvas);
16176        }
16177
16178        // skip step 2 & 5 if possible (common case)
16179        final int viewFlags = mViewFlags;
16180        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16181        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16182        if (!verticalEdges && !horizontalEdges) {
16183            // Step 3, draw the content
16184            if (!dirtyOpaque) onDraw(canvas);
16185
16186            // Step 4, draw the children
16187            dispatchDraw(canvas);
16188
16189            // Overlay is part of the content and draws beneath Foreground
16190            if (mOverlay != null && !mOverlay.isEmpty()) {
16191                mOverlay.getOverlayView().dispatchDraw(canvas);
16192            }
16193
16194            // Step 6, draw decorations (foreground, scrollbars)
16195            onDrawForeground(canvas);
16196
16197            // we're done...
16198            return;
16199        }
16200
16201        /*
16202         * Here we do the full fledged routine...
16203         * (this is an uncommon case where speed matters less,
16204         * this is why we repeat some of the tests that have been
16205         * done above)
16206         */
16207
16208        boolean drawTop = false;
16209        boolean drawBottom = false;
16210        boolean drawLeft = false;
16211        boolean drawRight = false;
16212
16213        float topFadeStrength = 0.0f;
16214        float bottomFadeStrength = 0.0f;
16215        float leftFadeStrength = 0.0f;
16216        float rightFadeStrength = 0.0f;
16217
16218        // Step 2, save the canvas' layers
16219        int paddingLeft = mPaddingLeft;
16220
16221        final boolean offsetRequired = isPaddingOffsetRequired();
16222        if (offsetRequired) {
16223            paddingLeft += getLeftPaddingOffset();
16224        }
16225
16226        int left = mScrollX + paddingLeft;
16227        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16228        int top = mScrollY + getFadeTop(offsetRequired);
16229        int bottom = top + getFadeHeight(offsetRequired);
16230
16231        if (offsetRequired) {
16232            right += getRightPaddingOffset();
16233            bottom += getBottomPaddingOffset();
16234        }
16235
16236        final ScrollabilityCache scrollabilityCache = mScrollCache;
16237        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16238        int length = (int) fadeHeight;
16239
16240        // clip the fade length if top and bottom fades overlap
16241        // overlapping fades produce odd-looking artifacts
16242        if (verticalEdges && (top + length > bottom - length)) {
16243            length = (bottom - top) / 2;
16244        }
16245
16246        // also clip horizontal fades if necessary
16247        if (horizontalEdges && (left + length > right - length)) {
16248            length = (right - left) / 2;
16249        }
16250
16251        if (verticalEdges) {
16252            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16253            drawTop = topFadeStrength * fadeHeight > 1.0f;
16254            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16255            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16256        }
16257
16258        if (horizontalEdges) {
16259            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16260            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16261            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16262            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16263        }
16264
16265        saveCount = canvas.getSaveCount();
16266
16267        int solidColor = getSolidColor();
16268        if (solidColor == 0) {
16269            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16270
16271            if (drawTop) {
16272                canvas.saveLayer(left, top, right, top + length, null, flags);
16273            }
16274
16275            if (drawBottom) {
16276                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16277            }
16278
16279            if (drawLeft) {
16280                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16281            }
16282
16283            if (drawRight) {
16284                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16285            }
16286        } else {
16287            scrollabilityCache.setFadeColor(solidColor);
16288        }
16289
16290        // Step 3, draw the content
16291        if (!dirtyOpaque) onDraw(canvas);
16292
16293        // Step 4, draw the children
16294        dispatchDraw(canvas);
16295
16296        // Step 5, draw the fade effect and restore layers
16297        final Paint p = scrollabilityCache.paint;
16298        final Matrix matrix = scrollabilityCache.matrix;
16299        final Shader fade = scrollabilityCache.shader;
16300
16301        if (drawTop) {
16302            matrix.setScale(1, fadeHeight * topFadeStrength);
16303            matrix.postTranslate(left, top);
16304            fade.setLocalMatrix(matrix);
16305            p.setShader(fade);
16306            canvas.drawRect(left, top, right, top + length, p);
16307        }
16308
16309        if (drawBottom) {
16310            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16311            matrix.postRotate(180);
16312            matrix.postTranslate(left, bottom);
16313            fade.setLocalMatrix(matrix);
16314            p.setShader(fade);
16315            canvas.drawRect(left, bottom - length, right, bottom, p);
16316        }
16317
16318        if (drawLeft) {
16319            matrix.setScale(1, fadeHeight * leftFadeStrength);
16320            matrix.postRotate(-90);
16321            matrix.postTranslate(left, top);
16322            fade.setLocalMatrix(matrix);
16323            p.setShader(fade);
16324            canvas.drawRect(left, top, left + length, bottom, p);
16325        }
16326
16327        if (drawRight) {
16328            matrix.setScale(1, fadeHeight * rightFadeStrength);
16329            matrix.postRotate(90);
16330            matrix.postTranslate(right, top);
16331            fade.setLocalMatrix(matrix);
16332            p.setShader(fade);
16333            canvas.drawRect(right - length, top, right, bottom, p);
16334        }
16335
16336        canvas.restoreToCount(saveCount);
16337
16338        // Overlay is part of the content and draws beneath Foreground
16339        if (mOverlay != null && !mOverlay.isEmpty()) {
16340            mOverlay.getOverlayView().dispatchDraw(canvas);
16341        }
16342
16343        // Step 6, draw decorations (foreground, scrollbars)
16344        onDrawForeground(canvas);
16345    }
16346
16347    /**
16348     * Draws the background onto the specified canvas.
16349     *
16350     * @param canvas Canvas on which to draw the background
16351     */
16352    private void drawBackground(Canvas canvas) {
16353        final Drawable background = mBackground;
16354        if (background == null) {
16355            return;
16356        }
16357
16358        setBackgroundBounds();
16359
16360        // Attempt to use a display list if requested.
16361        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16362                && mAttachInfo.mHardwareRenderer != null) {
16363            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16364
16365            final RenderNode renderNode = mBackgroundRenderNode;
16366            if (renderNode != null && renderNode.isValid()) {
16367                setBackgroundRenderNodeProperties(renderNode);
16368                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16369                return;
16370            }
16371        }
16372
16373        final int scrollX = mScrollX;
16374        final int scrollY = mScrollY;
16375        if ((scrollX | scrollY) == 0) {
16376            background.draw(canvas);
16377        } else {
16378            canvas.translate(scrollX, scrollY);
16379            background.draw(canvas);
16380            canvas.translate(-scrollX, -scrollY);
16381        }
16382    }
16383
16384    /**
16385     * Sets the correct background bounds and rebuilds the outline, if needed.
16386     * <p/>
16387     * This is called by LayoutLib.
16388     */
16389    void setBackgroundBounds() {
16390        if (mBackgroundSizeChanged && mBackground != null) {
16391            mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
16392            mBackgroundSizeChanged = false;
16393            rebuildOutline();
16394        }
16395    }
16396
16397    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16398        renderNode.setTranslationX(mScrollX);
16399        renderNode.setTranslationY(mScrollY);
16400    }
16401
16402    /**
16403     * Creates a new display list or updates the existing display list for the
16404     * specified Drawable.
16405     *
16406     * @param drawable Drawable for which to create a display list
16407     * @param renderNode Existing RenderNode, or {@code null}
16408     * @return A valid display list for the specified drawable
16409     */
16410    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16411        if (renderNode == null) {
16412            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16413        }
16414
16415        final Rect bounds = drawable.getBounds();
16416        final int width = bounds.width();
16417        final int height = bounds.height();
16418        final DisplayListCanvas canvas = renderNode.start(width, height);
16419
16420        // Reverse left/top translation done by drawable canvas, which will
16421        // instead be applied by rendernode's LTRB bounds below. This way, the
16422        // drawable's bounds match with its rendernode bounds and its content
16423        // will lie within those bounds in the rendernode tree.
16424        canvas.translate(-bounds.left, -bounds.top);
16425
16426        try {
16427            drawable.draw(canvas);
16428        } finally {
16429            renderNode.end(canvas);
16430        }
16431
16432        // Set up drawable properties that are view-independent.
16433        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16434        renderNode.setProjectBackwards(drawable.isProjected());
16435        renderNode.setProjectionReceiver(true);
16436        renderNode.setClipToBounds(false);
16437        return renderNode;
16438    }
16439
16440    /**
16441     * Returns the overlay for this view, creating it if it does not yet exist.
16442     * Adding drawables to the overlay will cause them to be displayed whenever
16443     * the view itself is redrawn. Objects in the overlay should be actively
16444     * managed: remove them when they should not be displayed anymore. The
16445     * overlay will always have the same size as its host view.
16446     *
16447     * <p>Note: Overlays do not currently work correctly with {@link
16448     * SurfaceView} or {@link TextureView}; contents in overlays for these
16449     * types of views may not display correctly.</p>
16450     *
16451     * @return The ViewOverlay object for this view.
16452     * @see ViewOverlay
16453     */
16454    public ViewOverlay getOverlay() {
16455        if (mOverlay == null) {
16456            mOverlay = new ViewOverlay(mContext, this);
16457        }
16458        return mOverlay;
16459    }
16460
16461    /**
16462     * Override this if your view is known to always be drawn on top of a solid color background,
16463     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16464     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16465     * should be set to 0xFF.
16466     *
16467     * @see #setVerticalFadingEdgeEnabled(boolean)
16468     * @see #setHorizontalFadingEdgeEnabled(boolean)
16469     *
16470     * @return The known solid color background for this view, or 0 if the color may vary
16471     */
16472    @ViewDebug.ExportedProperty(category = "drawing")
16473    @ColorInt
16474    public int getSolidColor() {
16475        return 0;
16476    }
16477
16478    /**
16479     * Build a human readable string representation of the specified view flags.
16480     *
16481     * @param flags the view flags to convert to a string
16482     * @return a String representing the supplied flags
16483     */
16484    private static String printFlags(int flags) {
16485        String output = "";
16486        int numFlags = 0;
16487        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16488            output += "TAKES_FOCUS";
16489            numFlags++;
16490        }
16491
16492        switch (flags & VISIBILITY_MASK) {
16493        case INVISIBLE:
16494            if (numFlags > 0) {
16495                output += " ";
16496            }
16497            output += "INVISIBLE";
16498            // USELESS HERE numFlags++;
16499            break;
16500        case GONE:
16501            if (numFlags > 0) {
16502                output += " ";
16503            }
16504            output += "GONE";
16505            // USELESS HERE numFlags++;
16506            break;
16507        default:
16508            break;
16509        }
16510        return output;
16511    }
16512
16513    /**
16514     * Build a human readable string representation of the specified private
16515     * view flags.
16516     *
16517     * @param privateFlags the private view flags to convert to a string
16518     * @return a String representing the supplied flags
16519     */
16520    private static String printPrivateFlags(int privateFlags) {
16521        String output = "";
16522        int numFlags = 0;
16523
16524        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16525            output += "WANTS_FOCUS";
16526            numFlags++;
16527        }
16528
16529        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16530            if (numFlags > 0) {
16531                output += " ";
16532            }
16533            output += "FOCUSED";
16534            numFlags++;
16535        }
16536
16537        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16538            if (numFlags > 0) {
16539                output += " ";
16540            }
16541            output += "SELECTED";
16542            numFlags++;
16543        }
16544
16545        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16546            if (numFlags > 0) {
16547                output += " ";
16548            }
16549            output += "IS_ROOT_NAMESPACE";
16550            numFlags++;
16551        }
16552
16553        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16554            if (numFlags > 0) {
16555                output += " ";
16556            }
16557            output += "HAS_BOUNDS";
16558            numFlags++;
16559        }
16560
16561        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16562            if (numFlags > 0) {
16563                output += " ";
16564            }
16565            output += "DRAWN";
16566            // USELESS HERE numFlags++;
16567        }
16568        return output;
16569    }
16570
16571    /**
16572     * <p>Indicates whether or not this view's layout will be requested during
16573     * the next hierarchy layout pass.</p>
16574     *
16575     * @return true if the layout will be forced during next layout pass
16576     */
16577    public boolean isLayoutRequested() {
16578        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16579    }
16580
16581    /**
16582     * Return true if o is a ViewGroup that is laying out using optical bounds.
16583     * @hide
16584     */
16585    public static boolean isLayoutModeOptical(Object o) {
16586        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16587    }
16588
16589    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16590        Insets parentInsets = mParent instanceof View ?
16591                ((View) mParent).getOpticalInsets() : Insets.NONE;
16592        Insets childInsets = getOpticalInsets();
16593        return setFrame(
16594                left   + parentInsets.left - childInsets.left,
16595                top    + parentInsets.top  - childInsets.top,
16596                right  + parentInsets.left + childInsets.right,
16597                bottom + parentInsets.top  + childInsets.bottom);
16598    }
16599
16600    /**
16601     * Assign a size and position to a view and all of its
16602     * descendants
16603     *
16604     * <p>This is the second phase of the layout mechanism.
16605     * (The first is measuring). In this phase, each parent calls
16606     * layout on all of its children to position them.
16607     * This is typically done using the child measurements
16608     * that were stored in the measure pass().</p>
16609     *
16610     * <p>Derived classes should not override this method.
16611     * Derived classes with children should override
16612     * onLayout. In that method, they should
16613     * call layout on each of their children.</p>
16614     *
16615     * @param l Left position, relative to parent
16616     * @param t Top position, relative to parent
16617     * @param r Right position, relative to parent
16618     * @param b Bottom position, relative to parent
16619     */
16620    @SuppressWarnings({"unchecked"})
16621    public void layout(int l, int t, int r, int b) {
16622        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16623            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16624            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16625        }
16626
16627        int oldL = mLeft;
16628        int oldT = mTop;
16629        int oldB = mBottom;
16630        int oldR = mRight;
16631
16632        boolean changed = isLayoutModeOptical(mParent) ?
16633                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16634
16635        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16636            onLayout(changed, l, t, r, b);
16637            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16638
16639            ListenerInfo li = mListenerInfo;
16640            if (li != null && li.mOnLayoutChangeListeners != null) {
16641                ArrayList<OnLayoutChangeListener> listenersCopy =
16642                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16643                int numListeners = listenersCopy.size();
16644                for (int i = 0; i < numListeners; ++i) {
16645                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16646                }
16647            }
16648        }
16649
16650        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16651        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16652    }
16653
16654    /**
16655     * Called from layout when this view should
16656     * assign a size and position to each of its children.
16657     *
16658     * Derived classes with children should override
16659     * this method and call layout on each of
16660     * their children.
16661     * @param changed This is a new size or position for this view
16662     * @param left Left position, relative to parent
16663     * @param top Top position, relative to parent
16664     * @param right Right position, relative to parent
16665     * @param bottom Bottom position, relative to parent
16666     */
16667    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16668    }
16669
16670    /**
16671     * Assign a size and position to this view.
16672     *
16673     * This is called from layout.
16674     *
16675     * @param left Left position, relative to parent
16676     * @param top Top position, relative to parent
16677     * @param right Right position, relative to parent
16678     * @param bottom Bottom position, relative to parent
16679     * @return true if the new size and position are different than the
16680     *         previous ones
16681     * {@hide}
16682     */
16683    protected boolean setFrame(int left, int top, int right, int bottom) {
16684        boolean changed = false;
16685
16686        if (DBG) {
16687            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16688                    + right + "," + bottom + ")");
16689        }
16690
16691        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16692            changed = true;
16693
16694            // Remember our drawn bit
16695            int drawn = mPrivateFlags & PFLAG_DRAWN;
16696
16697            int oldWidth = mRight - mLeft;
16698            int oldHeight = mBottom - mTop;
16699            int newWidth = right - left;
16700            int newHeight = bottom - top;
16701            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16702
16703            // Invalidate our old position
16704            invalidate(sizeChanged);
16705
16706            mLeft = left;
16707            mTop = top;
16708            mRight = right;
16709            mBottom = bottom;
16710            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16711
16712            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16713
16714
16715            if (sizeChanged) {
16716                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16717            }
16718
16719            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16720                // If we are visible, force the DRAWN bit to on so that
16721                // this invalidate will go through (at least to our parent).
16722                // This is because someone may have invalidated this view
16723                // before this call to setFrame came in, thereby clearing
16724                // the DRAWN bit.
16725                mPrivateFlags |= PFLAG_DRAWN;
16726                invalidate(sizeChanged);
16727                // parent display list may need to be recreated based on a change in the bounds
16728                // of any child
16729                invalidateParentCaches();
16730            }
16731
16732            // Reset drawn bit to original value (invalidate turns it off)
16733            mPrivateFlags |= drawn;
16734
16735            mBackgroundSizeChanged = true;
16736            if (mForegroundInfo != null) {
16737                mForegroundInfo.mBoundsChanged = true;
16738            }
16739
16740            notifySubtreeAccessibilityStateChangedIfNeeded();
16741        }
16742        return changed;
16743    }
16744
16745    /**
16746     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
16747     * @hide
16748     */
16749    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
16750        setFrame(left, top, right, bottom);
16751    }
16752
16753    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
16754        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
16755        if (mOverlay != null) {
16756            mOverlay.getOverlayView().setRight(newWidth);
16757            mOverlay.getOverlayView().setBottom(newHeight);
16758        }
16759        rebuildOutline();
16760    }
16761
16762    /**
16763     * Finalize inflating a view from XML.  This is called as the last phase
16764     * of inflation, after all child views have been added.
16765     *
16766     * <p>Even if the subclass overrides onFinishInflate, they should always be
16767     * sure to call the super method, so that we get called.
16768     */
16769    @CallSuper
16770    protected void onFinishInflate() {
16771    }
16772
16773    /**
16774     * Returns the resources associated with this view.
16775     *
16776     * @return Resources object.
16777     */
16778    public Resources getResources() {
16779        return mResources;
16780    }
16781
16782    /**
16783     * Invalidates the specified Drawable.
16784     *
16785     * @param drawable the drawable to invalidate
16786     */
16787    @Override
16788    public void invalidateDrawable(@NonNull Drawable drawable) {
16789        if (verifyDrawable(drawable)) {
16790            final Rect dirty = drawable.getDirtyBounds();
16791            final int scrollX = mScrollX;
16792            final int scrollY = mScrollY;
16793
16794            invalidate(dirty.left + scrollX, dirty.top + scrollY,
16795                    dirty.right + scrollX, dirty.bottom + scrollY);
16796            rebuildOutline();
16797        }
16798    }
16799
16800    /**
16801     * Schedules an action on a drawable to occur at a specified time.
16802     *
16803     * @param who the recipient of the action
16804     * @param what the action to run on the drawable
16805     * @param when the time at which the action must occur. Uses the
16806     *        {@link SystemClock#uptimeMillis} timebase.
16807     */
16808    @Override
16809    public void scheduleDrawable(Drawable who, Runnable what, long when) {
16810        if (verifyDrawable(who) && what != null) {
16811            final long delay = when - SystemClock.uptimeMillis();
16812            if (mAttachInfo != null) {
16813                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
16814                        Choreographer.CALLBACK_ANIMATION, what, who,
16815                        Choreographer.subtractFrameDelay(delay));
16816            } else {
16817                ViewRootImpl.getRunQueue().postDelayed(what, delay);
16818            }
16819        }
16820    }
16821
16822    /**
16823     * Cancels a scheduled action on a drawable.
16824     *
16825     * @param who the recipient of the action
16826     * @param what the action to cancel
16827     */
16828    @Override
16829    public void unscheduleDrawable(Drawable who, Runnable what) {
16830        if (verifyDrawable(who) && what != null) {
16831            if (mAttachInfo != null) {
16832                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16833                        Choreographer.CALLBACK_ANIMATION, what, who);
16834            }
16835            ViewRootImpl.getRunQueue().removeCallbacks(what);
16836        }
16837    }
16838
16839    /**
16840     * Unschedule any events associated with the given Drawable.  This can be
16841     * used when selecting a new Drawable into a view, so that the previous
16842     * one is completely unscheduled.
16843     *
16844     * @param who The Drawable to unschedule.
16845     *
16846     * @see #drawableStateChanged
16847     */
16848    public void unscheduleDrawable(Drawable who) {
16849        if (mAttachInfo != null && who != null) {
16850            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
16851                    Choreographer.CALLBACK_ANIMATION, null, who);
16852        }
16853    }
16854
16855    /**
16856     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
16857     * that the View directionality can and will be resolved before its Drawables.
16858     *
16859     * Will call {@link View#onResolveDrawables} when resolution is done.
16860     *
16861     * @hide
16862     */
16863    protected void resolveDrawables() {
16864        // Drawables resolution may need to happen before resolving the layout direction (which is
16865        // done only during the measure() call).
16866        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
16867        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
16868        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
16869        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
16870        // direction to be resolved as its resolved value will be the same as its raw value.
16871        if (!isLayoutDirectionResolved() &&
16872                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
16873            return;
16874        }
16875
16876        final int layoutDirection = isLayoutDirectionResolved() ?
16877                getLayoutDirection() : getRawLayoutDirection();
16878
16879        if (mBackground != null) {
16880            mBackground.setLayoutDirection(layoutDirection);
16881        }
16882        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16883            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
16884        }
16885        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
16886        onResolveDrawables(layoutDirection);
16887    }
16888
16889    boolean areDrawablesResolved() {
16890        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
16891    }
16892
16893    /**
16894     * Called when layout direction has been resolved.
16895     *
16896     * The default implementation does nothing.
16897     *
16898     * @param layoutDirection The resolved layout direction.
16899     *
16900     * @see #LAYOUT_DIRECTION_LTR
16901     * @see #LAYOUT_DIRECTION_RTL
16902     *
16903     * @hide
16904     */
16905    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
16906    }
16907
16908    /**
16909     * @hide
16910     */
16911    protected void resetResolvedDrawables() {
16912        resetResolvedDrawablesInternal();
16913    }
16914
16915    void resetResolvedDrawablesInternal() {
16916        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
16917    }
16918
16919    /**
16920     * If your view subclass is displaying its own Drawable objects, it should
16921     * override this function and return true for any Drawable it is
16922     * displaying.  This allows animations for those drawables to be
16923     * scheduled.
16924     *
16925     * <p>Be sure to call through to the super class when overriding this
16926     * function.
16927     *
16928     * @param who The Drawable to verify.  Return true if it is one you are
16929     *            displaying, else return the result of calling through to the
16930     *            super class.
16931     *
16932     * @return boolean If true than the Drawable is being displayed in the
16933     *         view; else false and it is not allowed to animate.
16934     *
16935     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
16936     * @see #drawableStateChanged()
16937     */
16938    @CallSuper
16939    protected boolean verifyDrawable(Drawable who) {
16940        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
16941                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
16942    }
16943
16944    /**
16945     * This function is called whenever the state of the view changes in such
16946     * a way that it impacts the state of drawables being shown.
16947     * <p>
16948     * If the View has a StateListAnimator, it will also be called to run necessary state
16949     * change animations.
16950     * <p>
16951     * Be sure to call through to the superclass when overriding this function.
16952     *
16953     * @see Drawable#setState(int[])
16954     */
16955    @CallSuper
16956    protected void drawableStateChanged() {
16957        final int[] state = getDrawableState();
16958
16959        final Drawable bg = mBackground;
16960        if (bg != null && bg.isStateful()) {
16961            bg.setState(state);
16962        }
16963
16964        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
16965        if (fg != null && fg.isStateful()) {
16966            fg.setState(state);
16967        }
16968
16969        if (mScrollCache != null) {
16970            final Drawable scrollBar = mScrollCache.scrollBar;
16971            if (scrollBar != null && scrollBar.isStateful()) {
16972                scrollBar.setState(state);
16973            }
16974        }
16975
16976        if (mStateListAnimator != null) {
16977            mStateListAnimator.setState(state);
16978        }
16979    }
16980
16981    /**
16982     * This function is called whenever the view hotspot changes and needs to
16983     * be propagated to drawables or child views managed by the view.
16984     * <p>
16985     * Dispatching to child views is handled by
16986     * {@link #dispatchDrawableHotspotChanged(float, float)}.
16987     * <p>
16988     * Be sure to call through to the superclass when overriding this function.
16989     *
16990     * @param x hotspot x coordinate
16991     * @param y hotspot y coordinate
16992     */
16993    @CallSuper
16994    public void drawableHotspotChanged(float x, float y) {
16995        if (mBackground != null) {
16996            mBackground.setHotspot(x, y);
16997        }
16998        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
16999            mForegroundInfo.mDrawable.setHotspot(x, y);
17000        }
17001
17002        dispatchDrawableHotspotChanged(x, y);
17003    }
17004
17005    /**
17006     * Dispatches drawableHotspotChanged to all of this View's children.
17007     *
17008     * @param x hotspot x coordinate
17009     * @param y hotspot y coordinate
17010     * @see #drawableHotspotChanged(float, float)
17011     */
17012    public void dispatchDrawableHotspotChanged(float x, float y) {
17013    }
17014
17015    /**
17016     * Call this to force a view to update its drawable state. This will cause
17017     * drawableStateChanged to be called on this view. Views that are interested
17018     * in the new state should call getDrawableState.
17019     *
17020     * @see #drawableStateChanged
17021     * @see #getDrawableState
17022     */
17023    public void refreshDrawableState() {
17024        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17025        drawableStateChanged();
17026
17027        ViewParent parent = mParent;
17028        if (parent != null) {
17029            parent.childDrawableStateChanged(this);
17030        }
17031    }
17032
17033    /**
17034     * Return an array of resource IDs of the drawable states representing the
17035     * current state of the view.
17036     *
17037     * @return The current drawable state
17038     *
17039     * @see Drawable#setState(int[])
17040     * @see #drawableStateChanged()
17041     * @see #onCreateDrawableState(int)
17042     */
17043    public final int[] getDrawableState() {
17044        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17045            return mDrawableState;
17046        } else {
17047            mDrawableState = onCreateDrawableState(0);
17048            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17049            return mDrawableState;
17050        }
17051    }
17052
17053    /**
17054     * Generate the new {@link android.graphics.drawable.Drawable} state for
17055     * this view. This is called by the view
17056     * system when the cached Drawable state is determined to be invalid.  To
17057     * retrieve the current state, you should use {@link #getDrawableState}.
17058     *
17059     * @param extraSpace if non-zero, this is the number of extra entries you
17060     * would like in the returned array in which you can place your own
17061     * states.
17062     *
17063     * @return Returns an array holding the current {@link Drawable} state of
17064     * the view.
17065     *
17066     * @see #mergeDrawableStates(int[], int[])
17067     */
17068    protected int[] onCreateDrawableState(int extraSpace) {
17069        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17070                mParent instanceof View) {
17071            return ((View) mParent).onCreateDrawableState(extraSpace);
17072        }
17073
17074        int[] drawableState;
17075
17076        int privateFlags = mPrivateFlags;
17077
17078        int viewStateIndex = 0;
17079        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17080        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17081        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17082        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17083        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17084        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17085        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17086                HardwareRenderer.isAvailable()) {
17087            // This is set if HW acceleration is requested, even if the current
17088            // process doesn't allow it.  This is just to allow app preview
17089            // windows to better match their app.
17090            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17091        }
17092        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17093
17094        final int privateFlags2 = mPrivateFlags2;
17095        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17096            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17097        }
17098        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17099            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17100        }
17101
17102        drawableState = StateSet.get(viewStateIndex);
17103
17104        //noinspection ConstantIfStatement
17105        if (false) {
17106            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17107            Log.i("View", toString()
17108                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17109                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17110                    + " fo=" + hasFocus()
17111                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17112                    + " wf=" + hasWindowFocus()
17113                    + ": " + Arrays.toString(drawableState));
17114        }
17115
17116        if (extraSpace == 0) {
17117            return drawableState;
17118        }
17119
17120        final int[] fullState;
17121        if (drawableState != null) {
17122            fullState = new int[drawableState.length + extraSpace];
17123            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17124        } else {
17125            fullState = new int[extraSpace];
17126        }
17127
17128        return fullState;
17129    }
17130
17131    /**
17132     * Merge your own state values in <var>additionalState</var> into the base
17133     * state values <var>baseState</var> that were returned by
17134     * {@link #onCreateDrawableState(int)}.
17135     *
17136     * @param baseState The base state values returned by
17137     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17138     * own additional state values.
17139     *
17140     * @param additionalState The additional state values you would like
17141     * added to <var>baseState</var>; this array is not modified.
17142     *
17143     * @return As a convenience, the <var>baseState</var> array you originally
17144     * passed into the function is returned.
17145     *
17146     * @see #onCreateDrawableState(int)
17147     */
17148    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17149        final int N = baseState.length;
17150        int i = N - 1;
17151        while (i >= 0 && baseState[i] == 0) {
17152            i--;
17153        }
17154        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17155        return baseState;
17156    }
17157
17158    /**
17159     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17160     * on all Drawable objects associated with this view.
17161     * <p>
17162     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17163     * attached to this view.
17164     */
17165    @CallSuper
17166    public void jumpDrawablesToCurrentState() {
17167        if (mBackground != null) {
17168            mBackground.jumpToCurrentState();
17169        }
17170        if (mStateListAnimator != null) {
17171            mStateListAnimator.jumpToCurrentState();
17172        }
17173        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17174            mForegroundInfo.mDrawable.jumpToCurrentState();
17175        }
17176    }
17177
17178    /**
17179     * Sets the background color for this view.
17180     * @param color the color of the background
17181     */
17182    @RemotableViewMethod
17183    public void setBackgroundColor(@ColorInt int color) {
17184        if (mBackground instanceof ColorDrawable) {
17185            ((ColorDrawable) mBackground.mutate()).setColor(color);
17186            computeOpaqueFlags();
17187            mBackgroundResource = 0;
17188        } else {
17189            setBackground(new ColorDrawable(color));
17190        }
17191    }
17192
17193    /**
17194     * Set the background to a given resource. The resource should refer to
17195     * a Drawable object or 0 to remove the background.
17196     * @param resid The identifier of the resource.
17197     *
17198     * @attr ref android.R.styleable#View_background
17199     */
17200    @RemotableViewMethod
17201    public void setBackgroundResource(@DrawableRes int resid) {
17202        if (resid != 0 && resid == mBackgroundResource) {
17203            return;
17204        }
17205
17206        Drawable d = null;
17207        if (resid != 0) {
17208            d = mContext.getDrawable(resid);
17209        }
17210        setBackground(d);
17211
17212        mBackgroundResource = resid;
17213    }
17214
17215    /**
17216     * Set the background to a given Drawable, or remove the background. If the
17217     * background has padding, this View's padding is set to the background's
17218     * padding. However, when a background is removed, this View's padding isn't
17219     * touched. If setting the padding is desired, please use
17220     * {@link #setPadding(int, int, int, int)}.
17221     *
17222     * @param background The Drawable to use as the background, or null to remove the
17223     *        background
17224     */
17225    public void setBackground(Drawable background) {
17226        //noinspection deprecation
17227        setBackgroundDrawable(background);
17228    }
17229
17230    /**
17231     * @deprecated use {@link #setBackground(Drawable)} instead
17232     */
17233    @Deprecated
17234    public void setBackgroundDrawable(Drawable background) {
17235        computeOpaqueFlags();
17236
17237        if (background == mBackground) {
17238            return;
17239        }
17240
17241        boolean requestLayout = false;
17242
17243        mBackgroundResource = 0;
17244
17245        /*
17246         * Regardless of whether we're setting a new background or not, we want
17247         * to clear the previous drawable.
17248         */
17249        if (mBackground != null) {
17250            mBackground.setCallback(null);
17251            unscheduleDrawable(mBackground);
17252        }
17253
17254        if (background != null) {
17255            Rect padding = sThreadLocal.get();
17256            if (padding == null) {
17257                padding = new Rect();
17258                sThreadLocal.set(padding);
17259            }
17260            resetResolvedDrawablesInternal();
17261            background.setLayoutDirection(getLayoutDirection());
17262            if (background.getPadding(padding)) {
17263                resetResolvedPaddingInternal();
17264                switch (background.getLayoutDirection()) {
17265                    case LAYOUT_DIRECTION_RTL:
17266                        mUserPaddingLeftInitial = padding.right;
17267                        mUserPaddingRightInitial = padding.left;
17268                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17269                        break;
17270                    case LAYOUT_DIRECTION_LTR:
17271                    default:
17272                        mUserPaddingLeftInitial = padding.left;
17273                        mUserPaddingRightInitial = padding.right;
17274                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17275                }
17276                mLeftPaddingDefined = false;
17277                mRightPaddingDefined = false;
17278            }
17279
17280            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17281            // if it has a different minimum size, we should layout again
17282            if (mBackground == null
17283                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17284                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17285                requestLayout = true;
17286            }
17287
17288            background.setCallback(this);
17289            if (background.isStateful()) {
17290                background.setState(getDrawableState());
17291            }
17292            background.setVisible(getVisibility() == VISIBLE, false);
17293            mBackground = background;
17294
17295            applyBackgroundTint();
17296
17297            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17298                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17299                requestLayout = true;
17300            }
17301        } else {
17302            /* Remove the background */
17303            mBackground = null;
17304            if ((mViewFlags & WILL_NOT_DRAW) != 0
17305                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17306                mPrivateFlags |= PFLAG_SKIP_DRAW;
17307            }
17308
17309            /*
17310             * When the background is set, we try to apply its padding to this
17311             * View. When the background is removed, we don't touch this View's
17312             * padding. This is noted in the Javadocs. Hence, we don't need to
17313             * requestLayout(), the invalidate() below is sufficient.
17314             */
17315
17316            // The old background's minimum size could have affected this
17317            // View's layout, so let's requestLayout
17318            requestLayout = true;
17319        }
17320
17321        computeOpaqueFlags();
17322
17323        if (requestLayout) {
17324            requestLayout();
17325        }
17326
17327        mBackgroundSizeChanged = true;
17328        invalidate(true);
17329    }
17330
17331    /**
17332     * Gets the background drawable
17333     *
17334     * @return The drawable used as the background for this view, if any.
17335     *
17336     * @see #setBackground(Drawable)
17337     *
17338     * @attr ref android.R.styleable#View_background
17339     */
17340    public Drawable getBackground() {
17341        return mBackground;
17342    }
17343
17344    /**
17345     * Applies a tint to the background drawable. Does not modify the current tint
17346     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17347     * <p>
17348     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17349     * mutate the drawable and apply the specified tint and tint mode using
17350     * {@link Drawable#setTintList(ColorStateList)}.
17351     *
17352     * @param tint the tint to apply, may be {@code null} to clear tint
17353     *
17354     * @attr ref android.R.styleable#View_backgroundTint
17355     * @see #getBackgroundTintList()
17356     * @see Drawable#setTintList(ColorStateList)
17357     */
17358    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17359        if (mBackgroundTint == null) {
17360            mBackgroundTint = new TintInfo();
17361        }
17362        mBackgroundTint.mTintList = tint;
17363        mBackgroundTint.mHasTintList = true;
17364
17365        applyBackgroundTint();
17366    }
17367
17368    /**
17369     * Return the tint applied to the background drawable, if specified.
17370     *
17371     * @return the tint applied to the background drawable
17372     * @attr ref android.R.styleable#View_backgroundTint
17373     * @see #setBackgroundTintList(ColorStateList)
17374     */
17375    @Nullable
17376    public ColorStateList getBackgroundTintList() {
17377        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17378    }
17379
17380    /**
17381     * Specifies the blending mode used to apply the tint specified by
17382     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17383     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17384     *
17385     * @param tintMode the blending mode used to apply the tint, may be
17386     *                 {@code null} to clear tint
17387     * @attr ref android.R.styleable#View_backgroundTintMode
17388     * @see #getBackgroundTintMode()
17389     * @see Drawable#setTintMode(PorterDuff.Mode)
17390     */
17391    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17392        if (mBackgroundTint == null) {
17393            mBackgroundTint = new TintInfo();
17394        }
17395        mBackgroundTint.mTintMode = tintMode;
17396        mBackgroundTint.mHasTintMode = true;
17397
17398        applyBackgroundTint();
17399    }
17400
17401    /**
17402     * Return the blending mode used to apply the tint to the background
17403     * drawable, if specified.
17404     *
17405     * @return the blending mode used to apply the tint to the background
17406     *         drawable
17407     * @attr ref android.R.styleable#View_backgroundTintMode
17408     * @see #setBackgroundTintMode(PorterDuff.Mode)
17409     */
17410    @Nullable
17411    public PorterDuff.Mode getBackgroundTintMode() {
17412        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17413    }
17414
17415    private void applyBackgroundTint() {
17416        if (mBackground != null && mBackgroundTint != null) {
17417            final TintInfo tintInfo = mBackgroundTint;
17418            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17419                mBackground = mBackground.mutate();
17420
17421                if (tintInfo.mHasTintList) {
17422                    mBackground.setTintList(tintInfo.mTintList);
17423                }
17424
17425                if (tintInfo.mHasTintMode) {
17426                    mBackground.setTintMode(tintInfo.mTintMode);
17427                }
17428
17429                // The drawable (or one of its children) may not have been
17430                // stateful before applying the tint, so let's try again.
17431                if (mBackground.isStateful()) {
17432                    mBackground.setState(getDrawableState());
17433                }
17434            }
17435        }
17436    }
17437
17438    /**
17439     * Returns the drawable used as the foreground of this View. The
17440     * foreground drawable, if non-null, is always drawn on top of the view's content.
17441     *
17442     * @return a Drawable or null if no foreground was set
17443     *
17444     * @see #onDrawForeground(Canvas)
17445     */
17446    public Drawable getForeground() {
17447        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17448    }
17449
17450    /**
17451     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17452     *
17453     * @param foreground the Drawable to be drawn on top of the children
17454     *
17455     * @attr ref android.R.styleable#View_foreground
17456     */
17457    public void setForeground(Drawable foreground) {
17458        if (mForegroundInfo == null) {
17459            if (foreground == null) {
17460                // Nothing to do.
17461                return;
17462            }
17463            mForegroundInfo = new ForegroundInfo();
17464        }
17465
17466        if (foreground == mForegroundInfo.mDrawable) {
17467            // Nothing to do
17468            return;
17469        }
17470
17471        if (mForegroundInfo.mDrawable != null) {
17472            mForegroundInfo.mDrawable.setCallback(null);
17473            unscheduleDrawable(mForegroundInfo.mDrawable);
17474        }
17475
17476        mForegroundInfo.mDrawable = foreground;
17477        mForegroundInfo.mBoundsChanged = true;
17478        if (foreground != null) {
17479            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17480                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17481            }
17482            foreground.setCallback(this);
17483            foreground.setLayoutDirection(getLayoutDirection());
17484            if (foreground.isStateful()) {
17485                foreground.setState(getDrawableState());
17486            }
17487            applyForegroundTint();
17488        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17489            mPrivateFlags |= PFLAG_SKIP_DRAW;
17490        }
17491        requestLayout();
17492        invalidate();
17493    }
17494
17495    /**
17496     * Magic bit used to support features of framework-internal window decor implementation details.
17497     * This used to live exclusively in FrameLayout.
17498     *
17499     * @return true if the foreground should draw inside the padding region or false
17500     *         if it should draw inset by the view's padding
17501     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17502     */
17503    public boolean isForegroundInsidePadding() {
17504        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17505    }
17506
17507    /**
17508     * Describes how the foreground is positioned.
17509     *
17510     * @return foreground gravity.
17511     *
17512     * @see #setForegroundGravity(int)
17513     *
17514     * @attr ref android.R.styleable#View_foregroundGravity
17515     */
17516    public int getForegroundGravity() {
17517        return mForegroundInfo != null ? mForegroundInfo.mGravity
17518                : Gravity.START | Gravity.TOP;
17519    }
17520
17521    /**
17522     * Describes how the foreground is positioned. Defaults to START and TOP.
17523     *
17524     * @param gravity see {@link android.view.Gravity}
17525     *
17526     * @see #getForegroundGravity()
17527     *
17528     * @attr ref android.R.styleable#View_foregroundGravity
17529     */
17530    public void setForegroundGravity(int gravity) {
17531        if (mForegroundInfo == null) {
17532            mForegroundInfo = new ForegroundInfo();
17533        }
17534
17535        if (mForegroundInfo.mGravity != gravity) {
17536            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17537                gravity |= Gravity.START;
17538            }
17539
17540            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17541                gravity |= Gravity.TOP;
17542            }
17543
17544            mForegroundInfo.mGravity = gravity;
17545            requestLayout();
17546        }
17547    }
17548
17549    /**
17550     * Applies a tint to the foreground drawable. Does not modify the current tint
17551     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17552     * <p>
17553     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17554     * mutate the drawable and apply the specified tint and tint mode using
17555     * {@link Drawable#setTintList(ColorStateList)}.
17556     *
17557     * @param tint the tint to apply, may be {@code null} to clear tint
17558     *
17559     * @attr ref android.R.styleable#View_foregroundTint
17560     * @see #getForegroundTintList()
17561     * @see Drawable#setTintList(ColorStateList)
17562     */
17563    public void setForegroundTintList(@Nullable ColorStateList tint) {
17564        if (mForegroundInfo == null) {
17565            mForegroundInfo = new ForegroundInfo();
17566        }
17567        if (mForegroundInfo.mTintInfo == null) {
17568            mForegroundInfo.mTintInfo = new TintInfo();
17569        }
17570        mForegroundInfo.mTintInfo.mTintList = tint;
17571        mForegroundInfo.mTintInfo.mHasTintList = true;
17572
17573        applyForegroundTint();
17574    }
17575
17576    /**
17577     * Return the tint applied to the foreground drawable, if specified.
17578     *
17579     * @return the tint applied to the foreground drawable
17580     * @attr ref android.R.styleable#View_foregroundTint
17581     * @see #setForegroundTintList(ColorStateList)
17582     */
17583    @Nullable
17584    public ColorStateList getForegroundTintList() {
17585        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17586                ? mForegroundInfo.mTintInfo.mTintList : null;
17587    }
17588
17589    /**
17590     * Specifies the blending mode used to apply the tint specified by
17591     * {@link #setForegroundTintList(ColorStateList)}} to the background
17592     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17593     *
17594     * @param tintMode the blending mode used to apply the tint, may be
17595     *                 {@code null} to clear tint
17596     * @attr ref android.R.styleable#View_foregroundTintMode
17597     * @see #getForegroundTintMode()
17598     * @see Drawable#setTintMode(PorterDuff.Mode)
17599     */
17600    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17601        if (mForegroundInfo == null) {
17602            mForegroundInfo = new ForegroundInfo();
17603        }
17604        if (mForegroundInfo.mTintInfo == null) {
17605            mForegroundInfo.mTintInfo = new TintInfo();
17606        }
17607        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17608        mForegroundInfo.mTintInfo.mHasTintMode = true;
17609
17610        applyForegroundTint();
17611    }
17612
17613    /**
17614     * Return the blending mode used to apply the tint to the foreground
17615     * drawable, if specified.
17616     *
17617     * @return the blending mode used to apply the tint to the foreground
17618     *         drawable
17619     * @attr ref android.R.styleable#View_foregroundTintMode
17620     * @see #setForegroundTintMode(PorterDuff.Mode)
17621     */
17622    @Nullable
17623    public PorterDuff.Mode getForegroundTintMode() {
17624        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17625                ? mForegroundInfo.mTintInfo.mTintMode : null;
17626    }
17627
17628    private void applyForegroundTint() {
17629        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17630                && mForegroundInfo.mTintInfo != null) {
17631            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17632            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17633                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17634
17635                if (tintInfo.mHasTintList) {
17636                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17637                }
17638
17639                if (tintInfo.mHasTintMode) {
17640                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17641                }
17642
17643                // The drawable (or one of its children) may not have been
17644                // stateful before applying the tint, so let's try again.
17645                if (mForegroundInfo.mDrawable.isStateful()) {
17646                    mForegroundInfo.mDrawable.setState(getDrawableState());
17647                }
17648            }
17649        }
17650    }
17651
17652    /**
17653     * Draw any foreground content for this view.
17654     *
17655     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17656     * drawable or other view-specific decorations. The foreground is drawn on top of the
17657     * primary view content.</p>
17658     *
17659     * @param canvas canvas to draw into
17660     */
17661    public void onDrawForeground(Canvas canvas) {
17662        onDrawScrollIndicators(canvas);
17663        onDrawScrollBars(canvas);
17664
17665        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17666        if (foreground != null) {
17667            if (mForegroundInfo.mBoundsChanged) {
17668                mForegroundInfo.mBoundsChanged = false;
17669                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17670                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17671
17672                if (mForegroundInfo.mInsidePadding) {
17673                    selfBounds.set(0, 0, getWidth(), getHeight());
17674                } else {
17675                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17676                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17677                }
17678
17679                final int ld = getLayoutDirection();
17680                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17681                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17682                foreground.setBounds(overlayBounds);
17683            }
17684
17685            foreground.draw(canvas);
17686        }
17687    }
17688
17689    /**
17690     * Sets the padding. The view may add on the space required to display
17691     * the scrollbars, depending on the style and visibility of the scrollbars.
17692     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17693     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17694     * from the values set in this call.
17695     *
17696     * @attr ref android.R.styleable#View_padding
17697     * @attr ref android.R.styleable#View_paddingBottom
17698     * @attr ref android.R.styleable#View_paddingLeft
17699     * @attr ref android.R.styleable#View_paddingRight
17700     * @attr ref android.R.styleable#View_paddingTop
17701     * @param left the left padding in pixels
17702     * @param top the top padding in pixels
17703     * @param right the right padding in pixels
17704     * @param bottom the bottom padding in pixels
17705     */
17706    public void setPadding(int left, int top, int right, int bottom) {
17707        resetResolvedPaddingInternal();
17708
17709        mUserPaddingStart = UNDEFINED_PADDING;
17710        mUserPaddingEnd = UNDEFINED_PADDING;
17711
17712        mUserPaddingLeftInitial = left;
17713        mUserPaddingRightInitial = right;
17714
17715        mLeftPaddingDefined = true;
17716        mRightPaddingDefined = true;
17717
17718        internalSetPadding(left, top, right, bottom);
17719    }
17720
17721    /**
17722     * @hide
17723     */
17724    protected void internalSetPadding(int left, int top, int right, int bottom) {
17725        mUserPaddingLeft = left;
17726        mUserPaddingRight = right;
17727        mUserPaddingBottom = bottom;
17728
17729        final int viewFlags = mViewFlags;
17730        boolean changed = false;
17731
17732        // Common case is there are no scroll bars.
17733        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
17734            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
17735                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
17736                        ? 0 : getVerticalScrollbarWidth();
17737                switch (mVerticalScrollbarPosition) {
17738                    case SCROLLBAR_POSITION_DEFAULT:
17739                        if (isLayoutRtl()) {
17740                            left += offset;
17741                        } else {
17742                            right += offset;
17743                        }
17744                        break;
17745                    case SCROLLBAR_POSITION_RIGHT:
17746                        right += offset;
17747                        break;
17748                    case SCROLLBAR_POSITION_LEFT:
17749                        left += offset;
17750                        break;
17751                }
17752            }
17753            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
17754                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
17755                        ? 0 : getHorizontalScrollbarHeight();
17756            }
17757        }
17758
17759        if (mPaddingLeft != left) {
17760            changed = true;
17761            mPaddingLeft = left;
17762        }
17763        if (mPaddingTop != top) {
17764            changed = true;
17765            mPaddingTop = top;
17766        }
17767        if (mPaddingRight != right) {
17768            changed = true;
17769            mPaddingRight = right;
17770        }
17771        if (mPaddingBottom != bottom) {
17772            changed = true;
17773            mPaddingBottom = bottom;
17774        }
17775
17776        if (changed) {
17777            requestLayout();
17778            invalidateOutline();
17779        }
17780    }
17781
17782    /**
17783     * Sets the relative padding. The view may add on the space required to display
17784     * the scrollbars, depending on the style and visibility of the scrollbars.
17785     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
17786     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
17787     * from the values set in this call.
17788     *
17789     * @attr ref android.R.styleable#View_padding
17790     * @attr ref android.R.styleable#View_paddingBottom
17791     * @attr ref android.R.styleable#View_paddingStart
17792     * @attr ref android.R.styleable#View_paddingEnd
17793     * @attr ref android.R.styleable#View_paddingTop
17794     * @param start the start padding in pixels
17795     * @param top the top padding in pixels
17796     * @param end the end padding in pixels
17797     * @param bottom the bottom padding in pixels
17798     */
17799    public void setPaddingRelative(int start, int top, int end, int bottom) {
17800        resetResolvedPaddingInternal();
17801
17802        mUserPaddingStart = start;
17803        mUserPaddingEnd = end;
17804        mLeftPaddingDefined = true;
17805        mRightPaddingDefined = true;
17806
17807        switch(getLayoutDirection()) {
17808            case LAYOUT_DIRECTION_RTL:
17809                mUserPaddingLeftInitial = end;
17810                mUserPaddingRightInitial = start;
17811                internalSetPadding(end, top, start, bottom);
17812                break;
17813            case LAYOUT_DIRECTION_LTR:
17814            default:
17815                mUserPaddingLeftInitial = start;
17816                mUserPaddingRightInitial = end;
17817                internalSetPadding(start, top, end, bottom);
17818        }
17819    }
17820
17821    /**
17822     * Returns the top padding of this view.
17823     *
17824     * @return the top padding in pixels
17825     */
17826    public int getPaddingTop() {
17827        return mPaddingTop;
17828    }
17829
17830    /**
17831     * Returns the bottom padding of this view. If there are inset and enabled
17832     * scrollbars, this value may include the space required to display the
17833     * scrollbars as well.
17834     *
17835     * @return the bottom padding in pixels
17836     */
17837    public int getPaddingBottom() {
17838        return mPaddingBottom;
17839    }
17840
17841    /**
17842     * Returns the left padding of this view. If there are inset and enabled
17843     * scrollbars, this value may include the space required to display the
17844     * scrollbars as well.
17845     *
17846     * @return the left padding in pixels
17847     */
17848    public int getPaddingLeft() {
17849        if (!isPaddingResolved()) {
17850            resolvePadding();
17851        }
17852        return mPaddingLeft;
17853    }
17854
17855    /**
17856     * Returns the start padding of this view depending on its resolved layout direction.
17857     * If there are inset and enabled scrollbars, this value may include the space
17858     * required to display the scrollbars as well.
17859     *
17860     * @return the start padding in pixels
17861     */
17862    public int getPaddingStart() {
17863        if (!isPaddingResolved()) {
17864            resolvePadding();
17865        }
17866        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17867                mPaddingRight : mPaddingLeft;
17868    }
17869
17870    /**
17871     * Returns the right padding of this view. If there are inset and enabled
17872     * scrollbars, this value may include the space required to display the
17873     * scrollbars as well.
17874     *
17875     * @return the right padding in pixels
17876     */
17877    public int getPaddingRight() {
17878        if (!isPaddingResolved()) {
17879            resolvePadding();
17880        }
17881        return mPaddingRight;
17882    }
17883
17884    /**
17885     * Returns the end padding of this view depending on its resolved layout direction.
17886     * If there are inset and enabled scrollbars, this value may include the space
17887     * required to display the scrollbars as well.
17888     *
17889     * @return the end padding in pixels
17890     */
17891    public int getPaddingEnd() {
17892        if (!isPaddingResolved()) {
17893            resolvePadding();
17894        }
17895        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
17896                mPaddingLeft : mPaddingRight;
17897    }
17898
17899    /**
17900     * Return if the padding has been set through relative values
17901     * {@link #setPaddingRelative(int, int, int, int)} or through
17902     * @attr ref android.R.styleable#View_paddingStart or
17903     * @attr ref android.R.styleable#View_paddingEnd
17904     *
17905     * @return true if the padding is relative or false if it is not.
17906     */
17907    public boolean isPaddingRelative() {
17908        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
17909    }
17910
17911    Insets computeOpticalInsets() {
17912        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
17913    }
17914
17915    /**
17916     * @hide
17917     */
17918    public void resetPaddingToInitialValues() {
17919        if (isRtlCompatibilityMode()) {
17920            mPaddingLeft = mUserPaddingLeftInitial;
17921            mPaddingRight = mUserPaddingRightInitial;
17922            return;
17923        }
17924        if (isLayoutRtl()) {
17925            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
17926            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
17927        } else {
17928            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
17929            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
17930        }
17931    }
17932
17933    /**
17934     * @hide
17935     */
17936    public Insets getOpticalInsets() {
17937        if (mLayoutInsets == null) {
17938            mLayoutInsets = computeOpticalInsets();
17939        }
17940        return mLayoutInsets;
17941    }
17942
17943    /**
17944     * Set this view's optical insets.
17945     *
17946     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
17947     * property. Views that compute their own optical insets should call it as part of measurement.
17948     * This method does not request layout. If you are setting optical insets outside of
17949     * measure/layout itself you will want to call requestLayout() yourself.
17950     * </p>
17951     * @hide
17952     */
17953    public void setOpticalInsets(Insets insets) {
17954        mLayoutInsets = insets;
17955    }
17956
17957    /**
17958     * Changes the selection state of this view. A view can be selected or not.
17959     * Note that selection is not the same as focus. Views are typically
17960     * selected in the context of an AdapterView like ListView or GridView;
17961     * the selected view is the view that is highlighted.
17962     *
17963     * @param selected true if the view must be selected, false otherwise
17964     */
17965    public void setSelected(boolean selected) {
17966        //noinspection DoubleNegation
17967        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
17968            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
17969            if (!selected) resetPressedState();
17970            invalidate(true);
17971            refreshDrawableState();
17972            dispatchSetSelected(selected);
17973            if (selected) {
17974                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
17975            } else {
17976                notifyViewAccessibilityStateChangedIfNeeded(
17977                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
17978            }
17979        }
17980    }
17981
17982    /**
17983     * Dispatch setSelected to all of this View's children.
17984     *
17985     * @see #setSelected(boolean)
17986     *
17987     * @param selected The new selected state
17988     */
17989    protected void dispatchSetSelected(boolean selected) {
17990    }
17991
17992    /**
17993     * Indicates the selection state of this view.
17994     *
17995     * @return true if the view is selected, false otherwise
17996     */
17997    @ViewDebug.ExportedProperty
17998    public boolean isSelected() {
17999        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18000    }
18001
18002    /**
18003     * Changes the activated state of this view. A view can be activated or not.
18004     * Note that activation is not the same as selection.  Selection is
18005     * a transient property, representing the view (hierarchy) the user is
18006     * currently interacting with.  Activation is a longer-term state that the
18007     * user can move views in and out of.  For example, in a list view with
18008     * single or multiple selection enabled, the views in the current selection
18009     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18010     * here.)  The activated state is propagated down to children of the view it
18011     * is set on.
18012     *
18013     * @param activated true if the view must be activated, false otherwise
18014     */
18015    public void setActivated(boolean activated) {
18016        //noinspection DoubleNegation
18017        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18018            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18019            invalidate(true);
18020            refreshDrawableState();
18021            dispatchSetActivated(activated);
18022        }
18023    }
18024
18025    /**
18026     * Dispatch setActivated to all of this View's children.
18027     *
18028     * @see #setActivated(boolean)
18029     *
18030     * @param activated The new activated state
18031     */
18032    protected void dispatchSetActivated(boolean activated) {
18033    }
18034
18035    /**
18036     * Indicates the activation state of this view.
18037     *
18038     * @return true if the view is activated, false otherwise
18039     */
18040    @ViewDebug.ExportedProperty
18041    public boolean isActivated() {
18042        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18043    }
18044
18045    /**
18046     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18047     * observer can be used to get notifications when global events, like
18048     * layout, happen.
18049     *
18050     * The returned ViewTreeObserver observer is not guaranteed to remain
18051     * valid for the lifetime of this View. If the caller of this method keeps
18052     * a long-lived reference to ViewTreeObserver, it should always check for
18053     * the return value of {@link ViewTreeObserver#isAlive()}.
18054     *
18055     * @return The ViewTreeObserver for this view's hierarchy.
18056     */
18057    public ViewTreeObserver getViewTreeObserver() {
18058        if (mAttachInfo != null) {
18059            return mAttachInfo.mTreeObserver;
18060        }
18061        if (mFloatingTreeObserver == null) {
18062            mFloatingTreeObserver = new ViewTreeObserver();
18063        }
18064        return mFloatingTreeObserver;
18065    }
18066
18067    /**
18068     * <p>Finds the topmost view in the current view hierarchy.</p>
18069     *
18070     * @return the topmost view containing this view
18071     */
18072    public View getRootView() {
18073        if (mAttachInfo != null) {
18074            final View v = mAttachInfo.mRootView;
18075            if (v != null) {
18076                return v;
18077            }
18078        }
18079
18080        View parent = this;
18081
18082        while (parent.mParent != null && parent.mParent instanceof View) {
18083            parent = (View) parent.mParent;
18084        }
18085
18086        return parent;
18087    }
18088
18089    /**
18090     * Transforms a motion event from view-local coordinates to on-screen
18091     * coordinates.
18092     *
18093     * @param ev the view-local motion event
18094     * @return false if the transformation could not be applied
18095     * @hide
18096     */
18097    public boolean toGlobalMotionEvent(MotionEvent ev) {
18098        final AttachInfo info = mAttachInfo;
18099        if (info == null) {
18100            return false;
18101        }
18102
18103        final Matrix m = info.mTmpMatrix;
18104        m.set(Matrix.IDENTITY_MATRIX);
18105        transformMatrixToGlobal(m);
18106        ev.transform(m);
18107        return true;
18108    }
18109
18110    /**
18111     * Transforms a motion event from on-screen coordinates to view-local
18112     * coordinates.
18113     *
18114     * @param ev the on-screen motion event
18115     * @return false if the transformation could not be applied
18116     * @hide
18117     */
18118    public boolean toLocalMotionEvent(MotionEvent ev) {
18119        final AttachInfo info = mAttachInfo;
18120        if (info == null) {
18121            return false;
18122        }
18123
18124        final Matrix m = info.mTmpMatrix;
18125        m.set(Matrix.IDENTITY_MATRIX);
18126        transformMatrixToLocal(m);
18127        ev.transform(m);
18128        return true;
18129    }
18130
18131    /**
18132     * Modifies the input matrix such that it maps view-local coordinates to
18133     * on-screen coordinates.
18134     *
18135     * @param m input matrix to modify
18136     * @hide
18137     */
18138    public void transformMatrixToGlobal(Matrix m) {
18139        final ViewParent parent = mParent;
18140        if (parent instanceof View) {
18141            final View vp = (View) parent;
18142            vp.transformMatrixToGlobal(m);
18143            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18144        } else if (parent instanceof ViewRootImpl) {
18145            final ViewRootImpl vr = (ViewRootImpl) parent;
18146            vr.transformMatrixToGlobal(m);
18147            m.preTranslate(0, -vr.mCurScrollY);
18148        }
18149
18150        m.preTranslate(mLeft, mTop);
18151
18152        if (!hasIdentityMatrix()) {
18153            m.preConcat(getMatrix());
18154        }
18155    }
18156
18157    /**
18158     * Modifies the input matrix such that it maps on-screen coordinates to
18159     * view-local coordinates.
18160     *
18161     * @param m input matrix to modify
18162     * @hide
18163     */
18164    public void transformMatrixToLocal(Matrix m) {
18165        final ViewParent parent = mParent;
18166        if (parent instanceof View) {
18167            final View vp = (View) parent;
18168            vp.transformMatrixToLocal(m);
18169            m.postTranslate(vp.mScrollX, vp.mScrollY);
18170        } else if (parent instanceof ViewRootImpl) {
18171            final ViewRootImpl vr = (ViewRootImpl) parent;
18172            vr.transformMatrixToLocal(m);
18173            m.postTranslate(0, vr.mCurScrollY);
18174        }
18175
18176        m.postTranslate(-mLeft, -mTop);
18177
18178        if (!hasIdentityMatrix()) {
18179            m.postConcat(getInverseMatrix());
18180        }
18181    }
18182
18183    /**
18184     * @hide
18185     */
18186    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18187            @ViewDebug.IntToString(from = 0, to = "x"),
18188            @ViewDebug.IntToString(from = 1, to = "y")
18189    })
18190    public int[] getLocationOnScreen() {
18191        int[] location = new int[2];
18192        getLocationOnScreen(location);
18193        return location;
18194    }
18195
18196    /**
18197     * <p>Computes the coordinates of this view on the screen. The argument
18198     * must be an array of two integers. After the method returns, the array
18199     * contains the x and y location in that order.</p>
18200     *
18201     * @param location an array of two integers in which to hold the coordinates
18202     */
18203    public void getLocationOnScreen(@Size(2) int[] location) {
18204        getLocationInWindow(location);
18205
18206        final AttachInfo info = mAttachInfo;
18207        if (info != null) {
18208            location[0] += info.mWindowLeft;
18209            location[1] += info.mWindowTop;
18210        }
18211    }
18212
18213    /**
18214     * <p>Computes the coordinates of this view in its window. The argument
18215     * must be an array of two integers. After the method returns, the array
18216     * contains the x and y location in that order.</p>
18217     *
18218     * @param location an array of two integers in which to hold the coordinates
18219     */
18220    public void getLocationInWindow(@Size(2) int[] location) {
18221        if (location == null || location.length < 2) {
18222            throw new IllegalArgumentException("location must be an array of two integers");
18223        }
18224
18225        if (mAttachInfo == null) {
18226            // When the view is not attached to a window, this method does not make sense
18227            location[0] = location[1] = 0;
18228            return;
18229        }
18230
18231        float[] position = mAttachInfo.mTmpTransformLocation;
18232        position[0] = position[1] = 0.0f;
18233
18234        if (!hasIdentityMatrix()) {
18235            getMatrix().mapPoints(position);
18236        }
18237
18238        position[0] += mLeft;
18239        position[1] += mTop;
18240
18241        ViewParent viewParent = mParent;
18242        while (viewParent instanceof View) {
18243            final View view = (View) viewParent;
18244
18245            position[0] -= view.mScrollX;
18246            position[1] -= view.mScrollY;
18247
18248            if (!view.hasIdentityMatrix()) {
18249                view.getMatrix().mapPoints(position);
18250            }
18251
18252            position[0] += view.mLeft;
18253            position[1] += view.mTop;
18254
18255            viewParent = view.mParent;
18256         }
18257
18258        if (viewParent instanceof ViewRootImpl) {
18259            // *cough*
18260            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18261            position[1] -= vr.mCurScrollY;
18262        }
18263
18264        location[0] = (int) (position[0] + 0.5f);
18265        location[1] = (int) (position[1] + 0.5f);
18266    }
18267
18268    /**
18269     * {@hide}
18270     * @param id the id of the view to be found
18271     * @return the view of the specified id, null if cannot be found
18272     */
18273    protected View findViewTraversal(@IdRes int id) {
18274        if (id == mID) {
18275            return this;
18276        }
18277        return null;
18278    }
18279
18280    /**
18281     * {@hide}
18282     * @param tag the tag of the view to be found
18283     * @return the view of specified tag, null if cannot be found
18284     */
18285    protected View findViewWithTagTraversal(Object tag) {
18286        if (tag != null && tag.equals(mTag)) {
18287            return this;
18288        }
18289        return null;
18290    }
18291
18292    /**
18293     * {@hide}
18294     * @param predicate The predicate to evaluate.
18295     * @param childToSkip If not null, ignores this child during the recursive traversal.
18296     * @return The first view that matches the predicate or null.
18297     */
18298    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18299        if (predicate.apply(this)) {
18300            return this;
18301        }
18302        return null;
18303    }
18304
18305    /**
18306     * Look for a child view with the given id.  If this view has the given
18307     * id, return this view.
18308     *
18309     * @param id The id to search for.
18310     * @return The view that has the given id in the hierarchy or null
18311     */
18312    @Nullable
18313    public final View findViewById(@IdRes int id) {
18314        if (id < 0) {
18315            return null;
18316        }
18317        return findViewTraversal(id);
18318    }
18319
18320    /**
18321     * Finds a view by its unuque and stable accessibility id.
18322     *
18323     * @param accessibilityId The searched accessibility id.
18324     * @return The found view.
18325     */
18326    final View findViewByAccessibilityId(int accessibilityId) {
18327        if (accessibilityId < 0) {
18328            return null;
18329        }
18330        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18331        if (view != null) {
18332            return view.includeForAccessibility() ? view : null;
18333        }
18334        return null;
18335    }
18336
18337    /**
18338     * Performs the traversal to find a view by its unuque and stable accessibility id.
18339     *
18340     * <strong>Note:</strong>This method does not stop at the root namespace
18341     * boundary since the user can touch the screen at an arbitrary location
18342     * potentially crossing the root namespace bounday which will send an
18343     * accessibility event to accessibility services and they should be able
18344     * to obtain the event source. Also accessibility ids are guaranteed to be
18345     * unique in the window.
18346     *
18347     * @param accessibilityId The accessibility id.
18348     * @return The found view.
18349     *
18350     * @hide
18351     */
18352    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18353        if (getAccessibilityViewId() == accessibilityId) {
18354            return this;
18355        }
18356        return null;
18357    }
18358
18359    /**
18360     * Look for a child view with the given tag.  If this view has the given
18361     * tag, return this view.
18362     *
18363     * @param tag The tag to search for, using "tag.equals(getTag())".
18364     * @return The View that has the given tag in the hierarchy or null
18365     */
18366    public final View findViewWithTag(Object tag) {
18367        if (tag == null) {
18368            return null;
18369        }
18370        return findViewWithTagTraversal(tag);
18371    }
18372
18373    /**
18374     * {@hide}
18375     * Look for a child view that matches the specified predicate.
18376     * If this view matches the predicate, return this view.
18377     *
18378     * @param predicate The predicate to evaluate.
18379     * @return The first view that matches the predicate or null.
18380     */
18381    public final View findViewByPredicate(Predicate<View> predicate) {
18382        return findViewByPredicateTraversal(predicate, null);
18383    }
18384
18385    /**
18386     * {@hide}
18387     * Look for a child view that matches the specified predicate,
18388     * starting with the specified view and its descendents and then
18389     * recusively searching the ancestors and siblings of that view
18390     * until this view is reached.
18391     *
18392     * This method is useful in cases where the predicate does not match
18393     * a single unique view (perhaps multiple views use the same id)
18394     * and we are trying to find the view that is "closest" in scope to the
18395     * starting view.
18396     *
18397     * @param start The view to start from.
18398     * @param predicate The predicate to evaluate.
18399     * @return The first view that matches the predicate or null.
18400     */
18401    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18402        View childToSkip = null;
18403        for (;;) {
18404            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18405            if (view != null || start == this) {
18406                return view;
18407            }
18408
18409            ViewParent parent = start.getParent();
18410            if (parent == null || !(parent instanceof View)) {
18411                return null;
18412            }
18413
18414            childToSkip = start;
18415            start = (View) parent;
18416        }
18417    }
18418
18419    /**
18420     * Sets the identifier for this view. The identifier does not have to be
18421     * unique in this view's hierarchy. The identifier should be a positive
18422     * number.
18423     *
18424     * @see #NO_ID
18425     * @see #getId()
18426     * @see #findViewById(int)
18427     *
18428     * @param id a number used to identify the view
18429     *
18430     * @attr ref android.R.styleable#View_id
18431     */
18432    public void setId(@IdRes int id) {
18433        mID = id;
18434        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18435            mID = generateViewId();
18436        }
18437    }
18438
18439    /**
18440     * {@hide}
18441     *
18442     * @param isRoot true if the view belongs to the root namespace, false
18443     *        otherwise
18444     */
18445    public void setIsRootNamespace(boolean isRoot) {
18446        if (isRoot) {
18447            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18448        } else {
18449            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18450        }
18451    }
18452
18453    /**
18454     * {@hide}
18455     *
18456     * @return true if the view belongs to the root namespace, false otherwise
18457     */
18458    public boolean isRootNamespace() {
18459        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18460    }
18461
18462    /**
18463     * Returns this view's identifier.
18464     *
18465     * @return a positive integer used to identify the view or {@link #NO_ID}
18466     *         if the view has no ID
18467     *
18468     * @see #setId(int)
18469     * @see #findViewById(int)
18470     * @attr ref android.R.styleable#View_id
18471     */
18472    @IdRes
18473    @ViewDebug.CapturedViewProperty
18474    public int getId() {
18475        return mID;
18476    }
18477
18478    /**
18479     * Returns this view's tag.
18480     *
18481     * @return the Object stored in this view as a tag, or {@code null} if not
18482     *         set
18483     *
18484     * @see #setTag(Object)
18485     * @see #getTag(int)
18486     */
18487    @ViewDebug.ExportedProperty
18488    public Object getTag() {
18489        return mTag;
18490    }
18491
18492    /**
18493     * Sets the tag associated with this view. A tag can be used to mark
18494     * a view in its hierarchy and does not have to be unique within the
18495     * hierarchy. Tags can also be used to store data within a view without
18496     * resorting to another data structure.
18497     *
18498     * @param tag an Object to tag the view with
18499     *
18500     * @see #getTag()
18501     * @see #setTag(int, Object)
18502     */
18503    public void setTag(final Object tag) {
18504        mTag = tag;
18505    }
18506
18507    /**
18508     * Returns the tag associated with this view and the specified key.
18509     *
18510     * @param key The key identifying the tag
18511     *
18512     * @return the Object stored in this view as a tag, or {@code null} if not
18513     *         set
18514     *
18515     * @see #setTag(int, Object)
18516     * @see #getTag()
18517     */
18518    public Object getTag(int key) {
18519        if (mKeyedTags != null) return mKeyedTags.get(key);
18520        return null;
18521    }
18522
18523    /**
18524     * Sets a tag associated with this view and a key. A tag can be used
18525     * to mark a view in its hierarchy and does not have to be unique within
18526     * the hierarchy. Tags can also be used to store data within a view
18527     * without resorting to another data structure.
18528     *
18529     * The specified key should be an id declared in the resources of the
18530     * application to ensure it is unique (see the <a
18531     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18532     * Keys identified as belonging to
18533     * the Android framework or not associated with any package will cause
18534     * an {@link IllegalArgumentException} to be thrown.
18535     *
18536     * @param key The key identifying the tag
18537     * @param tag An Object to tag the view with
18538     *
18539     * @throws IllegalArgumentException If they specified key is not valid
18540     *
18541     * @see #setTag(Object)
18542     * @see #getTag(int)
18543     */
18544    public void setTag(int key, final Object tag) {
18545        // If the package id is 0x00 or 0x01, it's either an undefined package
18546        // or a framework id
18547        if ((key >>> 24) < 2) {
18548            throw new IllegalArgumentException("The key must be an application-specific "
18549                    + "resource id.");
18550        }
18551
18552        setKeyedTag(key, tag);
18553    }
18554
18555    /**
18556     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18557     * framework id.
18558     *
18559     * @hide
18560     */
18561    public void setTagInternal(int key, Object tag) {
18562        if ((key >>> 24) != 0x1) {
18563            throw new IllegalArgumentException("The key must be a framework-specific "
18564                    + "resource id.");
18565        }
18566
18567        setKeyedTag(key, tag);
18568    }
18569
18570    private void setKeyedTag(int key, Object tag) {
18571        if (mKeyedTags == null) {
18572            mKeyedTags = new SparseArray<Object>(2);
18573        }
18574
18575        mKeyedTags.put(key, tag);
18576    }
18577
18578    /**
18579     * Prints information about this view in the log output, with the tag
18580     * {@link #VIEW_LOG_TAG}.
18581     *
18582     * @hide
18583     */
18584    public void debug() {
18585        debug(0);
18586    }
18587
18588    /**
18589     * Prints information about this view in the log output, with the tag
18590     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18591     * indentation defined by the <code>depth</code>.
18592     *
18593     * @param depth the indentation level
18594     *
18595     * @hide
18596     */
18597    protected void debug(int depth) {
18598        String output = debugIndent(depth - 1);
18599
18600        output += "+ " + this;
18601        int id = getId();
18602        if (id != -1) {
18603            output += " (id=" + id + ")";
18604        }
18605        Object tag = getTag();
18606        if (tag != null) {
18607            output += " (tag=" + tag + ")";
18608        }
18609        Log.d(VIEW_LOG_TAG, output);
18610
18611        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18612            output = debugIndent(depth) + " FOCUSED";
18613            Log.d(VIEW_LOG_TAG, output);
18614        }
18615
18616        output = debugIndent(depth);
18617        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18618                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18619                + "} ";
18620        Log.d(VIEW_LOG_TAG, output);
18621
18622        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18623                || mPaddingBottom != 0) {
18624            output = debugIndent(depth);
18625            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18626                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18627            Log.d(VIEW_LOG_TAG, output);
18628        }
18629
18630        output = debugIndent(depth);
18631        output += "mMeasureWidth=" + mMeasuredWidth +
18632                " mMeasureHeight=" + mMeasuredHeight;
18633        Log.d(VIEW_LOG_TAG, output);
18634
18635        output = debugIndent(depth);
18636        if (mLayoutParams == null) {
18637            output += "BAD! no layout params";
18638        } else {
18639            output = mLayoutParams.debug(output);
18640        }
18641        Log.d(VIEW_LOG_TAG, output);
18642
18643        output = debugIndent(depth);
18644        output += "flags={";
18645        output += View.printFlags(mViewFlags);
18646        output += "}";
18647        Log.d(VIEW_LOG_TAG, output);
18648
18649        output = debugIndent(depth);
18650        output += "privateFlags={";
18651        output += View.printPrivateFlags(mPrivateFlags);
18652        output += "}";
18653        Log.d(VIEW_LOG_TAG, output);
18654    }
18655
18656    /**
18657     * Creates a string of whitespaces used for indentation.
18658     *
18659     * @param depth the indentation level
18660     * @return a String containing (depth * 2 + 3) * 2 white spaces
18661     *
18662     * @hide
18663     */
18664    protected static String debugIndent(int depth) {
18665        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18666        for (int i = 0; i < (depth * 2) + 3; i++) {
18667            spaces.append(' ').append(' ');
18668        }
18669        return spaces.toString();
18670    }
18671
18672    /**
18673     * <p>Return the offset of the widget's text baseline from the widget's top
18674     * boundary. If this widget does not support baseline alignment, this
18675     * method returns -1. </p>
18676     *
18677     * @return the offset of the baseline within the widget's bounds or -1
18678     *         if baseline alignment is not supported
18679     */
18680    @ViewDebug.ExportedProperty(category = "layout")
18681    public int getBaseline() {
18682        return -1;
18683    }
18684
18685    /**
18686     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18687     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18688     * a layout pass.
18689     *
18690     * @return whether the view hierarchy is currently undergoing a layout pass
18691     */
18692    public boolean isInLayout() {
18693        ViewRootImpl viewRoot = getViewRootImpl();
18694        return (viewRoot != null && viewRoot.isInLayout());
18695    }
18696
18697    /**
18698     * Call this when something has changed which has invalidated the
18699     * layout of this view. This will schedule a layout pass of the view
18700     * tree. This should not be called while the view hierarchy is currently in a layout
18701     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18702     * end of the current layout pass (and then layout will run again) or after the current
18703     * frame is drawn and the next layout occurs.
18704     *
18705     * <p>Subclasses which override this method should call the superclass method to
18706     * handle possible request-during-layout errors correctly.</p>
18707     */
18708    @CallSuper
18709    public void requestLayout() {
18710        if (mMeasureCache != null) mMeasureCache.clear();
18711
18712        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
18713            // Only trigger request-during-layout logic if this is the view requesting it,
18714            // not the views in its parent hierarchy
18715            ViewRootImpl viewRoot = getViewRootImpl();
18716            if (viewRoot != null && viewRoot.isInLayout()) {
18717                if (!viewRoot.requestLayoutDuringLayout(this)) {
18718                    return;
18719                }
18720            }
18721            mAttachInfo.mViewRequestingLayout = this;
18722        }
18723
18724        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18725        mPrivateFlags |= PFLAG_INVALIDATED;
18726
18727        if (mParent != null && !mParent.isLayoutRequested()) {
18728            mParent.requestLayout();
18729        }
18730        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
18731            mAttachInfo.mViewRequestingLayout = null;
18732        }
18733    }
18734
18735    /**
18736     * Forces this view to be laid out during the next layout pass.
18737     * This method does not call requestLayout() or forceLayout()
18738     * on the parent.
18739     */
18740    public void forceLayout() {
18741        if (mMeasureCache != null) mMeasureCache.clear();
18742
18743        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
18744        mPrivateFlags |= PFLAG_INVALIDATED;
18745    }
18746
18747    /**
18748     * <p>
18749     * This is called to find out how big a view should be. The parent
18750     * supplies constraint information in the width and height parameters.
18751     * </p>
18752     *
18753     * <p>
18754     * The actual measurement work of a view is performed in
18755     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
18756     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
18757     * </p>
18758     *
18759     *
18760     * @param widthMeasureSpec Horizontal space requirements as imposed by the
18761     *        parent
18762     * @param heightMeasureSpec Vertical space requirements as imposed by the
18763     *        parent
18764     *
18765     * @see #onMeasure(int, int)
18766     */
18767    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
18768        boolean optical = isLayoutModeOptical(this);
18769        if (optical != isLayoutModeOptical(mParent)) {
18770            Insets insets = getOpticalInsets();
18771            int oWidth  = insets.left + insets.right;
18772            int oHeight = insets.top  + insets.bottom;
18773            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
18774            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
18775        }
18776
18777        // Suppress sign extension for the low bytes
18778        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
18779        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
18780
18781        if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
18782                widthMeasureSpec != mOldWidthMeasureSpec ||
18783                heightMeasureSpec != mOldHeightMeasureSpec) {
18784
18785            // first clears the measured dimension flag
18786            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
18787
18788            resolveRtlPropertiesIfNeeded();
18789
18790            int cacheIndex = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ? -1 :
18791                    mMeasureCache.indexOfKey(key);
18792            if (cacheIndex < 0 || sIgnoreMeasureCache) {
18793                // measure ourselves, this should set the measured dimension flag back
18794                onMeasure(widthMeasureSpec, heightMeasureSpec);
18795                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18796            } else {
18797                long value = mMeasureCache.valueAt(cacheIndex);
18798                // Casting a long to int drops the high 32 bits, no mask needed
18799                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
18800                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
18801            }
18802
18803            // flag not set, setMeasuredDimension() was not invoked, we raise
18804            // an exception to warn the developer
18805            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
18806                throw new IllegalStateException("View with id " + getId() + ": "
18807                        + getClass().getName() + "#onMeasure() did not set the"
18808                        + " measured dimension by calling"
18809                        + " setMeasuredDimension()");
18810            }
18811
18812            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
18813        }
18814
18815        mOldWidthMeasureSpec = widthMeasureSpec;
18816        mOldHeightMeasureSpec = heightMeasureSpec;
18817
18818        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
18819                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
18820    }
18821
18822    /**
18823     * <p>
18824     * Measure the view and its content to determine the measured width and the
18825     * measured height. This method is invoked by {@link #measure(int, int)} and
18826     * should be overridden by subclasses to provide accurate and efficient
18827     * measurement of their contents.
18828     * </p>
18829     *
18830     * <p>
18831     * <strong>CONTRACT:</strong> When overriding this method, you
18832     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
18833     * measured width and height of this view. Failure to do so will trigger an
18834     * <code>IllegalStateException</code>, thrown by
18835     * {@link #measure(int, int)}. Calling the superclass'
18836     * {@link #onMeasure(int, int)} is a valid use.
18837     * </p>
18838     *
18839     * <p>
18840     * The base class implementation of measure defaults to the background size,
18841     * unless a larger size is allowed by the MeasureSpec. Subclasses should
18842     * override {@link #onMeasure(int, int)} to provide better measurements of
18843     * their content.
18844     * </p>
18845     *
18846     * <p>
18847     * If this method is overridden, it is the subclass's responsibility to make
18848     * sure the measured height and width are at least the view's minimum height
18849     * and width ({@link #getSuggestedMinimumHeight()} and
18850     * {@link #getSuggestedMinimumWidth()}).
18851     * </p>
18852     *
18853     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
18854     *                         The requirements are encoded with
18855     *                         {@link android.view.View.MeasureSpec}.
18856     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
18857     *                         The requirements are encoded with
18858     *                         {@link android.view.View.MeasureSpec}.
18859     *
18860     * @see #getMeasuredWidth()
18861     * @see #getMeasuredHeight()
18862     * @see #setMeasuredDimension(int, int)
18863     * @see #getSuggestedMinimumHeight()
18864     * @see #getSuggestedMinimumWidth()
18865     * @see android.view.View.MeasureSpec#getMode(int)
18866     * @see android.view.View.MeasureSpec#getSize(int)
18867     */
18868    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
18869        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
18870                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
18871    }
18872
18873    /**
18874     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
18875     * measured width and measured height. Failing to do so will trigger an
18876     * exception at measurement time.</p>
18877     *
18878     * @param measuredWidth The measured width of this view.  May be a complex
18879     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18880     * {@link #MEASURED_STATE_TOO_SMALL}.
18881     * @param measuredHeight The measured height of this view.  May be a complex
18882     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18883     * {@link #MEASURED_STATE_TOO_SMALL}.
18884     */
18885    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
18886        boolean optical = isLayoutModeOptical(this);
18887        if (optical != isLayoutModeOptical(mParent)) {
18888            Insets insets = getOpticalInsets();
18889            int opticalWidth  = insets.left + insets.right;
18890            int opticalHeight = insets.top  + insets.bottom;
18891
18892            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
18893            measuredHeight += optical ? opticalHeight : -opticalHeight;
18894        }
18895        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
18896    }
18897
18898    /**
18899     * Sets the measured dimension without extra processing for things like optical bounds.
18900     * Useful for reapplying consistent values that have already been cooked with adjustments
18901     * for optical bounds, etc. such as those from the measurement cache.
18902     *
18903     * @param measuredWidth The measured width of this view.  May be a complex
18904     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18905     * {@link #MEASURED_STATE_TOO_SMALL}.
18906     * @param measuredHeight The measured height of this view.  May be a complex
18907     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
18908     * {@link #MEASURED_STATE_TOO_SMALL}.
18909     */
18910    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
18911        mMeasuredWidth = measuredWidth;
18912        mMeasuredHeight = measuredHeight;
18913
18914        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
18915    }
18916
18917    /**
18918     * Merge two states as returned by {@link #getMeasuredState()}.
18919     * @param curState The current state as returned from a view or the result
18920     * of combining multiple views.
18921     * @param newState The new view state to combine.
18922     * @return Returns a new integer reflecting the combination of the two
18923     * states.
18924     */
18925    public static int combineMeasuredStates(int curState, int newState) {
18926        return curState | newState;
18927    }
18928
18929    /**
18930     * Version of {@link #resolveSizeAndState(int, int, int)}
18931     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
18932     */
18933    public static int resolveSize(int size, int measureSpec) {
18934        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
18935    }
18936
18937    /**
18938     * Utility to reconcile a desired size and state, with constraints imposed
18939     * by a MeasureSpec. Will take the desired size, unless a different size
18940     * is imposed by the constraints. The returned value is a compound integer,
18941     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
18942     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
18943     * resulting size is smaller than the size the view wants to be.
18944     *
18945     * @param size How big the view wants to be.
18946     * @param measureSpec Constraints imposed by the parent.
18947     * @param childMeasuredState Size information bit mask for the view's
18948     *                           children.
18949     * @return Size information bit mask as defined by
18950     *         {@link #MEASURED_SIZE_MASK} and
18951     *         {@link #MEASURED_STATE_TOO_SMALL}.
18952     */
18953    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
18954        final int specMode = MeasureSpec.getMode(measureSpec);
18955        final int specSize = MeasureSpec.getSize(measureSpec);
18956        final int result;
18957        switch (specMode) {
18958            case MeasureSpec.AT_MOST:
18959                if (specSize < size) {
18960                    result = specSize | MEASURED_STATE_TOO_SMALL;
18961                } else {
18962                    result = size;
18963                }
18964                break;
18965            case MeasureSpec.EXACTLY:
18966                result = specSize;
18967                break;
18968            case MeasureSpec.UNSPECIFIED:
18969            default:
18970                result = size;
18971        }
18972        return result | (childMeasuredState & MEASURED_STATE_MASK);
18973    }
18974
18975    /**
18976     * Utility to return a default size. Uses the supplied size if the
18977     * MeasureSpec imposed no constraints. Will get larger if allowed
18978     * by the MeasureSpec.
18979     *
18980     * @param size Default size for this view
18981     * @param measureSpec Constraints imposed by the parent
18982     * @return The size this view should be.
18983     */
18984    public static int getDefaultSize(int size, int measureSpec) {
18985        int result = size;
18986        int specMode = MeasureSpec.getMode(measureSpec);
18987        int specSize = MeasureSpec.getSize(measureSpec);
18988
18989        switch (specMode) {
18990        case MeasureSpec.UNSPECIFIED:
18991            result = size;
18992            break;
18993        case MeasureSpec.AT_MOST:
18994        case MeasureSpec.EXACTLY:
18995            result = specSize;
18996            break;
18997        }
18998        return result;
18999    }
19000
19001    /**
19002     * Returns the suggested minimum height that the view should use. This
19003     * returns the maximum of the view's minimum height
19004     * and the background's minimum height
19005     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19006     * <p>
19007     * When being used in {@link #onMeasure(int, int)}, the caller should still
19008     * ensure the returned height is within the requirements of the parent.
19009     *
19010     * @return The suggested minimum height of the view.
19011     */
19012    protected int getSuggestedMinimumHeight() {
19013        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19014
19015    }
19016
19017    /**
19018     * Returns the suggested minimum width that the view should use. This
19019     * returns the maximum of the view's minimum width
19020     * and the background's minimum width
19021     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19022     * <p>
19023     * When being used in {@link #onMeasure(int, int)}, the caller should still
19024     * ensure the returned width is within the requirements of the parent.
19025     *
19026     * @return The suggested minimum width of the view.
19027     */
19028    protected int getSuggestedMinimumWidth() {
19029        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19030    }
19031
19032    /**
19033     * Returns the minimum height of the view.
19034     *
19035     * @return the minimum height the view will try to be.
19036     *
19037     * @see #setMinimumHeight(int)
19038     *
19039     * @attr ref android.R.styleable#View_minHeight
19040     */
19041    public int getMinimumHeight() {
19042        return mMinHeight;
19043    }
19044
19045    /**
19046     * Sets the minimum height of the view. It is not guaranteed the view will
19047     * be able to achieve this minimum height (for example, if its parent layout
19048     * constrains it with less available height).
19049     *
19050     * @param minHeight The minimum height the view will try to be.
19051     *
19052     * @see #getMinimumHeight()
19053     *
19054     * @attr ref android.R.styleable#View_minHeight
19055     */
19056    public void setMinimumHeight(int minHeight) {
19057        mMinHeight = minHeight;
19058        requestLayout();
19059    }
19060
19061    /**
19062     * Returns the minimum width of the view.
19063     *
19064     * @return the minimum width the view will try to be.
19065     *
19066     * @see #setMinimumWidth(int)
19067     *
19068     * @attr ref android.R.styleable#View_minWidth
19069     */
19070    public int getMinimumWidth() {
19071        return mMinWidth;
19072    }
19073
19074    /**
19075     * Sets the minimum width of the view. It is not guaranteed the view will
19076     * be able to achieve this minimum width (for example, if its parent layout
19077     * constrains it with less available width).
19078     *
19079     * @param minWidth The minimum width the view will try to be.
19080     *
19081     * @see #getMinimumWidth()
19082     *
19083     * @attr ref android.R.styleable#View_minWidth
19084     */
19085    public void setMinimumWidth(int minWidth) {
19086        mMinWidth = minWidth;
19087        requestLayout();
19088
19089    }
19090
19091    /**
19092     * Get the animation currently associated with this view.
19093     *
19094     * @return The animation that is currently playing or
19095     *         scheduled to play for this view.
19096     */
19097    public Animation getAnimation() {
19098        return mCurrentAnimation;
19099    }
19100
19101    /**
19102     * Start the specified animation now.
19103     *
19104     * @param animation the animation to start now
19105     */
19106    public void startAnimation(Animation animation) {
19107        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19108        setAnimation(animation);
19109        invalidateParentCaches();
19110        invalidate(true);
19111    }
19112
19113    /**
19114     * Cancels any animations for this view.
19115     */
19116    public void clearAnimation() {
19117        if (mCurrentAnimation != null) {
19118            mCurrentAnimation.detach();
19119        }
19120        mCurrentAnimation = null;
19121        invalidateParentIfNeeded();
19122    }
19123
19124    /**
19125     * Sets the next animation to play for this view.
19126     * If you want the animation to play immediately, use
19127     * {@link #startAnimation(android.view.animation.Animation)} instead.
19128     * This method provides allows fine-grained
19129     * control over the start time and invalidation, but you
19130     * must make sure that 1) the animation has a start time set, and
19131     * 2) the view's parent (which controls animations on its children)
19132     * will be invalidated when the animation is supposed to
19133     * start.
19134     *
19135     * @param animation The next animation, or null.
19136     */
19137    public void setAnimation(Animation animation) {
19138        mCurrentAnimation = animation;
19139
19140        if (animation != null) {
19141            // If the screen is off assume the animation start time is now instead of
19142            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19143            // would cause the animation to start when the screen turns back on
19144            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19145                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19146                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19147            }
19148            animation.reset();
19149        }
19150    }
19151
19152    /**
19153     * Invoked by a parent ViewGroup to notify the start of the animation
19154     * currently associated with this view. If you override this method,
19155     * always call super.onAnimationStart();
19156     *
19157     * @see #setAnimation(android.view.animation.Animation)
19158     * @see #getAnimation()
19159     */
19160    @CallSuper
19161    protected void onAnimationStart() {
19162        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19163    }
19164
19165    /**
19166     * Invoked by a parent ViewGroup to notify the end of the animation
19167     * currently associated with this view. If you override this method,
19168     * always call super.onAnimationEnd();
19169     *
19170     * @see #setAnimation(android.view.animation.Animation)
19171     * @see #getAnimation()
19172     */
19173    @CallSuper
19174    protected void onAnimationEnd() {
19175        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19176    }
19177
19178    /**
19179     * Invoked if there is a Transform that involves alpha. Subclass that can
19180     * draw themselves with the specified alpha should return true, and then
19181     * respect that alpha when their onDraw() is called. If this returns false
19182     * then the view may be redirected to draw into an offscreen buffer to
19183     * fulfill the request, which will look fine, but may be slower than if the
19184     * subclass handles it internally. The default implementation returns false.
19185     *
19186     * @param alpha The alpha (0..255) to apply to the view's drawing
19187     * @return true if the view can draw with the specified alpha.
19188     */
19189    protected boolean onSetAlpha(int alpha) {
19190        return false;
19191    }
19192
19193    /**
19194     * This is used by the RootView to perform an optimization when
19195     * the view hierarchy contains one or several SurfaceView.
19196     * SurfaceView is always considered transparent, but its children are not,
19197     * therefore all View objects remove themselves from the global transparent
19198     * region (passed as a parameter to this function).
19199     *
19200     * @param region The transparent region for this ViewAncestor (window).
19201     *
19202     * @return Returns true if the effective visibility of the view at this
19203     * point is opaque, regardless of the transparent region; returns false
19204     * if it is possible for underlying windows to be seen behind the view.
19205     *
19206     * {@hide}
19207     */
19208    public boolean gatherTransparentRegion(Region region) {
19209        final AttachInfo attachInfo = mAttachInfo;
19210        if (region != null && attachInfo != null) {
19211            final int pflags = mPrivateFlags;
19212            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19213                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19214                // remove it from the transparent region.
19215                final int[] location = attachInfo.mTransparentLocation;
19216                getLocationInWindow(location);
19217                region.op(location[0], location[1], location[0] + mRight - mLeft,
19218                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19219            } else {
19220                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19221                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19222                    // the background drawable's non-transparent parts from this transparent region.
19223                    applyDrawableToTransparentRegion(mBackground, region);
19224                }
19225                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19226                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19227                    // Similarly, we remove the foreground drawable's non-transparent parts.
19228                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19229                }
19230            }
19231        }
19232        return true;
19233    }
19234
19235    /**
19236     * Play a sound effect for this view.
19237     *
19238     * <p>The framework will play sound effects for some built in actions, such as
19239     * clicking, but you may wish to play these effects in your widget,
19240     * for instance, for internal navigation.
19241     *
19242     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19243     * {@link #isSoundEffectsEnabled()} is true.
19244     *
19245     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19246     */
19247    public void playSoundEffect(int soundConstant) {
19248        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19249            return;
19250        }
19251        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19252    }
19253
19254    /**
19255     * BZZZTT!!1!
19256     *
19257     * <p>Provide haptic feedback to the user for this view.
19258     *
19259     * <p>The framework will provide haptic feedback for some built in actions,
19260     * such as long presses, but you may wish to provide feedback for your
19261     * own widget.
19262     *
19263     * <p>The feedback will only be performed if
19264     * {@link #isHapticFeedbackEnabled()} is true.
19265     *
19266     * @param feedbackConstant One of the constants defined in
19267     * {@link HapticFeedbackConstants}
19268     */
19269    public boolean performHapticFeedback(int feedbackConstant) {
19270        return performHapticFeedback(feedbackConstant, 0);
19271    }
19272
19273    /**
19274     * BZZZTT!!1!
19275     *
19276     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19277     *
19278     * @param feedbackConstant One of the constants defined in
19279     * {@link HapticFeedbackConstants}
19280     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19281     */
19282    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19283        if (mAttachInfo == null) {
19284            return false;
19285        }
19286        //noinspection SimplifiableIfStatement
19287        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19288                && !isHapticFeedbackEnabled()) {
19289            return false;
19290        }
19291        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19292                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19293    }
19294
19295    /**
19296     * Request that the visibility of the status bar or other screen/window
19297     * decorations be changed.
19298     *
19299     * <p>This method is used to put the over device UI into temporary modes
19300     * where the user's attention is focused more on the application content,
19301     * by dimming or hiding surrounding system affordances.  This is typically
19302     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19303     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19304     * to be placed behind the action bar (and with these flags other system
19305     * affordances) so that smooth transitions between hiding and showing them
19306     * can be done.
19307     *
19308     * <p>Two representative examples of the use of system UI visibility is
19309     * implementing a content browsing application (like a magazine reader)
19310     * and a video playing application.
19311     *
19312     * <p>The first code shows a typical implementation of a View in a content
19313     * browsing application.  In this implementation, the application goes
19314     * into a content-oriented mode by hiding the status bar and action bar,
19315     * and putting the navigation elements into lights out mode.  The user can
19316     * then interact with content while in this mode.  Such an application should
19317     * provide an easy way for the user to toggle out of the mode (such as to
19318     * check information in the status bar or access notifications).  In the
19319     * implementation here, this is done simply by tapping on the content.
19320     *
19321     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19322     *      content}
19323     *
19324     * <p>This second code sample shows a typical implementation of a View
19325     * in a video playing application.  In this situation, while the video is
19326     * playing the application would like to go into a complete full-screen mode,
19327     * to use as much of the display as possible for the video.  When in this state
19328     * the user can not interact with the application; the system intercepts
19329     * touching on the screen to pop the UI out of full screen mode.  See
19330     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19331     *
19332     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19333     *      content}
19334     *
19335     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19336     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19337     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19338     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19339     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19340     */
19341    public void setSystemUiVisibility(int visibility) {
19342        if (visibility != mSystemUiVisibility) {
19343            mSystemUiVisibility = visibility;
19344            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19345                mParent.recomputeViewAttributes(this);
19346            }
19347        }
19348    }
19349
19350    /**
19351     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19352     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19353     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19354     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19355     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19356     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19357     */
19358    public int getSystemUiVisibility() {
19359        return mSystemUiVisibility;
19360    }
19361
19362    /**
19363     * Returns the current system UI visibility that is currently set for
19364     * the entire window.  This is the combination of the
19365     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19366     * views in the window.
19367     */
19368    public int getWindowSystemUiVisibility() {
19369        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19370    }
19371
19372    /**
19373     * Override to find out when the window's requested system UI visibility
19374     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19375     * This is different from the callbacks received through
19376     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19377     * in that this is only telling you about the local request of the window,
19378     * not the actual values applied by the system.
19379     */
19380    public void onWindowSystemUiVisibilityChanged(int visible) {
19381    }
19382
19383    /**
19384     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19385     * the view hierarchy.
19386     */
19387    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19388        onWindowSystemUiVisibilityChanged(visible);
19389    }
19390
19391    /**
19392     * Set a listener to receive callbacks when the visibility of the system bar changes.
19393     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19394     */
19395    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19396        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19397        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19398            mParent.recomputeViewAttributes(this);
19399        }
19400    }
19401
19402    /**
19403     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19404     * the view hierarchy.
19405     */
19406    public void dispatchSystemUiVisibilityChanged(int visibility) {
19407        ListenerInfo li = mListenerInfo;
19408        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19409            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19410                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19411        }
19412    }
19413
19414    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19415        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19416        if (val != mSystemUiVisibility) {
19417            setSystemUiVisibility(val);
19418            return true;
19419        }
19420        return false;
19421    }
19422
19423    /** @hide */
19424    public void setDisabledSystemUiVisibility(int flags) {
19425        if (mAttachInfo != null) {
19426            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19427                mAttachInfo.mDisabledSystemUiVisibility = flags;
19428                if (mParent != null) {
19429                    mParent.recomputeViewAttributes(this);
19430                }
19431            }
19432        }
19433    }
19434
19435    /**
19436     * Creates an image that the system displays during the drag and drop
19437     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19438     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19439     * appearance as the given View. The default also positions the center of the drag shadow
19440     * directly under the touch point. If no View is provided (the constructor with no parameters
19441     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19442     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19443     * default is an invisible drag shadow.
19444     * <p>
19445     * You are not required to use the View you provide to the constructor as the basis of the
19446     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19447     * anything you want as the drag shadow.
19448     * </p>
19449     * <p>
19450     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19451     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19452     *  size and position of the drag shadow. It uses this data to construct a
19453     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19454     *  so that your application can draw the shadow image in the Canvas.
19455     * </p>
19456     *
19457     * <div class="special reference">
19458     * <h3>Developer Guides</h3>
19459     * <p>For a guide to implementing drag and drop features, read the
19460     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19461     * </div>
19462     */
19463    public static class DragShadowBuilder {
19464        private final WeakReference<View> mView;
19465
19466        /**
19467         * Constructs a shadow image builder based on a View. By default, the resulting drag
19468         * shadow will have the same appearance and dimensions as the View, with the touch point
19469         * over the center of the View.
19470         * @param view A View. Any View in scope can be used.
19471         */
19472        public DragShadowBuilder(View view) {
19473            mView = new WeakReference<View>(view);
19474        }
19475
19476        /**
19477         * Construct a shadow builder object with no associated View.  This
19478         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19479         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19480         * to supply the drag shadow's dimensions and appearance without
19481         * reference to any View object. If they are not overridden, then the result is an
19482         * invisible drag shadow.
19483         */
19484        public DragShadowBuilder() {
19485            mView = new WeakReference<View>(null);
19486        }
19487
19488        /**
19489         * Returns the View object that had been passed to the
19490         * {@link #View.DragShadowBuilder(View)}
19491         * constructor.  If that View parameter was {@code null} or if the
19492         * {@link #View.DragShadowBuilder()}
19493         * constructor was used to instantiate the builder object, this method will return
19494         * null.
19495         *
19496         * @return The View object associate with this builder object.
19497         */
19498        @SuppressWarnings({"JavadocReference"})
19499        final public View getView() {
19500            return mView.get();
19501        }
19502
19503        /**
19504         * Provides the metrics for the shadow image. These include the dimensions of
19505         * the shadow image, and the point within that shadow that should
19506         * be centered under the touch location while dragging.
19507         * <p>
19508         * The default implementation sets the dimensions of the shadow to be the
19509         * same as the dimensions of the View itself and centers the shadow under
19510         * the touch point.
19511         * </p>
19512         *
19513         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19514         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19515         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19516         * image.
19517         *
19518         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19519         * shadow image that should be underneath the touch point during the drag and drop
19520         * operation. Your application must set {@link android.graphics.Point#x} to the
19521         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19522         */
19523        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19524            final View view = mView.get();
19525            if (view != null) {
19526                shadowSize.set(view.getWidth(), view.getHeight());
19527                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19528            } else {
19529                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19530            }
19531        }
19532
19533        /**
19534         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19535         * based on the dimensions it received from the
19536         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19537         *
19538         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19539         */
19540        public void onDrawShadow(Canvas canvas) {
19541            final View view = mView.get();
19542            if (view != null) {
19543                view.draw(canvas);
19544            } else {
19545                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19546            }
19547        }
19548    }
19549
19550    /**
19551     * Starts a drag and drop operation. When your application calls this method, it passes a
19552     * {@link android.view.View.DragShadowBuilder} object to the system. The
19553     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19554     * to get metrics for the drag shadow, and then calls the object's
19555     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19556     * <p>
19557     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19558     *  drag events to all the View objects in your application that are currently visible. It does
19559     *  this either by calling the View object's drag listener (an implementation of
19560     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19561     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19562     *  Both are passed a {@link android.view.DragEvent} object that has a
19563     *  {@link android.view.DragEvent#getAction()} value of
19564     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19565     * </p>
19566     * <p>
19567     * Your application can invoke startDrag() on any attached View object. The View object does not
19568     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19569     * be related to the View the user selected for dragging.
19570     * </p>
19571     * @param data A {@link android.content.ClipData} object pointing to the data to be
19572     * transferred by the drag and drop operation.
19573     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19574     * drag shadow.
19575     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19576     * drop operation. This Object is put into every DragEvent object sent by the system during the
19577     * current drag.
19578     * <p>
19579     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19580     * to the target Views. For example, it can contain flags that differentiate between a
19581     * a copy operation and a move operation.
19582     * </p>
19583     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19584     * so the parameter should be set to 0.
19585     * @return {@code true} if the method completes successfully, or
19586     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19587     * do a drag, and so no drag operation is in progress.
19588     */
19589    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19590            Object myLocalState, int flags) {
19591        if (ViewDebug.DEBUG_DRAG) {
19592            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19593        }
19594        boolean okay = false;
19595
19596        Point shadowSize = new Point();
19597        Point shadowTouchPoint = new Point();
19598        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19599
19600        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19601                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19602            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19603        }
19604
19605        if (ViewDebug.DEBUG_DRAG) {
19606            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19607                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19608        }
19609        Surface surface = new Surface();
19610        try {
19611            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19612                    flags, shadowSize.x, shadowSize.y, surface);
19613            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19614                    + " surface=" + surface);
19615            if (token != null) {
19616                Canvas canvas = surface.lockCanvas(null);
19617                try {
19618                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19619                    shadowBuilder.onDrawShadow(canvas);
19620                } finally {
19621                    surface.unlockCanvasAndPost(canvas);
19622                }
19623
19624                final ViewRootImpl root = getViewRootImpl();
19625
19626                // Cache the local state object for delivery with DragEvents
19627                root.setLocalDragState(myLocalState);
19628
19629                // repurpose 'shadowSize' for the last touch point
19630                root.getLastTouchPoint(shadowSize);
19631
19632                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19633                        shadowSize.x, shadowSize.y,
19634                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19635                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19636
19637                // Off and running!  Release our local surface instance; the drag
19638                // shadow surface is now managed by the system process.
19639                surface.release();
19640            }
19641        } catch (Exception e) {
19642            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19643            surface.destroy();
19644        }
19645
19646        return okay;
19647    }
19648
19649    /**
19650     * Handles drag events sent by the system following a call to
19651     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19652     *<p>
19653     * When the system calls this method, it passes a
19654     * {@link android.view.DragEvent} object. A call to
19655     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19656     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19657     * operation.
19658     * @param event The {@link android.view.DragEvent} sent by the system.
19659     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19660     * in DragEvent, indicating the type of drag event represented by this object.
19661     * @return {@code true} if the method was successful, otherwise {@code false}.
19662     * <p>
19663     *  The method should return {@code true} in response to an action type of
19664     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19665     *  operation.
19666     * </p>
19667     * <p>
19668     *  The method should also return {@code true} in response to an action type of
19669     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19670     *  {@code false} if it didn't.
19671     * </p>
19672     */
19673    public boolean onDragEvent(DragEvent event) {
19674        return false;
19675    }
19676
19677    /**
19678     * Detects if this View is enabled and has a drag event listener.
19679     * If both are true, then it calls the drag event listener with the
19680     * {@link android.view.DragEvent} it received. If the drag event listener returns
19681     * {@code true}, then dispatchDragEvent() returns {@code true}.
19682     * <p>
19683     * For all other cases, the method calls the
19684     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
19685     * method and returns its result.
19686     * </p>
19687     * <p>
19688     * This ensures that a drag event is always consumed, even if the View does not have a drag
19689     * event listener. However, if the View has a listener and the listener returns true, then
19690     * onDragEvent() is not called.
19691     * </p>
19692     */
19693    public boolean dispatchDragEvent(DragEvent event) {
19694        ListenerInfo li = mListenerInfo;
19695        //noinspection SimplifiableIfStatement
19696        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
19697                && li.mOnDragListener.onDrag(this, event)) {
19698            return true;
19699        }
19700        return onDragEvent(event);
19701    }
19702
19703    boolean canAcceptDrag() {
19704        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
19705    }
19706
19707    /**
19708     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
19709     * it is ever exposed at all.
19710     * @hide
19711     */
19712    public void onCloseSystemDialogs(String reason) {
19713    }
19714
19715    /**
19716     * Given a Drawable whose bounds have been set to draw into this view,
19717     * update a Region being computed for
19718     * {@link #gatherTransparentRegion(android.graphics.Region)} so
19719     * that any non-transparent parts of the Drawable are removed from the
19720     * given transparent region.
19721     *
19722     * @param dr The Drawable whose transparency is to be applied to the region.
19723     * @param region A Region holding the current transparency information,
19724     * where any parts of the region that are set are considered to be
19725     * transparent.  On return, this region will be modified to have the
19726     * transparency information reduced by the corresponding parts of the
19727     * Drawable that are not transparent.
19728     * {@hide}
19729     */
19730    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
19731        if (DBG) {
19732            Log.i("View", "Getting transparent region for: " + this);
19733        }
19734        final Region r = dr.getTransparentRegion();
19735        final Rect db = dr.getBounds();
19736        final AttachInfo attachInfo = mAttachInfo;
19737        if (r != null && attachInfo != null) {
19738            final int w = getRight()-getLeft();
19739            final int h = getBottom()-getTop();
19740            if (db.left > 0) {
19741                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
19742                r.op(0, 0, db.left, h, Region.Op.UNION);
19743            }
19744            if (db.right < w) {
19745                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
19746                r.op(db.right, 0, w, h, Region.Op.UNION);
19747            }
19748            if (db.top > 0) {
19749                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
19750                r.op(0, 0, w, db.top, Region.Op.UNION);
19751            }
19752            if (db.bottom < h) {
19753                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
19754                r.op(0, db.bottom, w, h, Region.Op.UNION);
19755            }
19756            final int[] location = attachInfo.mTransparentLocation;
19757            getLocationInWindow(location);
19758            r.translate(location[0], location[1]);
19759            region.op(r, Region.Op.INTERSECT);
19760        } else {
19761            region.op(db, Region.Op.DIFFERENCE);
19762        }
19763    }
19764
19765    private void checkForLongClick(int delayOffset) {
19766        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
19767            mHasPerformedLongPress = false;
19768
19769            if (mPendingCheckForLongPress == null) {
19770                mPendingCheckForLongPress = new CheckForLongPress();
19771            }
19772            mPendingCheckForLongPress.rememberWindowAttachCount();
19773            postDelayed(mPendingCheckForLongPress,
19774                    ViewConfiguration.getLongPressTimeout() - delayOffset);
19775        }
19776    }
19777
19778    /**
19779     * Inflate a view from an XML resource.  This convenience method wraps the {@link
19780     * LayoutInflater} class, which provides a full range of options for view inflation.
19781     *
19782     * @param context The Context object for your activity or application.
19783     * @param resource The resource ID to inflate
19784     * @param root A view group that will be the parent.  Used to properly inflate the
19785     * layout_* parameters.
19786     * @see LayoutInflater
19787     */
19788    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
19789        LayoutInflater factory = LayoutInflater.from(context);
19790        return factory.inflate(resource, root);
19791    }
19792
19793    /**
19794     * Scroll the view with standard behavior for scrolling beyond the normal
19795     * content boundaries. Views that call this method should override
19796     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
19797     * results of an over-scroll operation.
19798     *
19799     * Views can use this method to handle any touch or fling-based scrolling.
19800     *
19801     * @param deltaX Change in X in pixels
19802     * @param deltaY Change in Y in pixels
19803     * @param scrollX Current X scroll value in pixels before applying deltaX
19804     * @param scrollY Current Y scroll value in pixels before applying deltaY
19805     * @param scrollRangeX Maximum content scroll range along the X axis
19806     * @param scrollRangeY Maximum content scroll range along the Y axis
19807     * @param maxOverScrollX Number of pixels to overscroll by in either direction
19808     *          along the X axis.
19809     * @param maxOverScrollY Number of pixels to overscroll by in either direction
19810     *          along the Y axis.
19811     * @param isTouchEvent true if this scroll operation is the result of a touch event.
19812     * @return true if scrolling was clamped to an over-scroll boundary along either
19813     *          axis, false otherwise.
19814     */
19815    @SuppressWarnings({"UnusedParameters"})
19816    protected boolean overScrollBy(int deltaX, int deltaY,
19817            int scrollX, int scrollY,
19818            int scrollRangeX, int scrollRangeY,
19819            int maxOverScrollX, int maxOverScrollY,
19820            boolean isTouchEvent) {
19821        final int overScrollMode = mOverScrollMode;
19822        final boolean canScrollHorizontal =
19823                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
19824        final boolean canScrollVertical =
19825                computeVerticalScrollRange() > computeVerticalScrollExtent();
19826        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
19827                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
19828        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
19829                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
19830
19831        int newScrollX = scrollX + deltaX;
19832        if (!overScrollHorizontal) {
19833            maxOverScrollX = 0;
19834        }
19835
19836        int newScrollY = scrollY + deltaY;
19837        if (!overScrollVertical) {
19838            maxOverScrollY = 0;
19839        }
19840
19841        // Clamp values if at the limits and record
19842        final int left = -maxOverScrollX;
19843        final int right = maxOverScrollX + scrollRangeX;
19844        final int top = -maxOverScrollY;
19845        final int bottom = maxOverScrollY + scrollRangeY;
19846
19847        boolean clampedX = false;
19848        if (newScrollX > right) {
19849            newScrollX = right;
19850            clampedX = true;
19851        } else if (newScrollX < left) {
19852            newScrollX = left;
19853            clampedX = true;
19854        }
19855
19856        boolean clampedY = false;
19857        if (newScrollY > bottom) {
19858            newScrollY = bottom;
19859            clampedY = true;
19860        } else if (newScrollY < top) {
19861            newScrollY = top;
19862            clampedY = true;
19863        }
19864
19865        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
19866
19867        return clampedX || clampedY;
19868    }
19869
19870    /**
19871     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
19872     * respond to the results of an over-scroll operation.
19873     *
19874     * @param scrollX New X scroll value in pixels
19875     * @param scrollY New Y scroll value in pixels
19876     * @param clampedX True if scrollX was clamped to an over-scroll boundary
19877     * @param clampedY True if scrollY was clamped to an over-scroll boundary
19878     */
19879    protected void onOverScrolled(int scrollX, int scrollY,
19880            boolean clampedX, boolean clampedY) {
19881        // Intentionally empty.
19882    }
19883
19884    /**
19885     * Returns the over-scroll mode for this view. The result will be
19886     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19887     * (allow over-scrolling only if the view content is larger than the container),
19888     * or {@link #OVER_SCROLL_NEVER}.
19889     *
19890     * @return This view's over-scroll mode.
19891     */
19892    public int getOverScrollMode() {
19893        return mOverScrollMode;
19894    }
19895
19896    /**
19897     * Set the over-scroll mode for this view. Valid over-scroll modes are
19898     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
19899     * (allow over-scrolling only if the view content is larger than the container),
19900     * or {@link #OVER_SCROLL_NEVER}.
19901     *
19902     * Setting the over-scroll mode of a view will have an effect only if the
19903     * view is capable of scrolling.
19904     *
19905     * @param overScrollMode The new over-scroll mode for this view.
19906     */
19907    public void setOverScrollMode(int overScrollMode) {
19908        if (overScrollMode != OVER_SCROLL_ALWAYS &&
19909                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
19910                overScrollMode != OVER_SCROLL_NEVER) {
19911            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
19912        }
19913        mOverScrollMode = overScrollMode;
19914    }
19915
19916    /**
19917     * Enable or disable nested scrolling for this view.
19918     *
19919     * <p>If this property is set to true the view will be permitted to initiate nested
19920     * scrolling operations with a compatible parent view in the current hierarchy. If this
19921     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
19922     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
19923     * the nested scroll.</p>
19924     *
19925     * @param enabled true to enable nested scrolling, false to disable
19926     *
19927     * @see #isNestedScrollingEnabled()
19928     */
19929    public void setNestedScrollingEnabled(boolean enabled) {
19930        if (enabled) {
19931            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
19932        } else {
19933            stopNestedScroll();
19934            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
19935        }
19936    }
19937
19938    /**
19939     * Returns true if nested scrolling is enabled for this view.
19940     *
19941     * <p>If nested scrolling is enabled and this View class implementation supports it,
19942     * this view will act as a nested scrolling child view when applicable, forwarding data
19943     * about the scroll operation in progress to a compatible and cooperating nested scrolling
19944     * parent.</p>
19945     *
19946     * @return true if nested scrolling is enabled
19947     *
19948     * @see #setNestedScrollingEnabled(boolean)
19949     */
19950    public boolean isNestedScrollingEnabled() {
19951        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
19952                PFLAG3_NESTED_SCROLLING_ENABLED;
19953    }
19954
19955    /**
19956     * Begin a nestable scroll operation along the given axes.
19957     *
19958     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
19959     *
19960     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
19961     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
19962     * In the case of touch scrolling the nested scroll will be terminated automatically in
19963     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
19964     * In the event of programmatic scrolling the caller must explicitly call
19965     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
19966     *
19967     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
19968     * If it returns false the caller may ignore the rest of this contract until the next scroll.
19969     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
19970     *
19971     * <p>At each incremental step of the scroll the caller should invoke
19972     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
19973     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
19974     * parent at least partially consumed the scroll and the caller should adjust the amount it
19975     * scrolls by.</p>
19976     *
19977     * <p>After applying the remainder of the scroll delta the caller should invoke
19978     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
19979     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
19980     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
19981     * </p>
19982     *
19983     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
19984     *             {@link #SCROLL_AXIS_VERTICAL}.
19985     * @return true if a cooperative parent was found and nested scrolling has been enabled for
19986     *         the current gesture.
19987     *
19988     * @see #stopNestedScroll()
19989     * @see #dispatchNestedPreScroll(int, int, int[], int[])
19990     * @see #dispatchNestedScroll(int, int, int, int, int[])
19991     */
19992    public boolean startNestedScroll(int axes) {
19993        if (hasNestedScrollingParent()) {
19994            // Already in progress
19995            return true;
19996        }
19997        if (isNestedScrollingEnabled()) {
19998            ViewParent p = getParent();
19999            View child = this;
20000            while (p != null) {
20001                try {
20002                    if (p.onStartNestedScroll(child, this, axes)) {
20003                        mNestedScrollingParent = p;
20004                        p.onNestedScrollAccepted(child, this, axes);
20005                        return true;
20006                    }
20007                } catch (AbstractMethodError e) {
20008                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20009                            "method onStartNestedScroll", e);
20010                    // Allow the search upward to continue
20011                }
20012                if (p instanceof View) {
20013                    child = (View) p;
20014                }
20015                p = p.getParent();
20016            }
20017        }
20018        return false;
20019    }
20020
20021    /**
20022     * Stop a nested scroll in progress.
20023     *
20024     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20025     *
20026     * @see #startNestedScroll(int)
20027     */
20028    public void stopNestedScroll() {
20029        if (mNestedScrollingParent != null) {
20030            mNestedScrollingParent.onStopNestedScroll(this);
20031            mNestedScrollingParent = null;
20032        }
20033    }
20034
20035    /**
20036     * Returns true if this view has a nested scrolling parent.
20037     *
20038     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20039     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20040     *
20041     * @return whether this view has a nested scrolling parent
20042     */
20043    public boolean hasNestedScrollingParent() {
20044        return mNestedScrollingParent != null;
20045    }
20046
20047    /**
20048     * Dispatch one step of a nested scroll in progress.
20049     *
20050     * <p>Implementations of views that support nested scrolling should call this to report
20051     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20052     * is not currently in progress or nested scrolling is not
20053     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20054     *
20055     * <p>Compatible View implementations should also call
20056     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20057     * consuming a component of the scroll event themselves.</p>
20058     *
20059     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20060     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20061     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20062     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20063     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20064     *                       in local view coordinates of this view from before this operation
20065     *                       to after it completes. View implementations may use this to adjust
20066     *                       expected input coordinate tracking.
20067     * @return true if the event was dispatched, false if it could not be dispatched.
20068     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20069     */
20070    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20071            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20072        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20073            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20074                int startX = 0;
20075                int startY = 0;
20076                if (offsetInWindow != null) {
20077                    getLocationInWindow(offsetInWindow);
20078                    startX = offsetInWindow[0];
20079                    startY = offsetInWindow[1];
20080                }
20081
20082                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20083                        dxUnconsumed, dyUnconsumed);
20084
20085                if (offsetInWindow != null) {
20086                    getLocationInWindow(offsetInWindow);
20087                    offsetInWindow[0] -= startX;
20088                    offsetInWindow[1] -= startY;
20089                }
20090                return true;
20091            } else if (offsetInWindow != null) {
20092                // No motion, no dispatch. Keep offsetInWindow up to date.
20093                offsetInWindow[0] = 0;
20094                offsetInWindow[1] = 0;
20095            }
20096        }
20097        return false;
20098    }
20099
20100    /**
20101     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20102     *
20103     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20104     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20105     * scrolling operation to consume some or all of the scroll operation before the child view
20106     * consumes it.</p>
20107     *
20108     * @param dx Horizontal scroll distance in pixels
20109     * @param dy Vertical scroll distance in pixels
20110     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20111     *                 and consumed[1] the consumed dy.
20112     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20113     *                       in local view coordinates of this view from before this operation
20114     *                       to after it completes. View implementations may use this to adjust
20115     *                       expected input coordinate tracking.
20116     * @return true if the parent consumed some or all of the scroll delta
20117     * @see #dispatchNestedScroll(int, int, int, int, int[])
20118     */
20119    public boolean dispatchNestedPreScroll(int dx, int dy,
20120            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20121        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20122            if (dx != 0 || dy != 0) {
20123                int startX = 0;
20124                int startY = 0;
20125                if (offsetInWindow != null) {
20126                    getLocationInWindow(offsetInWindow);
20127                    startX = offsetInWindow[0];
20128                    startY = offsetInWindow[1];
20129                }
20130
20131                if (consumed == null) {
20132                    if (mTempNestedScrollConsumed == null) {
20133                        mTempNestedScrollConsumed = new int[2];
20134                    }
20135                    consumed = mTempNestedScrollConsumed;
20136                }
20137                consumed[0] = 0;
20138                consumed[1] = 0;
20139                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20140
20141                if (offsetInWindow != null) {
20142                    getLocationInWindow(offsetInWindow);
20143                    offsetInWindow[0] -= startX;
20144                    offsetInWindow[1] -= startY;
20145                }
20146                return consumed[0] != 0 || consumed[1] != 0;
20147            } else if (offsetInWindow != null) {
20148                offsetInWindow[0] = 0;
20149                offsetInWindow[1] = 0;
20150            }
20151        }
20152        return false;
20153    }
20154
20155    /**
20156     * Dispatch a fling to a nested scrolling parent.
20157     *
20158     * <p>This method should be used to indicate that a nested scrolling child has detected
20159     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20160     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20161     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20162     * along a scrollable axis.</p>
20163     *
20164     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20165     * its own content, it can use this method to delegate the fling to its nested scrolling
20166     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20167     *
20168     * @param velocityX Horizontal fling velocity in pixels per second
20169     * @param velocityY Vertical fling velocity in pixels per second
20170     * @param consumed true if the child consumed the fling, false otherwise
20171     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20172     */
20173    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20174        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20175            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20176        }
20177        return false;
20178    }
20179
20180    /**
20181     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20182     *
20183     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20184     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20185     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20186     * before the child view consumes it. If this method returns <code>true</code>, a nested
20187     * parent view consumed the fling and this view should not scroll as a result.</p>
20188     *
20189     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20190     * the fling at a time. If a parent view consumed the fling this method will return false.
20191     * Custom view implementations should account for this in two ways:</p>
20192     *
20193     * <ul>
20194     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20195     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20196     *     position regardless.</li>
20197     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20198     *     even to settle back to a valid idle position.</li>
20199     * </ul>
20200     *
20201     * <p>Views should also not offer fling velocities to nested parent views along an axis
20202     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20203     * should not offer a horizontal fling velocity to its parents since scrolling along that
20204     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20205     *
20206     * @param velocityX Horizontal fling velocity in pixels per second
20207     * @param velocityY Vertical fling velocity in pixels per second
20208     * @return true if a nested scrolling parent consumed the fling
20209     */
20210    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20211        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20212            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20213        }
20214        return false;
20215    }
20216
20217    /**
20218     * Gets a scale factor that determines the distance the view should scroll
20219     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20220     * @return The vertical scroll scale factor.
20221     * @hide
20222     */
20223    protected float getVerticalScrollFactor() {
20224        if (mVerticalScrollFactor == 0) {
20225            TypedValue outValue = new TypedValue();
20226            if (!mContext.getTheme().resolveAttribute(
20227                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20228                throw new IllegalStateException(
20229                        "Expected theme to define listPreferredItemHeight.");
20230            }
20231            mVerticalScrollFactor = outValue.getDimension(
20232                    mContext.getResources().getDisplayMetrics());
20233        }
20234        return mVerticalScrollFactor;
20235    }
20236
20237    /**
20238     * Gets a scale factor that determines the distance the view should scroll
20239     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20240     * @return The horizontal scroll scale factor.
20241     * @hide
20242     */
20243    protected float getHorizontalScrollFactor() {
20244        // TODO: Should use something else.
20245        return getVerticalScrollFactor();
20246    }
20247
20248    /**
20249     * Return the value specifying the text direction or policy that was set with
20250     * {@link #setTextDirection(int)}.
20251     *
20252     * @return the defined text direction. It can be one of:
20253     *
20254     * {@link #TEXT_DIRECTION_INHERIT},
20255     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20256     * {@link #TEXT_DIRECTION_ANY_RTL},
20257     * {@link #TEXT_DIRECTION_LTR},
20258     * {@link #TEXT_DIRECTION_RTL},
20259     * {@link #TEXT_DIRECTION_LOCALE},
20260     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20261     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20262     *
20263     * @attr ref android.R.styleable#View_textDirection
20264     *
20265     * @hide
20266     */
20267    @ViewDebug.ExportedProperty(category = "text", mapping = {
20268            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20269            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20270            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20271            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20272            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20273            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20274            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20275            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20276    })
20277    public int getRawTextDirection() {
20278        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20279    }
20280
20281    /**
20282     * Set the text direction.
20283     *
20284     * @param textDirection the direction to set. Should be one of:
20285     *
20286     * {@link #TEXT_DIRECTION_INHERIT},
20287     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20288     * {@link #TEXT_DIRECTION_ANY_RTL},
20289     * {@link #TEXT_DIRECTION_LTR},
20290     * {@link #TEXT_DIRECTION_RTL},
20291     * {@link #TEXT_DIRECTION_LOCALE}
20292     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20293     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20294     *
20295     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20296     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20297     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20298     *
20299     * @attr ref android.R.styleable#View_textDirection
20300     */
20301    public void setTextDirection(int textDirection) {
20302        if (getRawTextDirection() != textDirection) {
20303            // Reset the current text direction and the resolved one
20304            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20305            resetResolvedTextDirection();
20306            // Set the new text direction
20307            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20308            // Do resolution
20309            resolveTextDirection();
20310            // Notify change
20311            onRtlPropertiesChanged(getLayoutDirection());
20312            // Refresh
20313            requestLayout();
20314            invalidate(true);
20315        }
20316    }
20317
20318    /**
20319     * Return the resolved text direction.
20320     *
20321     * @return the resolved text direction. Returns one of:
20322     *
20323     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20324     * {@link #TEXT_DIRECTION_ANY_RTL},
20325     * {@link #TEXT_DIRECTION_LTR},
20326     * {@link #TEXT_DIRECTION_RTL},
20327     * {@link #TEXT_DIRECTION_LOCALE},
20328     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20329     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20330     *
20331     * @attr ref android.R.styleable#View_textDirection
20332     */
20333    @ViewDebug.ExportedProperty(category = "text", mapping = {
20334            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20335            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20336            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20337            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20338            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20339            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20340            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20341            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20342    })
20343    public int getTextDirection() {
20344        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20345    }
20346
20347    /**
20348     * Resolve the text direction.
20349     *
20350     * @return true if resolution has been done, false otherwise.
20351     *
20352     * @hide
20353     */
20354    public boolean resolveTextDirection() {
20355        // Reset any previous text direction resolution
20356        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20357
20358        if (hasRtlSupport()) {
20359            // Set resolved text direction flag depending on text direction flag
20360            final int textDirection = getRawTextDirection();
20361            switch(textDirection) {
20362                case TEXT_DIRECTION_INHERIT:
20363                    if (!canResolveTextDirection()) {
20364                        // We cannot do the resolution if there is no parent, so use the default one
20365                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20366                        // Resolution will need to happen again later
20367                        return false;
20368                    }
20369
20370                    // Parent has not yet resolved, so we still return the default
20371                    try {
20372                        if (!mParent.isTextDirectionResolved()) {
20373                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20374                            // Resolution will need to happen again later
20375                            return false;
20376                        }
20377                    } catch (AbstractMethodError e) {
20378                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20379                                " does not fully implement ViewParent", e);
20380                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20381                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20382                        return true;
20383                    }
20384
20385                    // Set current resolved direction to the same value as the parent's one
20386                    int parentResolvedDirection;
20387                    try {
20388                        parentResolvedDirection = mParent.getTextDirection();
20389                    } catch (AbstractMethodError e) {
20390                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20391                                " does not fully implement ViewParent", e);
20392                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20393                    }
20394                    switch (parentResolvedDirection) {
20395                        case TEXT_DIRECTION_FIRST_STRONG:
20396                        case TEXT_DIRECTION_ANY_RTL:
20397                        case TEXT_DIRECTION_LTR:
20398                        case TEXT_DIRECTION_RTL:
20399                        case TEXT_DIRECTION_LOCALE:
20400                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20401                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20402                            mPrivateFlags2 |=
20403                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20404                            break;
20405                        default:
20406                            // Default resolved direction is "first strong" heuristic
20407                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20408                    }
20409                    break;
20410                case TEXT_DIRECTION_FIRST_STRONG:
20411                case TEXT_DIRECTION_ANY_RTL:
20412                case TEXT_DIRECTION_LTR:
20413                case TEXT_DIRECTION_RTL:
20414                case TEXT_DIRECTION_LOCALE:
20415                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20416                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20417                    // Resolved direction is the same as text direction
20418                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20419                    break;
20420                default:
20421                    // Default resolved direction is "first strong" heuristic
20422                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20423            }
20424        } else {
20425            // Default resolved direction is "first strong" heuristic
20426            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20427        }
20428
20429        // Set to resolved
20430        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20431        return true;
20432    }
20433
20434    /**
20435     * Check if text direction resolution can be done.
20436     *
20437     * @return true if text direction resolution can be done otherwise return false.
20438     */
20439    public boolean canResolveTextDirection() {
20440        switch (getRawTextDirection()) {
20441            case TEXT_DIRECTION_INHERIT:
20442                if (mParent != null) {
20443                    try {
20444                        return mParent.canResolveTextDirection();
20445                    } catch (AbstractMethodError e) {
20446                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20447                                " does not fully implement ViewParent", e);
20448                    }
20449                }
20450                return false;
20451
20452            default:
20453                return true;
20454        }
20455    }
20456
20457    /**
20458     * Reset resolved text direction. Text direction will be resolved during a call to
20459     * {@link #onMeasure(int, int)}.
20460     *
20461     * @hide
20462     */
20463    public void resetResolvedTextDirection() {
20464        // Reset any previous text direction resolution
20465        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20466        // Set to default value
20467        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20468    }
20469
20470    /**
20471     * @return true if text direction is inherited.
20472     *
20473     * @hide
20474     */
20475    public boolean isTextDirectionInherited() {
20476        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20477    }
20478
20479    /**
20480     * @return true if text direction is resolved.
20481     */
20482    public boolean isTextDirectionResolved() {
20483        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20484    }
20485
20486    /**
20487     * Return the value specifying the text alignment or policy that was set with
20488     * {@link #setTextAlignment(int)}.
20489     *
20490     * @return the defined text alignment. It can be one of:
20491     *
20492     * {@link #TEXT_ALIGNMENT_INHERIT},
20493     * {@link #TEXT_ALIGNMENT_GRAVITY},
20494     * {@link #TEXT_ALIGNMENT_CENTER},
20495     * {@link #TEXT_ALIGNMENT_TEXT_START},
20496     * {@link #TEXT_ALIGNMENT_TEXT_END},
20497     * {@link #TEXT_ALIGNMENT_VIEW_START},
20498     * {@link #TEXT_ALIGNMENT_VIEW_END}
20499     *
20500     * @attr ref android.R.styleable#View_textAlignment
20501     *
20502     * @hide
20503     */
20504    @ViewDebug.ExportedProperty(category = "text", mapping = {
20505            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20506            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20507            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20508            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20509            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20510            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20511            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20512    })
20513    @TextAlignment
20514    public int getRawTextAlignment() {
20515        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20516    }
20517
20518    /**
20519     * Set the text alignment.
20520     *
20521     * @param textAlignment The text alignment to set. Should be one of
20522     *
20523     * {@link #TEXT_ALIGNMENT_INHERIT},
20524     * {@link #TEXT_ALIGNMENT_GRAVITY},
20525     * {@link #TEXT_ALIGNMENT_CENTER},
20526     * {@link #TEXT_ALIGNMENT_TEXT_START},
20527     * {@link #TEXT_ALIGNMENT_TEXT_END},
20528     * {@link #TEXT_ALIGNMENT_VIEW_START},
20529     * {@link #TEXT_ALIGNMENT_VIEW_END}
20530     *
20531     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20532     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20533     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20534     *
20535     * @attr ref android.R.styleable#View_textAlignment
20536     */
20537    public void setTextAlignment(@TextAlignment int textAlignment) {
20538        if (textAlignment != getRawTextAlignment()) {
20539            // Reset the current and resolved text alignment
20540            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20541            resetResolvedTextAlignment();
20542            // Set the new text alignment
20543            mPrivateFlags2 |=
20544                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20545            // Do resolution
20546            resolveTextAlignment();
20547            // Notify change
20548            onRtlPropertiesChanged(getLayoutDirection());
20549            // Refresh
20550            requestLayout();
20551            invalidate(true);
20552        }
20553    }
20554
20555    /**
20556     * Return the resolved text alignment.
20557     *
20558     * @return the resolved text alignment. Returns one of:
20559     *
20560     * {@link #TEXT_ALIGNMENT_GRAVITY},
20561     * {@link #TEXT_ALIGNMENT_CENTER},
20562     * {@link #TEXT_ALIGNMENT_TEXT_START},
20563     * {@link #TEXT_ALIGNMENT_TEXT_END},
20564     * {@link #TEXT_ALIGNMENT_VIEW_START},
20565     * {@link #TEXT_ALIGNMENT_VIEW_END}
20566     *
20567     * @attr ref android.R.styleable#View_textAlignment
20568     */
20569    @ViewDebug.ExportedProperty(category = "text", mapping = {
20570            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20571            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20572            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20573            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20574            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20575            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20576            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20577    })
20578    @TextAlignment
20579    public int getTextAlignment() {
20580        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20581                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20582    }
20583
20584    /**
20585     * Resolve the text alignment.
20586     *
20587     * @return true if resolution has been done, false otherwise.
20588     *
20589     * @hide
20590     */
20591    public boolean resolveTextAlignment() {
20592        // Reset any previous text alignment resolution
20593        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20594
20595        if (hasRtlSupport()) {
20596            // Set resolved text alignment flag depending on text alignment flag
20597            final int textAlignment = getRawTextAlignment();
20598            switch (textAlignment) {
20599                case TEXT_ALIGNMENT_INHERIT:
20600                    // Check if we can resolve the text alignment
20601                    if (!canResolveTextAlignment()) {
20602                        // We cannot do the resolution if there is no parent so use the default
20603                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20604                        // Resolution will need to happen again later
20605                        return false;
20606                    }
20607
20608                    // Parent has not yet resolved, so we still return the default
20609                    try {
20610                        if (!mParent.isTextAlignmentResolved()) {
20611                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20612                            // Resolution will need to happen again later
20613                            return false;
20614                        }
20615                    } catch (AbstractMethodError e) {
20616                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20617                                " does not fully implement ViewParent", e);
20618                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20619                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20620                        return true;
20621                    }
20622
20623                    int parentResolvedTextAlignment;
20624                    try {
20625                        parentResolvedTextAlignment = mParent.getTextAlignment();
20626                    } catch (AbstractMethodError e) {
20627                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20628                                " does not fully implement ViewParent", e);
20629                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20630                    }
20631                    switch (parentResolvedTextAlignment) {
20632                        case TEXT_ALIGNMENT_GRAVITY:
20633                        case TEXT_ALIGNMENT_TEXT_START:
20634                        case TEXT_ALIGNMENT_TEXT_END:
20635                        case TEXT_ALIGNMENT_CENTER:
20636                        case TEXT_ALIGNMENT_VIEW_START:
20637                        case TEXT_ALIGNMENT_VIEW_END:
20638                            // Resolved text alignment is the same as the parent resolved
20639                            // text alignment
20640                            mPrivateFlags2 |=
20641                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20642                            break;
20643                        default:
20644                            // Use default resolved text alignment
20645                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20646                    }
20647                    break;
20648                case TEXT_ALIGNMENT_GRAVITY:
20649                case TEXT_ALIGNMENT_TEXT_START:
20650                case TEXT_ALIGNMENT_TEXT_END:
20651                case TEXT_ALIGNMENT_CENTER:
20652                case TEXT_ALIGNMENT_VIEW_START:
20653                case TEXT_ALIGNMENT_VIEW_END:
20654                    // Resolved text alignment is the same as text alignment
20655                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20656                    break;
20657                default:
20658                    // Use default resolved text alignment
20659                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20660            }
20661        } else {
20662            // Use default resolved text alignment
20663            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20664        }
20665
20666        // Set the resolved
20667        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20668        return true;
20669    }
20670
20671    /**
20672     * Check if text alignment resolution can be done.
20673     *
20674     * @return true if text alignment resolution can be done otherwise return false.
20675     */
20676    public boolean canResolveTextAlignment() {
20677        switch (getRawTextAlignment()) {
20678            case TEXT_DIRECTION_INHERIT:
20679                if (mParent != null) {
20680                    try {
20681                        return mParent.canResolveTextAlignment();
20682                    } catch (AbstractMethodError e) {
20683                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20684                                " does not fully implement ViewParent", e);
20685                    }
20686                }
20687                return false;
20688
20689            default:
20690                return true;
20691        }
20692    }
20693
20694    /**
20695     * Reset resolved text alignment. Text alignment will be resolved during a call to
20696     * {@link #onMeasure(int, int)}.
20697     *
20698     * @hide
20699     */
20700    public void resetResolvedTextAlignment() {
20701        // Reset any previous text alignment resolution
20702        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20703        // Set to default
20704        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20705    }
20706
20707    /**
20708     * @return true if text alignment is inherited.
20709     *
20710     * @hide
20711     */
20712    public boolean isTextAlignmentInherited() {
20713        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
20714    }
20715
20716    /**
20717     * @return true if text alignment is resolved.
20718     */
20719    public boolean isTextAlignmentResolved() {
20720        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20721    }
20722
20723    /**
20724     * Generate a value suitable for use in {@link #setId(int)}.
20725     * This value will not collide with ID values generated at build time by aapt for R.id.
20726     *
20727     * @return a generated ID value
20728     */
20729    public static int generateViewId() {
20730        for (;;) {
20731            final int result = sNextGeneratedId.get();
20732            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
20733            int newValue = result + 1;
20734            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
20735            if (sNextGeneratedId.compareAndSet(result, newValue)) {
20736                return result;
20737            }
20738        }
20739    }
20740
20741    /**
20742     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
20743     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
20744     *                           a normal View or a ViewGroup with
20745     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
20746     * @hide
20747     */
20748    public void captureTransitioningViews(List<View> transitioningViews) {
20749        if (getVisibility() == View.VISIBLE) {
20750            transitioningViews.add(this);
20751        }
20752    }
20753
20754    /**
20755     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
20756     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
20757     * @hide
20758     */
20759    public void findNamedViews(Map<String, View> namedElements) {
20760        if (getVisibility() == VISIBLE || mGhostView != null) {
20761            String transitionName = getTransitionName();
20762            if (transitionName != null) {
20763                namedElements.put(transitionName, this);
20764            }
20765        }
20766    }
20767
20768    //
20769    // Properties
20770    //
20771    /**
20772     * A Property wrapper around the <code>alpha</code> functionality handled by the
20773     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
20774     */
20775    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
20776        @Override
20777        public void setValue(View object, float value) {
20778            object.setAlpha(value);
20779        }
20780
20781        @Override
20782        public Float get(View object) {
20783            return object.getAlpha();
20784        }
20785    };
20786
20787    /**
20788     * A Property wrapper around the <code>translationX</code> functionality handled by the
20789     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
20790     */
20791    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
20792        @Override
20793        public void setValue(View object, float value) {
20794            object.setTranslationX(value);
20795        }
20796
20797                @Override
20798        public Float get(View object) {
20799            return object.getTranslationX();
20800        }
20801    };
20802
20803    /**
20804     * A Property wrapper around the <code>translationY</code> functionality handled by the
20805     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
20806     */
20807    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
20808        @Override
20809        public void setValue(View object, float value) {
20810            object.setTranslationY(value);
20811        }
20812
20813        @Override
20814        public Float get(View object) {
20815            return object.getTranslationY();
20816        }
20817    };
20818
20819    /**
20820     * A Property wrapper around the <code>translationZ</code> functionality handled by the
20821     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
20822     */
20823    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
20824        @Override
20825        public void setValue(View object, float value) {
20826            object.setTranslationZ(value);
20827        }
20828
20829        @Override
20830        public Float get(View object) {
20831            return object.getTranslationZ();
20832        }
20833    };
20834
20835    /**
20836     * A Property wrapper around the <code>x</code> functionality handled by the
20837     * {@link View#setX(float)} and {@link View#getX()} methods.
20838     */
20839    public static final Property<View, Float> X = new FloatProperty<View>("x") {
20840        @Override
20841        public void setValue(View object, float value) {
20842            object.setX(value);
20843        }
20844
20845        @Override
20846        public Float get(View object) {
20847            return object.getX();
20848        }
20849    };
20850
20851    /**
20852     * A Property wrapper around the <code>y</code> functionality handled by the
20853     * {@link View#setY(float)} and {@link View#getY()} methods.
20854     */
20855    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
20856        @Override
20857        public void setValue(View object, float value) {
20858            object.setY(value);
20859        }
20860
20861        @Override
20862        public Float get(View object) {
20863            return object.getY();
20864        }
20865    };
20866
20867    /**
20868     * A Property wrapper around the <code>z</code> functionality handled by the
20869     * {@link View#setZ(float)} and {@link View#getZ()} methods.
20870     */
20871    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
20872        @Override
20873        public void setValue(View object, float value) {
20874            object.setZ(value);
20875        }
20876
20877        @Override
20878        public Float get(View object) {
20879            return object.getZ();
20880        }
20881    };
20882
20883    /**
20884     * A Property wrapper around the <code>rotation</code> functionality handled by the
20885     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
20886     */
20887    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
20888        @Override
20889        public void setValue(View object, float value) {
20890            object.setRotation(value);
20891        }
20892
20893        @Override
20894        public Float get(View object) {
20895            return object.getRotation();
20896        }
20897    };
20898
20899    /**
20900     * A Property wrapper around the <code>rotationX</code> functionality handled by the
20901     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
20902     */
20903    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
20904        @Override
20905        public void setValue(View object, float value) {
20906            object.setRotationX(value);
20907        }
20908
20909        @Override
20910        public Float get(View object) {
20911            return object.getRotationX();
20912        }
20913    };
20914
20915    /**
20916     * A Property wrapper around the <code>rotationY</code> functionality handled by the
20917     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
20918     */
20919    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
20920        @Override
20921        public void setValue(View object, float value) {
20922            object.setRotationY(value);
20923        }
20924
20925        @Override
20926        public Float get(View object) {
20927            return object.getRotationY();
20928        }
20929    };
20930
20931    /**
20932     * A Property wrapper around the <code>scaleX</code> functionality handled by the
20933     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
20934     */
20935    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
20936        @Override
20937        public void setValue(View object, float value) {
20938            object.setScaleX(value);
20939        }
20940
20941        @Override
20942        public Float get(View object) {
20943            return object.getScaleX();
20944        }
20945    };
20946
20947    /**
20948     * A Property wrapper around the <code>scaleY</code> functionality handled by the
20949     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
20950     */
20951    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
20952        @Override
20953        public void setValue(View object, float value) {
20954            object.setScaleY(value);
20955        }
20956
20957        @Override
20958        public Float get(View object) {
20959            return object.getScaleY();
20960        }
20961    };
20962
20963    /**
20964     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
20965     * Each MeasureSpec represents a requirement for either the width or the height.
20966     * A MeasureSpec is comprised of a size and a mode. There are three possible
20967     * modes:
20968     * <dl>
20969     * <dt>UNSPECIFIED</dt>
20970     * <dd>
20971     * The parent has not imposed any constraint on the child. It can be whatever size
20972     * it wants.
20973     * </dd>
20974     *
20975     * <dt>EXACTLY</dt>
20976     * <dd>
20977     * The parent has determined an exact size for the child. The child is going to be
20978     * given those bounds regardless of how big it wants to be.
20979     * </dd>
20980     *
20981     * <dt>AT_MOST</dt>
20982     * <dd>
20983     * The child can be as large as it wants up to the specified size.
20984     * </dd>
20985     * </dl>
20986     *
20987     * MeasureSpecs are implemented as ints to reduce object allocation. This class
20988     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
20989     */
20990    public static class MeasureSpec {
20991        private static final int MODE_SHIFT = 30;
20992        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
20993
20994        /**
20995         * Measure specification mode: The parent has not imposed any constraint
20996         * on the child. It can be whatever size it wants.
20997         */
20998        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
20999
21000        /**
21001         * Measure specification mode: The parent has determined an exact size
21002         * for the child. The child is going to be given those bounds regardless
21003         * of how big it wants to be.
21004         */
21005        public static final int EXACTLY     = 1 << MODE_SHIFT;
21006
21007        /**
21008         * Measure specification mode: The child can be as large as it wants up
21009         * to the specified size.
21010         */
21011        public static final int AT_MOST     = 2 << MODE_SHIFT;
21012
21013        /**
21014         * Creates a measure specification based on the supplied size and mode.
21015         *
21016         * The mode must always be one of the following:
21017         * <ul>
21018         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21019         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21020         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21021         * </ul>
21022         *
21023         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21024         * implementation was such that the order of arguments did not matter
21025         * and overflow in either value could impact the resulting MeasureSpec.
21026         * {@link android.widget.RelativeLayout} was affected by this bug.
21027         * Apps targeting API levels greater than 17 will get the fixed, more strict
21028         * behavior.</p>
21029         *
21030         * @param size the size of the measure specification
21031         * @param mode the mode of the measure specification
21032         * @return the measure specification based on size and mode
21033         */
21034        public static int makeMeasureSpec(int size, int mode) {
21035            if (sUseBrokenMakeMeasureSpec) {
21036                return size + mode;
21037            } else {
21038                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21039            }
21040        }
21041
21042        /**
21043         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21044         * will automatically get a size of 0. Older apps expect this.
21045         *
21046         * @hide internal use only for compatibility with system widgets and older apps
21047         */
21048        public static int makeSafeMeasureSpec(int size, int mode) {
21049            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21050                return 0;
21051            }
21052            return makeMeasureSpec(size, mode);
21053        }
21054
21055        /**
21056         * Extracts the mode from the supplied measure specification.
21057         *
21058         * @param measureSpec the measure specification to extract the mode from
21059         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21060         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21061         *         {@link android.view.View.MeasureSpec#EXACTLY}
21062         */
21063        public static int getMode(int measureSpec) {
21064            return (measureSpec & MODE_MASK);
21065        }
21066
21067        /**
21068         * Extracts the size from the supplied measure specification.
21069         *
21070         * @param measureSpec the measure specification to extract the size from
21071         * @return the size in pixels defined in the supplied measure specification
21072         */
21073        public static int getSize(int measureSpec) {
21074            return (measureSpec & ~MODE_MASK);
21075        }
21076
21077        static int adjust(int measureSpec, int delta) {
21078            final int mode = getMode(measureSpec);
21079            int size = getSize(measureSpec);
21080            if (mode == UNSPECIFIED) {
21081                // No need to adjust size for UNSPECIFIED mode.
21082                return makeMeasureSpec(size, UNSPECIFIED);
21083            }
21084            size += delta;
21085            if (size < 0) {
21086                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21087                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21088                size = 0;
21089            }
21090            return makeMeasureSpec(size, mode);
21091        }
21092
21093        /**
21094         * Returns a String representation of the specified measure
21095         * specification.
21096         *
21097         * @param measureSpec the measure specification to convert to a String
21098         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21099         */
21100        public static String toString(int measureSpec) {
21101            int mode = getMode(measureSpec);
21102            int size = getSize(measureSpec);
21103
21104            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21105
21106            if (mode == UNSPECIFIED)
21107                sb.append("UNSPECIFIED ");
21108            else if (mode == EXACTLY)
21109                sb.append("EXACTLY ");
21110            else if (mode == AT_MOST)
21111                sb.append("AT_MOST ");
21112            else
21113                sb.append(mode).append(" ");
21114
21115            sb.append(size);
21116            return sb.toString();
21117        }
21118    }
21119
21120    private final class CheckForLongPress implements Runnable {
21121        private int mOriginalWindowAttachCount;
21122
21123        @Override
21124        public void run() {
21125            if (isPressed() && (mParent != null)
21126                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21127                if (performLongClick()) {
21128                    mHasPerformedLongPress = true;
21129                }
21130            }
21131        }
21132
21133        public void rememberWindowAttachCount() {
21134            mOriginalWindowAttachCount = mWindowAttachCount;
21135        }
21136    }
21137
21138    private final class CheckForTap implements Runnable {
21139        public float x;
21140        public float y;
21141
21142        @Override
21143        public void run() {
21144            mPrivateFlags &= ~PFLAG_PREPRESSED;
21145            setPressed(true, x, y);
21146            checkForLongClick(ViewConfiguration.getTapTimeout());
21147        }
21148    }
21149
21150    private final class PerformClick implements Runnable {
21151        @Override
21152        public void run() {
21153            performClick();
21154        }
21155    }
21156
21157    /** @hide */
21158    public void hackTurnOffWindowResizeAnim(boolean off) {
21159        mAttachInfo.mTurnOffWindowResizeAnim = off;
21160    }
21161
21162    /**
21163     * This method returns a ViewPropertyAnimator object, which can be used to animate
21164     * specific properties on this View.
21165     *
21166     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21167     */
21168    public ViewPropertyAnimator animate() {
21169        if (mAnimator == null) {
21170            mAnimator = new ViewPropertyAnimator(this);
21171        }
21172        return mAnimator;
21173    }
21174
21175    /**
21176     * Sets the name of the View to be used to identify Views in Transitions.
21177     * Names should be unique in the View hierarchy.
21178     *
21179     * @param transitionName The name of the View to uniquely identify it for Transitions.
21180     */
21181    public final void setTransitionName(String transitionName) {
21182        mTransitionName = transitionName;
21183    }
21184
21185    /**
21186     * Returns the name of the View to be used to identify Views in Transitions.
21187     * Names should be unique in the View hierarchy.
21188     *
21189     * <p>This returns null if the View has not been given a name.</p>
21190     *
21191     * @return The name used of the View to be used to identify Views in Transitions or null
21192     * if no name has been given.
21193     */
21194    @ViewDebug.ExportedProperty
21195    public String getTransitionName() {
21196        return mTransitionName;
21197    }
21198
21199    /**
21200     * Interface definition for a callback to be invoked when a hardware key event is
21201     * dispatched to this view. The callback will be invoked before the key event is
21202     * given to the view. This is only useful for hardware keyboards; a software input
21203     * method has no obligation to trigger this listener.
21204     */
21205    public interface OnKeyListener {
21206        /**
21207         * Called when a hardware key is dispatched to a view. This allows listeners to
21208         * get a chance to respond before the target view.
21209         * <p>Key presses in software keyboards will generally NOT trigger this method,
21210         * although some may elect to do so in some situations. Do not assume a
21211         * software input method has to be key-based; even if it is, it may use key presses
21212         * in a different way than you expect, so there is no way to reliably catch soft
21213         * input key presses.
21214         *
21215         * @param v The view the key has been dispatched to.
21216         * @param keyCode The code for the physical key that was pressed
21217         * @param event The KeyEvent object containing full information about
21218         *        the event.
21219         * @return True if the listener has consumed the event, false otherwise.
21220         */
21221        boolean onKey(View v, int keyCode, KeyEvent event);
21222    }
21223
21224    /**
21225     * Interface definition for a callback to be invoked when a touch event is
21226     * dispatched to this view. The callback will be invoked before the touch
21227     * event is given to the view.
21228     */
21229    public interface OnTouchListener {
21230        /**
21231         * Called when a touch event is dispatched to a view. This allows listeners to
21232         * get a chance to respond before the target view.
21233         *
21234         * @param v The view the touch event has been dispatched to.
21235         * @param event The MotionEvent object containing full information about
21236         *        the event.
21237         * @return True if the listener has consumed the event, false otherwise.
21238         */
21239        boolean onTouch(View v, MotionEvent event);
21240    }
21241
21242    /**
21243     * Interface definition for a callback to be invoked when a hover event is
21244     * dispatched to this view. The callback will be invoked before the hover
21245     * event is given to the view.
21246     */
21247    public interface OnHoverListener {
21248        /**
21249         * Called when a hover event is dispatched to a view. This allows listeners to
21250         * get a chance to respond before the target view.
21251         *
21252         * @param v The view the hover event has been dispatched to.
21253         * @param event The MotionEvent object containing full information about
21254         *        the event.
21255         * @return True if the listener has consumed the event, false otherwise.
21256         */
21257        boolean onHover(View v, MotionEvent event);
21258    }
21259
21260    /**
21261     * Interface definition for a callback to be invoked when a generic motion event is
21262     * dispatched to this view. The callback will be invoked before the generic motion
21263     * event is given to the view.
21264     */
21265    public interface OnGenericMotionListener {
21266        /**
21267         * Called when a generic motion event is dispatched to a view. This allows listeners to
21268         * get a chance to respond before the target view.
21269         *
21270         * @param v The view the generic motion event has been dispatched to.
21271         * @param event The MotionEvent object containing full information about
21272         *        the event.
21273         * @return True if the listener has consumed the event, false otherwise.
21274         */
21275        boolean onGenericMotion(View v, MotionEvent event);
21276    }
21277
21278    /**
21279     * Interface definition for a callback to be invoked when a view has been clicked and held.
21280     */
21281    public interface OnLongClickListener {
21282        /**
21283         * Called when a view has been clicked and held.
21284         *
21285         * @param v The view that was clicked and held.
21286         *
21287         * @return true if the callback consumed the long click, false otherwise.
21288         */
21289        boolean onLongClick(View v);
21290    }
21291
21292    /**
21293     * Interface definition for a callback to be invoked when a drag is being dispatched
21294     * to this view.  The callback will be invoked before the hosting view's own
21295     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21296     * onDrag(event) behavior, it should return 'false' from this callback.
21297     *
21298     * <div class="special reference">
21299     * <h3>Developer Guides</h3>
21300     * <p>For a guide to implementing drag and drop features, read the
21301     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21302     * </div>
21303     */
21304    public interface OnDragListener {
21305        /**
21306         * Called when a drag event is dispatched to a view. This allows listeners
21307         * to get a chance to override base View behavior.
21308         *
21309         * @param v The View that received the drag event.
21310         * @param event The {@link android.view.DragEvent} object for the drag event.
21311         * @return {@code true} if the drag event was handled successfully, or {@code false}
21312         * if the drag event was not handled. Note that {@code false} will trigger the View
21313         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21314         */
21315        boolean onDrag(View v, DragEvent event);
21316    }
21317
21318    /**
21319     * Interface definition for a callback to be invoked when the focus state of
21320     * a view changed.
21321     */
21322    public interface OnFocusChangeListener {
21323        /**
21324         * Called when the focus state of a view has changed.
21325         *
21326         * @param v The view whose state has changed.
21327         * @param hasFocus The new focus state of v.
21328         */
21329        void onFocusChange(View v, boolean hasFocus);
21330    }
21331
21332    /**
21333     * Interface definition for a callback to be invoked when a view is clicked.
21334     */
21335    public interface OnClickListener {
21336        /**
21337         * Called when a view has been clicked.
21338         *
21339         * @param v The view that was clicked.
21340         */
21341        void onClick(View v);
21342    }
21343
21344    /**
21345     * Interface definition for a callback to be invoked when a view is context clicked.
21346     */
21347    public interface OnContextClickListener {
21348        /**
21349         * Called when a view is context clicked.
21350         *
21351         * @param v The view that has been context clicked.
21352         * @return true if the callback consumed the context click, false otherwise.
21353         */
21354        boolean onContextClick(View v);
21355    }
21356
21357    /**
21358     * Interface definition for a callback to be invoked when the context menu
21359     * for this view is being built.
21360     */
21361    public interface OnCreateContextMenuListener {
21362        /**
21363         * Called when the context menu for this view is being built. It is not
21364         * safe to hold onto the menu after this method returns.
21365         *
21366         * @param menu The context menu that is being built
21367         * @param v The view for which the context menu is being built
21368         * @param menuInfo Extra information about the item for which the
21369         *            context menu should be shown. This information will vary
21370         *            depending on the class of v.
21371         */
21372        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21373    }
21374
21375    /**
21376     * Interface definition for a callback to be invoked when the status bar changes
21377     * visibility.  This reports <strong>global</strong> changes to the system UI
21378     * state, not what the application is requesting.
21379     *
21380     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21381     */
21382    public interface OnSystemUiVisibilityChangeListener {
21383        /**
21384         * Called when the status bar changes visibility because of a call to
21385         * {@link View#setSystemUiVisibility(int)}.
21386         *
21387         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21388         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21389         * This tells you the <strong>global</strong> state of these UI visibility
21390         * flags, not what your app is currently applying.
21391         */
21392        public void onSystemUiVisibilityChange(int visibility);
21393    }
21394
21395    /**
21396     * Interface definition for a callback to be invoked when this view is attached
21397     * or detached from its window.
21398     */
21399    public interface OnAttachStateChangeListener {
21400        /**
21401         * Called when the view is attached to a window.
21402         * @param v The view that was attached
21403         */
21404        public void onViewAttachedToWindow(View v);
21405        /**
21406         * Called when the view is detached from a window.
21407         * @param v The view that was detached
21408         */
21409        public void onViewDetachedFromWindow(View v);
21410    }
21411
21412    /**
21413     * Listener for applying window insets on a view in a custom way.
21414     *
21415     * <p>Apps may choose to implement this interface if they want to apply custom policy
21416     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21417     * is set, its
21418     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21419     * method will be called instead of the View's own
21420     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21421     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21422     * the View's normal behavior as part of its own.</p>
21423     */
21424    public interface OnApplyWindowInsetsListener {
21425        /**
21426         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21427         * on a View, this listener method will be called instead of the view's own
21428         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21429         *
21430         * @param v The view applying window insets
21431         * @param insets The insets to apply
21432         * @return The insets supplied, minus any insets that were consumed
21433         */
21434        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21435    }
21436
21437    private final class UnsetPressedState implements Runnable {
21438        @Override
21439        public void run() {
21440            setPressed(false);
21441        }
21442    }
21443
21444    /**
21445     * Base class for derived classes that want to save and restore their own
21446     * state in {@link android.view.View#onSaveInstanceState()}.
21447     */
21448    public static class BaseSavedState extends AbsSavedState {
21449        String mStartActivityRequestWhoSaved;
21450
21451        /**
21452         * Constructor used when reading from a parcel. Reads the state of the superclass.
21453         *
21454         * @param source
21455         */
21456        public BaseSavedState(Parcel source) {
21457            super(source);
21458            mStartActivityRequestWhoSaved = source.readString();
21459        }
21460
21461        /**
21462         * Constructor called by derived classes when creating their SavedState objects
21463         *
21464         * @param superState The state of the superclass of this view
21465         */
21466        public BaseSavedState(Parcelable superState) {
21467            super(superState);
21468        }
21469
21470        @Override
21471        public void writeToParcel(Parcel out, int flags) {
21472            super.writeToParcel(out, flags);
21473            out.writeString(mStartActivityRequestWhoSaved);
21474        }
21475
21476        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21477                new Parcelable.Creator<BaseSavedState>() {
21478            public BaseSavedState createFromParcel(Parcel in) {
21479                return new BaseSavedState(in);
21480            }
21481
21482            public BaseSavedState[] newArray(int size) {
21483                return new BaseSavedState[size];
21484            }
21485        };
21486    }
21487
21488    /**
21489     * A set of information given to a view when it is attached to its parent
21490     * window.
21491     */
21492    final static class AttachInfo {
21493        interface Callbacks {
21494            void playSoundEffect(int effectId);
21495            boolean performHapticFeedback(int effectId, boolean always);
21496        }
21497
21498        /**
21499         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21500         * to a Handler. This class contains the target (View) to invalidate and
21501         * the coordinates of the dirty rectangle.
21502         *
21503         * For performance purposes, this class also implements a pool of up to
21504         * POOL_LIMIT objects that get reused. This reduces memory allocations
21505         * whenever possible.
21506         */
21507        static class InvalidateInfo {
21508            private static final int POOL_LIMIT = 10;
21509
21510            private static final SynchronizedPool<InvalidateInfo> sPool =
21511                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21512
21513            View target;
21514
21515            int left;
21516            int top;
21517            int right;
21518            int bottom;
21519
21520            public static InvalidateInfo obtain() {
21521                InvalidateInfo instance = sPool.acquire();
21522                return (instance != null) ? instance : new InvalidateInfo();
21523            }
21524
21525            public void recycle() {
21526                target = null;
21527                sPool.release(this);
21528            }
21529        }
21530
21531        final IWindowSession mSession;
21532
21533        final IWindow mWindow;
21534
21535        final IBinder mWindowToken;
21536
21537        final Display mDisplay;
21538
21539        final Callbacks mRootCallbacks;
21540
21541        IWindowId mIWindowId;
21542        WindowId mWindowId;
21543
21544        /**
21545         * The top view of the hierarchy.
21546         */
21547        View mRootView;
21548
21549        IBinder mPanelParentWindowToken;
21550
21551        boolean mHardwareAccelerated;
21552        boolean mHardwareAccelerationRequested;
21553        HardwareRenderer mHardwareRenderer;
21554        List<RenderNode> mPendingAnimatingRenderNodes;
21555
21556        /**
21557         * The state of the display to which the window is attached, as reported
21558         * by {@link Display#getState()}.  Note that the display state constants
21559         * declared by {@link Display} do not exactly line up with the screen state
21560         * constants declared by {@link View} (there are more display states than
21561         * screen states).
21562         */
21563        int mDisplayState = Display.STATE_UNKNOWN;
21564
21565        /**
21566         * Scale factor used by the compatibility mode
21567         */
21568        float mApplicationScale;
21569
21570        /**
21571         * Indicates whether the application is in compatibility mode
21572         */
21573        boolean mScalingRequired;
21574
21575        /**
21576         * If set, ViewRootImpl doesn't use its lame animation for when the window resizes.
21577         */
21578        boolean mTurnOffWindowResizeAnim;
21579
21580        /**
21581         * Left position of this view's window
21582         */
21583        int mWindowLeft;
21584
21585        /**
21586         * Top position of this view's window
21587         */
21588        int mWindowTop;
21589
21590        /**
21591         * Indicates whether views need to use 32-bit drawing caches
21592         */
21593        boolean mUse32BitDrawingCache;
21594
21595        /**
21596         * For windows that are full-screen but using insets to layout inside
21597         * of the screen areas, these are the current insets to appear inside
21598         * the overscan area of the display.
21599         */
21600        final Rect mOverscanInsets = new Rect();
21601
21602        /**
21603         * For windows that are full-screen but using insets to layout inside
21604         * of the screen decorations, these are the current insets for the
21605         * content of the window.
21606         */
21607        final Rect mContentInsets = new Rect();
21608
21609        /**
21610         * For windows that are full-screen but using insets to layout inside
21611         * of the screen decorations, these are the current insets for the
21612         * actual visible parts of the window.
21613         */
21614        final Rect mVisibleInsets = new Rect();
21615
21616        /**
21617         * For windows that are full-screen but using insets to layout inside
21618         * of the screen decorations, these are the current insets for the
21619         * stable system windows.
21620         */
21621        final Rect mStableInsets = new Rect();
21622
21623        /**
21624         * For windows that include areas that are not covered by real surface these are the outsets
21625         * for real surface.
21626         */
21627        final Rect mOutsets = new Rect();
21628
21629        /**
21630         * The internal insets given by this window.  This value is
21631         * supplied by the client (through
21632         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21633         * be given to the window manager when changed to be used in laying
21634         * out windows behind it.
21635         */
21636        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21637                = new ViewTreeObserver.InternalInsetsInfo();
21638
21639        /**
21640         * Set to true when mGivenInternalInsets is non-empty.
21641         */
21642        boolean mHasNonEmptyGivenInternalInsets;
21643
21644        /**
21645         * All views in the window's hierarchy that serve as scroll containers,
21646         * used to determine if the window can be resized or must be panned
21647         * to adjust for a soft input area.
21648         */
21649        final ArrayList<View> mScrollContainers = new ArrayList<View>();
21650
21651        final KeyEvent.DispatcherState mKeyDispatchState
21652                = new KeyEvent.DispatcherState();
21653
21654        /**
21655         * Indicates whether the view's window currently has the focus.
21656         */
21657        boolean mHasWindowFocus;
21658
21659        /**
21660         * The current visibility of the window.
21661         */
21662        int mWindowVisibility;
21663
21664        /**
21665         * Indicates the time at which drawing started to occur.
21666         */
21667        long mDrawingTime;
21668
21669        /**
21670         * Indicates whether or not ignoring the DIRTY_MASK flags.
21671         */
21672        boolean mIgnoreDirtyState;
21673
21674        /**
21675         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
21676         * to avoid clearing that flag prematurely.
21677         */
21678        boolean mSetIgnoreDirtyState = false;
21679
21680        /**
21681         * Indicates whether the view's window is currently in touch mode.
21682         */
21683        boolean mInTouchMode;
21684
21685        /**
21686         * Indicates whether the view has requested unbuffered input dispatching for the current
21687         * event stream.
21688         */
21689        boolean mUnbufferedDispatchRequested;
21690
21691        /**
21692         * Indicates that ViewAncestor should trigger a global layout change
21693         * the next time it performs a traversal
21694         */
21695        boolean mRecomputeGlobalAttributes;
21696
21697        /**
21698         * Always report new attributes at next traversal.
21699         */
21700        boolean mForceReportNewAttributes;
21701
21702        /**
21703         * Set during a traveral if any views want to keep the screen on.
21704         */
21705        boolean mKeepScreenOn;
21706
21707        /**
21708         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
21709         */
21710        int mSystemUiVisibility;
21711
21712        /**
21713         * Hack to force certain system UI visibility flags to be cleared.
21714         */
21715        int mDisabledSystemUiVisibility;
21716
21717        /**
21718         * Last global system UI visibility reported by the window manager.
21719         */
21720        int mGlobalSystemUiVisibility;
21721
21722        /**
21723         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
21724         * attached.
21725         */
21726        boolean mHasSystemUiListeners;
21727
21728        /**
21729         * Set if the window has requested to extend into the overscan region
21730         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
21731         */
21732        boolean mOverscanRequested;
21733
21734        /**
21735         * Set if the visibility of any views has changed.
21736         */
21737        boolean mViewVisibilityChanged;
21738
21739        /**
21740         * Set to true if a view has been scrolled.
21741         */
21742        boolean mViewScrollChanged;
21743
21744        /**
21745         * Set to true if high contrast mode enabled
21746         */
21747        boolean mHighContrastText;
21748
21749        /**
21750         * Global to the view hierarchy used as a temporary for dealing with
21751         * x/y points in the transparent region computations.
21752         */
21753        final int[] mTransparentLocation = new int[2];
21754
21755        /**
21756         * Global to the view hierarchy used as a temporary for dealing with
21757         * x/y points in the ViewGroup.invalidateChild implementation.
21758         */
21759        final int[] mInvalidateChildLocation = new int[2];
21760
21761        /**
21762         * Global to the view hierarchy used as a temporary for dealng with
21763         * computing absolute on-screen location.
21764         */
21765        final int[] mTmpLocation = new int[2];
21766
21767        /**
21768         * Global to the view hierarchy used as a temporary for dealing with
21769         * x/y location when view is transformed.
21770         */
21771        final float[] mTmpTransformLocation = new float[2];
21772
21773        /**
21774         * The view tree observer used to dispatch global events like
21775         * layout, pre-draw, touch mode change, etc.
21776         */
21777        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
21778
21779        /**
21780         * A Canvas used by the view hierarchy to perform bitmap caching.
21781         */
21782        Canvas mCanvas;
21783
21784        /**
21785         * The view root impl.
21786         */
21787        final ViewRootImpl mViewRootImpl;
21788
21789        /**
21790         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
21791         * handler can be used to pump events in the UI events queue.
21792         */
21793        final Handler mHandler;
21794
21795        /**
21796         * Temporary for use in computing invalidate rectangles while
21797         * calling up the hierarchy.
21798         */
21799        final Rect mTmpInvalRect = new Rect();
21800
21801        /**
21802         * Temporary for use in computing hit areas with transformed views
21803         */
21804        final RectF mTmpTransformRect = new RectF();
21805
21806        /**
21807         * Temporary for use in computing hit areas with transformed views
21808         */
21809        final RectF mTmpTransformRect1 = new RectF();
21810
21811        /**
21812         * Temporary list of rectanges.
21813         */
21814        final List<RectF> mTmpRectList = new ArrayList<>();
21815
21816        /**
21817         * Temporary for use in transforming invalidation rect
21818         */
21819        final Matrix mTmpMatrix = new Matrix();
21820
21821        /**
21822         * Temporary for use in transforming invalidation rect
21823         */
21824        final Transformation mTmpTransformation = new Transformation();
21825
21826        /**
21827         * Temporary for use in querying outlines from OutlineProviders
21828         */
21829        final Outline mTmpOutline = new Outline();
21830
21831        /**
21832         * Temporary list for use in collecting focusable descendents of a view.
21833         */
21834        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
21835
21836        /**
21837         * The id of the window for accessibility purposes.
21838         */
21839        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
21840
21841        /**
21842         * Flags related to accessibility processing.
21843         *
21844         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
21845         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
21846         */
21847        int mAccessibilityFetchFlags;
21848
21849        /**
21850         * The drawable for highlighting accessibility focus.
21851         */
21852        Drawable mAccessibilityFocusDrawable;
21853
21854        /**
21855         * Show where the margins, bounds and layout bounds are for each view.
21856         */
21857        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
21858
21859        /**
21860         * Point used to compute visible regions.
21861         */
21862        final Point mPoint = new Point();
21863
21864        /**
21865         * Used to track which View originated a requestLayout() call, used when
21866         * requestLayout() is called during layout.
21867         */
21868        View mViewRequestingLayout;
21869
21870        /**
21871         * Creates a new set of attachment information with the specified
21872         * events handler and thread.
21873         *
21874         * @param handler the events handler the view must use
21875         */
21876        AttachInfo(IWindowSession session, IWindow window, Display display,
21877                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
21878            mSession = session;
21879            mWindow = window;
21880            mWindowToken = window.asBinder();
21881            mDisplay = display;
21882            mViewRootImpl = viewRootImpl;
21883            mHandler = handler;
21884            mRootCallbacks = effectPlayer;
21885        }
21886    }
21887
21888    /**
21889     * <p>ScrollabilityCache holds various fields used by a View when scrolling
21890     * is supported. This avoids keeping too many unused fields in most
21891     * instances of View.</p>
21892     */
21893    private static class ScrollabilityCache implements Runnable {
21894
21895        /**
21896         * Scrollbars are not visible
21897         */
21898        public static final int OFF = 0;
21899
21900        /**
21901         * Scrollbars are visible
21902         */
21903        public static final int ON = 1;
21904
21905        /**
21906         * Scrollbars are fading away
21907         */
21908        public static final int FADING = 2;
21909
21910        public boolean fadeScrollBars;
21911
21912        public int fadingEdgeLength;
21913        public int scrollBarDefaultDelayBeforeFade;
21914        public int scrollBarFadeDuration;
21915
21916        public int scrollBarSize;
21917        public ScrollBarDrawable scrollBar;
21918        public float[] interpolatorValues;
21919        public View host;
21920
21921        public final Paint paint;
21922        public final Matrix matrix;
21923        public Shader shader;
21924
21925        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
21926
21927        private static final float[] OPAQUE = { 255 };
21928        private static final float[] TRANSPARENT = { 0.0f };
21929
21930        /**
21931         * When fading should start. This time moves into the future every time
21932         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
21933         */
21934        public long fadeStartTime;
21935
21936
21937        /**
21938         * The current state of the scrollbars: ON, OFF, or FADING
21939         */
21940        public int state = OFF;
21941
21942        private int mLastColor;
21943
21944        public ScrollabilityCache(ViewConfiguration configuration, View host) {
21945            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
21946            scrollBarSize = configuration.getScaledScrollBarSize();
21947            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
21948            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
21949
21950            paint = new Paint();
21951            matrix = new Matrix();
21952            // use use a height of 1, and then wack the matrix each time we
21953            // actually use it.
21954            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21955            paint.setShader(shader);
21956            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21957
21958            this.host = host;
21959        }
21960
21961        public void setFadeColor(int color) {
21962            if (color != mLastColor) {
21963                mLastColor = color;
21964
21965                if (color != 0) {
21966                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
21967                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
21968                    paint.setShader(shader);
21969                    // Restore the default transfer mode (src_over)
21970                    paint.setXfermode(null);
21971                } else {
21972                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
21973                    paint.setShader(shader);
21974                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
21975                }
21976            }
21977        }
21978
21979        public void run() {
21980            long now = AnimationUtils.currentAnimationTimeMillis();
21981            if (now >= fadeStartTime) {
21982
21983                // the animation fades the scrollbars out by changing
21984                // the opacity (alpha) from fully opaque to fully
21985                // transparent
21986                int nextFrame = (int) now;
21987                int framesCount = 0;
21988
21989                Interpolator interpolator = scrollBarInterpolator;
21990
21991                // Start opaque
21992                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
21993
21994                // End transparent
21995                nextFrame += scrollBarFadeDuration;
21996                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
21997
21998                state = FADING;
21999
22000                // Kick off the fade animation
22001                host.invalidate(true);
22002            }
22003        }
22004    }
22005
22006    /**
22007     * Resuable callback for sending
22008     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22009     */
22010    private class SendViewScrolledAccessibilityEvent implements Runnable {
22011        public volatile boolean mIsPending;
22012
22013        public void run() {
22014            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22015            mIsPending = false;
22016        }
22017    }
22018
22019    /**
22020     * <p>
22021     * This class represents a delegate that can be registered in a {@link View}
22022     * to enhance accessibility support via composition rather via inheritance.
22023     * It is specifically targeted to widget developers that extend basic View
22024     * classes i.e. classes in package android.view, that would like their
22025     * applications to be backwards compatible.
22026     * </p>
22027     * <div class="special reference">
22028     * <h3>Developer Guides</h3>
22029     * <p>For more information about making applications accessible, read the
22030     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22031     * developer guide.</p>
22032     * </div>
22033     * <p>
22034     * A scenario in which a developer would like to use an accessibility delegate
22035     * is overriding a method introduced in a later API version then the minimal API
22036     * version supported by the application. For example, the method
22037     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22038     * in API version 4 when the accessibility APIs were first introduced. If a
22039     * developer would like his application to run on API version 4 devices (assuming
22040     * all other APIs used by the application are version 4 or lower) and take advantage
22041     * of this method, instead of overriding the method which would break the application's
22042     * backwards compatibility, he can override the corresponding method in this
22043     * delegate and register the delegate in the target View if the API version of
22044     * the system is high enough i.e. the API version is same or higher to the API
22045     * version that introduced
22046     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22047     * </p>
22048     * <p>
22049     * Here is an example implementation:
22050     * </p>
22051     * <code><pre><p>
22052     * if (Build.VERSION.SDK_INT >= 14) {
22053     *     // If the API version is equal of higher than the version in
22054     *     // which onInitializeAccessibilityNodeInfo was introduced we
22055     *     // register a delegate with a customized implementation.
22056     *     View view = findViewById(R.id.view_id);
22057     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22058     *         public void onInitializeAccessibilityNodeInfo(View host,
22059     *                 AccessibilityNodeInfo info) {
22060     *             // Let the default implementation populate the info.
22061     *             super.onInitializeAccessibilityNodeInfo(host, info);
22062     *             // Set some other information.
22063     *             info.setEnabled(host.isEnabled());
22064     *         }
22065     *     });
22066     * }
22067     * </code></pre></p>
22068     * <p>
22069     * This delegate contains methods that correspond to the accessibility methods
22070     * in View. If a delegate has been specified the implementation in View hands
22071     * off handling to the corresponding method in this delegate. The default
22072     * implementation the delegate methods behaves exactly as the corresponding
22073     * method in View for the case of no accessibility delegate been set. Hence,
22074     * to customize the behavior of a View method, clients can override only the
22075     * corresponding delegate method without altering the behavior of the rest
22076     * accessibility related methods of the host view.
22077     * </p>
22078     */
22079    public static class AccessibilityDelegate {
22080
22081        /**
22082         * Sends an accessibility event of the given type. If accessibility is not
22083         * enabled this method has no effect.
22084         * <p>
22085         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22086         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22087         * been set.
22088         * </p>
22089         *
22090         * @param host The View hosting the delegate.
22091         * @param eventType The type of the event to send.
22092         *
22093         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22094         */
22095        public void sendAccessibilityEvent(View host, int eventType) {
22096            host.sendAccessibilityEventInternal(eventType);
22097        }
22098
22099        /**
22100         * Performs the specified accessibility action on the view. For
22101         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22102         * <p>
22103         * The default implementation behaves as
22104         * {@link View#performAccessibilityAction(int, Bundle)
22105         *  View#performAccessibilityAction(int, Bundle)} for the case of
22106         *  no accessibility delegate been set.
22107         * </p>
22108         *
22109         * @param action The action to perform.
22110         * @return Whether the action was performed.
22111         *
22112         * @see View#performAccessibilityAction(int, Bundle)
22113         *      View#performAccessibilityAction(int, Bundle)
22114         */
22115        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22116            return host.performAccessibilityActionInternal(action, args);
22117        }
22118
22119        /**
22120         * Sends an accessibility event. This method behaves exactly as
22121         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22122         * empty {@link AccessibilityEvent} and does not perform a check whether
22123         * accessibility is enabled.
22124         * <p>
22125         * The default implementation behaves as
22126         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22127         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22128         * the case of no accessibility delegate been set.
22129         * </p>
22130         *
22131         * @param host The View hosting the delegate.
22132         * @param event The event to send.
22133         *
22134         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22135         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22136         */
22137        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22138            host.sendAccessibilityEventUncheckedInternal(event);
22139        }
22140
22141        /**
22142         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22143         * to its children for adding their text content to the event.
22144         * <p>
22145         * The default implementation behaves as
22146         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22147         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22148         * the case of no accessibility delegate been set.
22149         * </p>
22150         *
22151         * @param host The View hosting the delegate.
22152         * @param event The event.
22153         * @return True if the event population was completed.
22154         *
22155         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22156         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22157         */
22158        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22159            return host.dispatchPopulateAccessibilityEventInternal(event);
22160        }
22161
22162        /**
22163         * Gives a chance to the host View to populate the accessibility event with its
22164         * text content.
22165         * <p>
22166         * The default implementation behaves as
22167         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22168         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22169         * the case of no accessibility delegate been set.
22170         * </p>
22171         *
22172         * @param host The View hosting the delegate.
22173         * @param event The accessibility event which to populate.
22174         *
22175         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22176         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22177         */
22178        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22179            host.onPopulateAccessibilityEventInternal(event);
22180        }
22181
22182        /**
22183         * Initializes an {@link AccessibilityEvent} with information about the
22184         * the host View which is the event source.
22185         * <p>
22186         * The default implementation behaves as
22187         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22188         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22189         * the case of no accessibility delegate been set.
22190         * </p>
22191         *
22192         * @param host The View hosting the delegate.
22193         * @param event The event to initialize.
22194         *
22195         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22196         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22197         */
22198        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22199            host.onInitializeAccessibilityEventInternal(event);
22200        }
22201
22202        /**
22203         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22204         * <p>
22205         * The default implementation behaves as
22206         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22207         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22208         * the case of no accessibility delegate been set.
22209         * </p>
22210         *
22211         * @param host The View hosting the delegate.
22212         * @param info The instance to initialize.
22213         *
22214         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22215         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22216         */
22217        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22218            host.onInitializeAccessibilityNodeInfoInternal(info);
22219        }
22220
22221        /**
22222         * Called when a child of the host View has requested sending an
22223         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22224         * to augment the event.
22225         * <p>
22226         * The default implementation behaves as
22227         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22228         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22229         * the case of no accessibility delegate been set.
22230         * </p>
22231         *
22232         * @param host The View hosting the delegate.
22233         * @param child The child which requests sending the event.
22234         * @param event The event to be sent.
22235         * @return True if the event should be sent
22236         *
22237         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22238         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22239         */
22240        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22241                AccessibilityEvent event) {
22242            return host.onRequestSendAccessibilityEventInternal(child, event);
22243        }
22244
22245        /**
22246         * Gets the provider for managing a virtual view hierarchy rooted at this View
22247         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22248         * that explore the window content.
22249         * <p>
22250         * The default implementation behaves as
22251         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22252         * the case of no accessibility delegate been set.
22253         * </p>
22254         *
22255         * @return The provider.
22256         *
22257         * @see AccessibilityNodeProvider
22258         */
22259        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22260            return null;
22261        }
22262
22263        /**
22264         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22265         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22266         * This method is responsible for obtaining an accessibility node info from a
22267         * pool of reusable instances and calling
22268         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22269         * view to initialize the former.
22270         * <p>
22271         * <strong>Note:</strong> The client is responsible for recycling the obtained
22272         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22273         * creation.
22274         * </p>
22275         * <p>
22276         * The default implementation behaves as
22277         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22278         * the case of no accessibility delegate been set.
22279         * </p>
22280         * @return A populated {@link AccessibilityNodeInfo}.
22281         *
22282         * @see AccessibilityNodeInfo
22283         *
22284         * @hide
22285         */
22286        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22287            return host.createAccessibilityNodeInfoInternal();
22288        }
22289    }
22290
22291    private class MatchIdPredicate implements Predicate<View> {
22292        public int mId;
22293
22294        @Override
22295        public boolean apply(View view) {
22296            return (view.mID == mId);
22297        }
22298    }
22299
22300    private class MatchLabelForPredicate implements Predicate<View> {
22301        private int mLabeledId;
22302
22303        @Override
22304        public boolean apply(View view) {
22305            return (view.mLabelForId == mLabeledId);
22306        }
22307    }
22308
22309    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22310        private int mChangeTypes = 0;
22311        private boolean mPosted;
22312        private boolean mPostedWithDelay;
22313        private long mLastEventTimeMillis;
22314
22315        @Override
22316        public void run() {
22317            mPosted = false;
22318            mPostedWithDelay = false;
22319            mLastEventTimeMillis = SystemClock.uptimeMillis();
22320            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22321                final AccessibilityEvent event = AccessibilityEvent.obtain();
22322                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22323                event.setContentChangeTypes(mChangeTypes);
22324                sendAccessibilityEventUnchecked(event);
22325            }
22326            mChangeTypes = 0;
22327        }
22328
22329        public void runOrPost(int changeType) {
22330            mChangeTypes |= changeType;
22331
22332            // If this is a live region or the child of a live region, collect
22333            // all events from this frame and send them on the next frame.
22334            if (inLiveRegion()) {
22335                // If we're already posted with a delay, remove that.
22336                if (mPostedWithDelay) {
22337                    removeCallbacks(this);
22338                    mPostedWithDelay = false;
22339                }
22340                // Only post if we're not already posted.
22341                if (!mPosted) {
22342                    post(this);
22343                    mPosted = true;
22344                }
22345                return;
22346            }
22347
22348            if (mPosted) {
22349                return;
22350            }
22351
22352            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22353            final long minEventIntevalMillis =
22354                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22355            if (timeSinceLastMillis >= minEventIntevalMillis) {
22356                removeCallbacks(this);
22357                run();
22358            } else {
22359                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22360                mPostedWithDelay = true;
22361            }
22362        }
22363    }
22364
22365    private boolean inLiveRegion() {
22366        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22367            return true;
22368        }
22369
22370        ViewParent parent = getParent();
22371        while (parent instanceof View) {
22372            if (((View) parent).getAccessibilityLiveRegion()
22373                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22374                return true;
22375            }
22376            parent = parent.getParent();
22377        }
22378
22379        return false;
22380    }
22381
22382    /**
22383     * Dump all private flags in readable format, useful for documentation and
22384     * sanity checking.
22385     */
22386    private static void dumpFlags() {
22387        final HashMap<String, String> found = Maps.newHashMap();
22388        try {
22389            for (Field field : View.class.getDeclaredFields()) {
22390                final int modifiers = field.getModifiers();
22391                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22392                    if (field.getType().equals(int.class)) {
22393                        final int value = field.getInt(null);
22394                        dumpFlag(found, field.getName(), value);
22395                    } else if (field.getType().equals(int[].class)) {
22396                        final int[] values = (int[]) field.get(null);
22397                        for (int i = 0; i < values.length; i++) {
22398                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22399                        }
22400                    }
22401                }
22402            }
22403        } catch (IllegalAccessException e) {
22404            throw new RuntimeException(e);
22405        }
22406
22407        final ArrayList<String> keys = Lists.newArrayList();
22408        keys.addAll(found.keySet());
22409        Collections.sort(keys);
22410        for (String key : keys) {
22411            Log.d(VIEW_LOG_TAG, found.get(key));
22412        }
22413    }
22414
22415    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22416        // Sort flags by prefix, then by bits, always keeping unique keys
22417        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22418        final int prefix = name.indexOf('_');
22419        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22420        final String output = bits + " " + name;
22421        found.put(key, output);
22422    }
22423
22424    /** {@hide} */
22425    public void encode(@NonNull ViewHierarchyEncoder stream) {
22426        stream.beginObject(this);
22427        encodeProperties(stream);
22428        stream.endObject();
22429    }
22430
22431    /** {@hide} */
22432    @CallSuper
22433    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22434        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22435        if (resolveId instanceof String) {
22436            stream.addProperty("id", (String) resolveId);
22437        } else {
22438            stream.addProperty("id", mID);
22439        }
22440
22441        stream.addProperty("misc:transformation.alpha",
22442                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22443        stream.addProperty("misc:transitionName", getTransitionName());
22444
22445        // layout
22446        stream.addProperty("layout:left", mLeft);
22447        stream.addProperty("layout:right", mRight);
22448        stream.addProperty("layout:top", mTop);
22449        stream.addProperty("layout:bottom", mBottom);
22450        stream.addProperty("layout:width", getWidth());
22451        stream.addProperty("layout:height", getHeight());
22452        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22453        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22454        stream.addProperty("layout:hasTransientState", hasTransientState());
22455        stream.addProperty("layout:baseline", getBaseline());
22456
22457        // layout params
22458        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22459        if (layoutParams != null) {
22460            stream.addPropertyKey("layoutParams");
22461            layoutParams.encode(stream);
22462        }
22463
22464        // scrolling
22465        stream.addProperty("scrolling:scrollX", mScrollX);
22466        stream.addProperty("scrolling:scrollY", mScrollY);
22467
22468        // padding
22469        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22470        stream.addProperty("padding:paddingRight", mPaddingRight);
22471        stream.addProperty("padding:paddingTop", mPaddingTop);
22472        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22473        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22474        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22475        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22476        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22477        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22478
22479        // measurement
22480        stream.addProperty("measurement:minHeight", mMinHeight);
22481        stream.addProperty("measurement:minWidth", mMinWidth);
22482        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22483        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22484
22485        // drawing
22486        stream.addProperty("drawing:elevation", getElevation());
22487        stream.addProperty("drawing:translationX", getTranslationX());
22488        stream.addProperty("drawing:translationY", getTranslationY());
22489        stream.addProperty("drawing:translationZ", getTranslationZ());
22490        stream.addProperty("drawing:rotation", getRotation());
22491        stream.addProperty("drawing:rotationX", getRotationX());
22492        stream.addProperty("drawing:rotationY", getRotationY());
22493        stream.addProperty("drawing:scaleX", getScaleX());
22494        stream.addProperty("drawing:scaleY", getScaleY());
22495        stream.addProperty("drawing:pivotX", getPivotX());
22496        stream.addProperty("drawing:pivotY", getPivotY());
22497        stream.addProperty("drawing:opaque", isOpaque());
22498        stream.addProperty("drawing:alpha", getAlpha());
22499        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22500        stream.addProperty("drawing:shadow", hasShadow());
22501        stream.addProperty("drawing:solidColor", getSolidColor());
22502        stream.addProperty("drawing:layerType", mLayerType);
22503        stream.addProperty("drawing:willNotDraw", willNotDraw());
22504        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22505        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22506        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22507        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22508
22509        // focus
22510        stream.addProperty("focus:hasFocus", hasFocus());
22511        stream.addProperty("focus:isFocused", isFocused());
22512        stream.addProperty("focus:isFocusable", isFocusable());
22513        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22514
22515        stream.addProperty("misc:clickable", isClickable());
22516        stream.addProperty("misc:pressed", isPressed());
22517        stream.addProperty("misc:selected", isSelected());
22518        stream.addProperty("misc:touchMode", isInTouchMode());
22519        stream.addProperty("misc:hovered", isHovered());
22520        stream.addProperty("misc:activated", isActivated());
22521
22522        stream.addProperty("misc:visibility", getVisibility());
22523        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22524        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22525
22526        stream.addProperty("misc:enabled", isEnabled());
22527        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22528        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22529
22530        // theme attributes
22531        Resources.Theme theme = getContext().getTheme();
22532        if (theme != null) {
22533            stream.addPropertyKey("theme");
22534            theme.encode(stream);
22535        }
22536
22537        // view attribute information
22538        int n = mAttributes != null ? mAttributes.length : 0;
22539        stream.addProperty("meta:__attrCount__", n/2);
22540        for (int i = 0; i < n; i += 2) {
22541            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22542        }
22543
22544        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22545
22546        // text
22547        stream.addProperty("text:textDirection", getTextDirection());
22548        stream.addProperty("text:textAlignment", getTextAlignment());
22549
22550        // accessibility
22551        CharSequence contentDescription = getContentDescription();
22552        stream.addProperty("accessibility:contentDescription",
22553                contentDescription == null ? "" : contentDescription.toString());
22554        stream.addProperty("accessibility:labelFor", getLabelFor());
22555        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22556    }
22557}
22558