View.java revision c45b1d4ae4afa52f292df2bf1b09a5691eef1cfa
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 * <p>
580 * Tags may be specified with character sequence values in layout XML as either
581 * a single tag using the {@link android.R.styleable#View_tag android:tag}
582 * attribute or multiple tags using the {@code &lt;tag&gt;} child element:
583 * <pre>
584 *     &ltView ...
585 *           android:tag="@string/mytag_value" /&gt;
586 *     &ltView ...&gt;
587 *         &lttag android:id="@+id/mytag"
588 *              android:value="@string/mytag_value" /&gt;
589 *     &lt/View>
590 * </pre>
591 * </p>
592 * <p>
593 * Tags may also be specified with arbitrary objects from code using
594 * {@link #setTag(Object)} or {@link #setTag(int, Object)}.
595 * </p>
596 *
597 * <a name="Themes"></a>
598 * <h3>Themes</h3>
599 * <p>
600 * By default, Views are created using the theme of the Context object supplied
601 * to their constructor; however, a different theme may be specified by using
602 * the {@link android.R.styleable#View_theme android:theme} attribute in layout
603 * XML or by passing a {@link ContextThemeWrapper} to the constructor from
604 * code.
605 * </p>
606 * <p>
607 * When the {@link android.R.styleable#View_theme android:theme} attribute is
608 * used in XML, the specified theme is applied on top of the inflation
609 * context's theme (see {@link LayoutInflater}) and used for the view itself as
610 * well as any child elements.
611 * </p>
612 * <p>
613 * In the following example, both views will be created using the Material dark
614 * color scheme; however, because an overlay theme is used which only defines a
615 * subset of attributes, the value of
616 * {@link android.R.styleable#Theme_colorAccent android:colorAccent} defined on
617 * the inflation context's theme (e.g. the Activity theme) will be preserved.
618 * <pre>
619 *     &ltLinearLayout
620 *             ...
621 *             android:theme="@android:theme/ThemeOverlay.Material.Dark"&gt;
622 *         &ltView ...&gt;
623 *     &lt/LinearLayout&gt;
624 * </pre>
625 * </p>
626 *
627 * <a name="Properties"></a>
628 * <h3>Properties</h3>
629 * <p>
630 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
631 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
632 * available both in the {@link Property} form as well as in similarly-named setter/getter
633 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
634 * be used to set persistent state associated with these rendering-related properties on the view.
635 * The properties and methods can also be used in conjunction with
636 * {@link android.animation.Animator Animator}-based animations, described more in the
637 * <a href="#Animation">Animation</a> section.
638 * </p>
639 *
640 * <a name="Animation"></a>
641 * <h3>Animation</h3>
642 * <p>
643 * Starting with Android 3.0, the preferred way of animating views is to use the
644 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
645 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
646 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
647 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
648 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
649 * makes animating these View properties particularly easy and efficient.
650 * </p>
651 * <p>
652 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
653 * You can attach an {@link Animation} object to a view using
654 * {@link #setAnimation(Animation)} or
655 * {@link #startAnimation(Animation)}. The animation can alter the scale,
656 * rotation, translation and alpha of a view over time. If the animation is
657 * attached to a view that has children, the animation will affect the entire
658 * subtree rooted by that node. When an animation is started, the framework will
659 * take care of redrawing the appropriate views until the animation completes.
660 * </p>
661 *
662 * <a name="Security"></a>
663 * <h3>Security</h3>
664 * <p>
665 * Sometimes it is essential that an application be able to verify that an action
666 * is being performed with the full knowledge and consent of the user, such as
667 * granting a permission request, making a purchase or clicking on an advertisement.
668 * Unfortunately, a malicious application could try to spoof the user into
669 * performing these actions, unaware, by concealing the intended purpose of the view.
670 * As a remedy, the framework offers a touch filtering mechanism that can be used to
671 * improve the security of views that provide access to sensitive functionality.
672 * </p><p>
673 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
674 * android:filterTouchesWhenObscured layout attribute to true.  When enabled, the framework
675 * will discard touches that are received whenever the view's window is obscured by
676 * another visible window.  As a result, the view will not receive touches whenever a
677 * toast, dialog or other window appears above the view's window.
678 * </p><p>
679 * For more fine-grained control over security, consider overriding the
680 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
681 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
682 * </p>
683 *
684 * @attr ref android.R.styleable#View_alpha
685 * @attr ref android.R.styleable#View_background
686 * @attr ref android.R.styleable#View_clickable
687 * @attr ref android.R.styleable#View_contentDescription
688 * @attr ref android.R.styleable#View_drawingCacheQuality
689 * @attr ref android.R.styleable#View_duplicateParentState
690 * @attr ref android.R.styleable#View_id
691 * @attr ref android.R.styleable#View_requiresFadingEdge
692 * @attr ref android.R.styleable#View_fadeScrollbars
693 * @attr ref android.R.styleable#View_fadingEdgeLength
694 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
695 * @attr ref android.R.styleable#View_fitsSystemWindows
696 * @attr ref android.R.styleable#View_isScrollContainer
697 * @attr ref android.R.styleable#View_focusable
698 * @attr ref android.R.styleable#View_focusableInTouchMode
699 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
700 * @attr ref android.R.styleable#View_keepScreenOn
701 * @attr ref android.R.styleable#View_layerType
702 * @attr ref android.R.styleable#View_layoutDirection
703 * @attr ref android.R.styleable#View_longClickable
704 * @attr ref android.R.styleable#View_minHeight
705 * @attr ref android.R.styleable#View_minWidth
706 * @attr ref android.R.styleable#View_nextFocusDown
707 * @attr ref android.R.styleable#View_nextFocusLeft
708 * @attr ref android.R.styleable#View_nextFocusRight
709 * @attr ref android.R.styleable#View_nextFocusUp
710 * @attr ref android.R.styleable#View_onClick
711 * @attr ref android.R.styleable#View_padding
712 * @attr ref android.R.styleable#View_paddingBottom
713 * @attr ref android.R.styleable#View_paddingLeft
714 * @attr ref android.R.styleable#View_paddingRight
715 * @attr ref android.R.styleable#View_paddingTop
716 * @attr ref android.R.styleable#View_paddingStart
717 * @attr ref android.R.styleable#View_paddingEnd
718 * @attr ref android.R.styleable#View_saveEnabled
719 * @attr ref android.R.styleable#View_rotation
720 * @attr ref android.R.styleable#View_rotationX
721 * @attr ref android.R.styleable#View_rotationY
722 * @attr ref android.R.styleable#View_scaleX
723 * @attr ref android.R.styleable#View_scaleY
724 * @attr ref android.R.styleable#View_scrollX
725 * @attr ref android.R.styleable#View_scrollY
726 * @attr ref android.R.styleable#View_scrollbarSize
727 * @attr ref android.R.styleable#View_scrollbarStyle
728 * @attr ref android.R.styleable#View_scrollbars
729 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
730 * @attr ref android.R.styleable#View_scrollbarFadeDuration
731 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
732 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
733 * @attr ref android.R.styleable#View_scrollbarThumbVertical
734 * @attr ref android.R.styleable#View_scrollbarTrackVertical
735 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
736 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
737 * @attr ref android.R.styleable#View_stateListAnimator
738 * @attr ref android.R.styleable#View_transitionName
739 * @attr ref android.R.styleable#View_soundEffectsEnabled
740 * @attr ref android.R.styleable#View_tag
741 * @attr ref android.R.styleable#View_textAlignment
742 * @attr ref android.R.styleable#View_textDirection
743 * @attr ref android.R.styleable#View_transformPivotX
744 * @attr ref android.R.styleable#View_transformPivotY
745 * @attr ref android.R.styleable#View_translationX
746 * @attr ref android.R.styleable#View_translationY
747 * @attr ref android.R.styleable#View_translationZ
748 * @attr ref android.R.styleable#View_visibility
749 * @attr ref android.R.styleable#View_theme
750 *
751 * @see android.view.ViewGroup
752 */
753@UiThread
754public class View implements Drawable.Callback, KeyEvent.Callback,
755        AccessibilityEventSource {
756    private static final boolean DBG = false;
757
758    /**
759     * The logging tag used by this class with android.util.Log.
760     */
761    protected static final String VIEW_LOG_TAG = "View";
762
763    /**
764     * When set to true, apps will draw debugging information about their layouts.
765     *
766     * @hide
767     */
768    public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
769
770    /**
771     * When set to true, this view will save its attribute data.
772     *
773     * @hide
774     */
775    public static boolean mDebugViewAttributes = false;
776
777    /**
778     * Used to mark a View that has no ID.
779     */
780    public static final int NO_ID = -1;
781
782    /**
783     * Signals that compatibility booleans have been initialized according to
784     * target SDK versions.
785     */
786    private static boolean sCompatibilityDone = false;
787
788    /**
789     * Use the old (broken) way of building MeasureSpecs.
790     */
791    private static boolean sUseBrokenMakeMeasureSpec = false;
792
793    /**
794     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
795     */
796    static boolean sUseZeroUnspecifiedMeasureSpec = false;
797
798    /**
799     * Ignore any optimizations using the measure cache.
800     */
801    private static boolean sIgnoreMeasureCache = false;
802
803    /**
804     * Ignore an optimization that skips unnecessary EXACTLY layout passes.
805     */
806    private static boolean sAlwaysRemeasureExactly = false;
807
808    /**
809     * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
810     * calling setFlags.
811     */
812    private static final int NOT_FOCUSABLE = 0x00000000;
813
814    /**
815     * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
816     * setFlags.
817     */
818    private static final int FOCUSABLE = 0x00000001;
819
820    /**
821     * Mask for use with setFlags indicating bits used for focus.
822     */
823    private static final int FOCUSABLE_MASK = 0x00000001;
824
825    /**
826     * This view will adjust its padding to fit sytem windows (e.g. status bar)
827     */
828    private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
829
830    /** @hide */
831    @IntDef({VISIBLE, INVISIBLE, GONE})
832    @Retention(RetentionPolicy.SOURCE)
833    public @interface Visibility {}
834
835    /**
836     * This view is visible.
837     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
838     * android:visibility}.
839     */
840    public static final int VISIBLE = 0x00000000;
841
842    /**
843     * This view is invisible, but it still takes up space for layout purposes.
844     * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
845     * android:visibility}.
846     */
847    public static final int INVISIBLE = 0x00000004;
848
849    /**
850     * This view is invisible, and it doesn't take any space for layout
851     * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
852     * android:visibility}.
853     */
854    public static final int GONE = 0x00000008;
855
856    /**
857     * Mask for use with setFlags indicating bits used for visibility.
858     * {@hide}
859     */
860    static final int VISIBILITY_MASK = 0x0000000C;
861
862    private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
863
864    /**
865     * This view is enabled. Interpretation varies by subclass.
866     * Use with ENABLED_MASK when calling setFlags.
867     * {@hide}
868     */
869    static final int ENABLED = 0x00000000;
870
871    /**
872     * This view is disabled. Interpretation varies by subclass.
873     * Use with ENABLED_MASK when calling setFlags.
874     * {@hide}
875     */
876    static final int DISABLED = 0x00000020;
877
878   /**
879    * Mask for use with setFlags indicating bits used for indicating whether
880    * this view is enabled
881    * {@hide}
882    */
883    static final int ENABLED_MASK = 0x00000020;
884
885    /**
886     * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
887     * called and further optimizations will be performed. It is okay to have
888     * this flag set and a background. Use with DRAW_MASK when calling setFlags.
889     * {@hide}
890     */
891    static final int WILL_NOT_DRAW = 0x00000080;
892
893    /**
894     * Mask for use with setFlags indicating bits used for indicating whether
895     * this view is will draw
896     * {@hide}
897     */
898    static final int DRAW_MASK = 0x00000080;
899
900    /**
901     * <p>This view doesn't show scrollbars.</p>
902     * {@hide}
903     */
904    static final int SCROLLBARS_NONE = 0x00000000;
905
906    /**
907     * <p>This view shows horizontal scrollbars.</p>
908     * {@hide}
909     */
910    static final int SCROLLBARS_HORIZONTAL = 0x00000100;
911
912    /**
913     * <p>This view shows vertical scrollbars.</p>
914     * {@hide}
915     */
916    static final int SCROLLBARS_VERTICAL = 0x00000200;
917
918    /**
919     * <p>Mask for use with setFlags indicating bits used for indicating which
920     * scrollbars are enabled.</p>
921     * {@hide}
922     */
923    static final int SCROLLBARS_MASK = 0x00000300;
924
925    /**
926     * Indicates that the view should filter touches when its window is obscured.
927     * Refer to the class comments for more information about this security feature.
928     * {@hide}
929     */
930    static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
931
932    /**
933     * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
934     * that they are optional and should be skipped if the window has
935     * requested system UI flags that ignore those insets for layout.
936     */
937    static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
938
939    /**
940     * <p>This view doesn't show fading edges.</p>
941     * {@hide}
942     */
943    static final int FADING_EDGE_NONE = 0x00000000;
944
945    /**
946     * <p>This view shows horizontal fading edges.</p>
947     * {@hide}
948     */
949    static final int FADING_EDGE_HORIZONTAL = 0x00001000;
950
951    /**
952     * <p>This view shows vertical fading edges.</p>
953     * {@hide}
954     */
955    static final int FADING_EDGE_VERTICAL = 0x00002000;
956
957    /**
958     * <p>Mask for use with setFlags indicating bits used for indicating which
959     * fading edges are enabled.</p>
960     * {@hide}
961     */
962    static final int FADING_EDGE_MASK = 0x00003000;
963
964    /**
965     * <p>Indicates this view can be clicked. When clickable, a View reacts
966     * to clicks by notifying the OnClickListener.<p>
967     * {@hide}
968     */
969    static final int CLICKABLE = 0x00004000;
970
971    /**
972     * <p>Indicates this view is caching its drawing into a bitmap.</p>
973     * {@hide}
974     */
975    static final int DRAWING_CACHE_ENABLED = 0x00008000;
976
977    /**
978     * <p>Indicates that no icicle should be saved for this view.<p>
979     * {@hide}
980     */
981    static final int SAVE_DISABLED = 0x000010000;
982
983    /**
984     * <p>Mask for use with setFlags indicating bits used for the saveEnabled
985     * property.</p>
986     * {@hide}
987     */
988    static final int SAVE_DISABLED_MASK = 0x000010000;
989
990    /**
991     * <p>Indicates that no drawing cache should ever be created for this view.<p>
992     * {@hide}
993     */
994    static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
995
996    /**
997     * <p>Indicates this view can take / keep focus when int touch mode.</p>
998     * {@hide}
999     */
1000    static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
1001
1002    /** @hide */
1003    @Retention(RetentionPolicy.SOURCE)
1004    @IntDef({DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH, DRAWING_CACHE_QUALITY_AUTO})
1005    public @interface DrawingCacheQuality {}
1006
1007    /**
1008     * <p>Enables low quality mode for the drawing cache.</p>
1009     */
1010    public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
1011
1012    /**
1013     * <p>Enables high quality mode for the drawing cache.</p>
1014     */
1015    public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
1016
1017    /**
1018     * <p>Enables automatic quality mode for the drawing cache.</p>
1019     */
1020    public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
1021
1022    private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
1023            DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
1024    };
1025
1026    /**
1027     * <p>Mask for use with setFlags indicating bits used for the cache
1028     * quality property.</p>
1029     * {@hide}
1030     */
1031    static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
1032
1033    /**
1034     * <p>
1035     * Indicates this view can be long clicked. When long clickable, a View
1036     * reacts to long clicks by notifying the OnLongClickListener or showing a
1037     * context menu.
1038     * </p>
1039     * {@hide}
1040     */
1041    static final int LONG_CLICKABLE = 0x00200000;
1042
1043    /**
1044     * <p>Indicates that this view gets its drawable states from its direct parent
1045     * and ignores its original internal states.</p>
1046     *
1047     * @hide
1048     */
1049    static final int DUPLICATE_PARENT_STATE = 0x00400000;
1050
1051    /**
1052     * <p>
1053     * Indicates this view can be context clicked. When context clickable, a View reacts to a
1054     * context click (e.g. a primary stylus button press or right mouse click) by notifying the
1055     * OnContextClickListener.
1056     * </p>
1057     * {@hide}
1058     */
1059    static final int CONTEXT_CLICKABLE = 0x00800000;
1060
1061
1062    /** @hide */
1063    @IntDef({
1064        SCROLLBARS_INSIDE_OVERLAY,
1065        SCROLLBARS_INSIDE_INSET,
1066        SCROLLBARS_OUTSIDE_OVERLAY,
1067        SCROLLBARS_OUTSIDE_INSET
1068    })
1069    @Retention(RetentionPolicy.SOURCE)
1070    public @interface ScrollBarStyle {}
1071
1072    /**
1073     * The scrollbar style to display the scrollbars inside the content area,
1074     * without increasing the padding. The scrollbars will be overlaid with
1075     * translucency on the view's content.
1076     */
1077    public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
1078
1079    /**
1080     * The scrollbar style to display the scrollbars inside the padded area,
1081     * increasing the padding of the view. The scrollbars will not overlap the
1082     * content area of the view.
1083     */
1084    public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
1085
1086    /**
1087     * The scrollbar style to display the scrollbars at the edge of the view,
1088     * without increasing the padding. The scrollbars will be overlaid with
1089     * translucency.
1090     */
1091    public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
1092
1093    /**
1094     * The scrollbar style to display the scrollbars at the edge of the view,
1095     * increasing the padding of the view. The scrollbars will only overlap the
1096     * background, if any.
1097     */
1098    public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
1099
1100    /**
1101     * Mask to check if the scrollbar style is overlay or inset.
1102     * {@hide}
1103     */
1104    static final int SCROLLBARS_INSET_MASK = 0x01000000;
1105
1106    /**
1107     * Mask to check if the scrollbar style is inside or outside.
1108     * {@hide}
1109     */
1110    static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
1111
1112    /**
1113     * Mask for scrollbar style.
1114     * {@hide}
1115     */
1116    static final int SCROLLBARS_STYLE_MASK = 0x03000000;
1117
1118    /**
1119     * View flag indicating that the screen should remain on while the
1120     * window containing this view is visible to the user.  This effectively
1121     * takes care of automatically setting the WindowManager's
1122     * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
1123     */
1124    public static final int KEEP_SCREEN_ON = 0x04000000;
1125
1126    /**
1127     * View flag indicating whether this view should have sound effects enabled
1128     * for events such as clicking and touching.
1129     */
1130    public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
1131
1132    /**
1133     * View flag indicating whether this view should have haptic feedback
1134     * enabled for events such as long presses.
1135     */
1136    public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
1137
1138    /**
1139     * <p>Indicates that the view hierarchy should stop saving state when
1140     * it reaches this view.  If state saving is initiated immediately at
1141     * the view, it will be allowed.
1142     * {@hide}
1143     */
1144    static final int PARENT_SAVE_DISABLED = 0x20000000;
1145
1146    /**
1147     * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
1148     * {@hide}
1149     */
1150    static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
1151
1152    /** @hide */
1153    @IntDef(flag = true,
1154            value = {
1155                FOCUSABLES_ALL,
1156                FOCUSABLES_TOUCH_MODE
1157            })
1158    @Retention(RetentionPolicy.SOURCE)
1159    public @interface FocusableMode {}
1160
1161    /**
1162     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1163     * should add all focusable Views regardless if they are focusable in touch mode.
1164     */
1165    public static final int FOCUSABLES_ALL = 0x00000000;
1166
1167    /**
1168     * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1169     * should add only Views focusable in touch mode.
1170     */
1171    public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1172
1173    /** @hide */
1174    @IntDef({
1175            FOCUS_BACKWARD,
1176            FOCUS_FORWARD,
1177            FOCUS_LEFT,
1178            FOCUS_UP,
1179            FOCUS_RIGHT,
1180            FOCUS_DOWN
1181    })
1182    @Retention(RetentionPolicy.SOURCE)
1183    public @interface FocusDirection {}
1184
1185    /** @hide */
1186    @IntDef({
1187            FOCUS_LEFT,
1188            FOCUS_UP,
1189            FOCUS_RIGHT,
1190            FOCUS_DOWN
1191    })
1192    @Retention(RetentionPolicy.SOURCE)
1193    public @interface FocusRealDirection {} // Like @FocusDirection, but without forward/backward
1194
1195    /**
1196     * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
1197     * item.
1198     */
1199    public static final int FOCUS_BACKWARD = 0x00000001;
1200
1201    /**
1202     * Use with {@link #focusSearch(int)}. Move focus to the next selectable
1203     * item.
1204     */
1205    public static final int FOCUS_FORWARD = 0x00000002;
1206
1207    /**
1208     * Use with {@link #focusSearch(int)}. Move focus to the left.
1209     */
1210    public static final int FOCUS_LEFT = 0x00000011;
1211
1212    /**
1213     * Use with {@link #focusSearch(int)}. Move focus up.
1214     */
1215    public static final int FOCUS_UP = 0x00000021;
1216
1217    /**
1218     * Use with {@link #focusSearch(int)}. Move focus to the right.
1219     */
1220    public static final int FOCUS_RIGHT = 0x00000042;
1221
1222    /**
1223     * Use with {@link #focusSearch(int)}. Move focus down.
1224     */
1225    public static final int FOCUS_DOWN = 0x00000082;
1226
1227    /**
1228     * Bits of {@link #getMeasuredWidthAndState()} and
1229     * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1230     */
1231    public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1232
1233    /**
1234     * Bits of {@link #getMeasuredWidthAndState()} and
1235     * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1236     */
1237    public static final int MEASURED_STATE_MASK = 0xff000000;
1238
1239    /**
1240     * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1241     * for functions that combine both width and height into a single int,
1242     * such as {@link #getMeasuredState()} and the childState argument of
1243     * {@link #resolveSizeAndState(int, int, int)}.
1244     */
1245    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1246
1247    /**
1248     * Bit of {@link #getMeasuredWidthAndState()} and
1249     * {@link #getMeasuredWidthAndState()} that indicates the measured size
1250     * is smaller that the space the view would like to have.
1251     */
1252    public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1253
1254    /**
1255     * Base View state sets
1256     */
1257    // Singles
1258    /**
1259     * Indicates the view has no states set. States are used with
1260     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1261     * view depending on its state.
1262     *
1263     * @see android.graphics.drawable.Drawable
1264     * @see #getDrawableState()
1265     */
1266    protected static final int[] EMPTY_STATE_SET;
1267    /**
1268     * Indicates the view is enabled. States are used with
1269     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1270     * view depending on its state.
1271     *
1272     * @see android.graphics.drawable.Drawable
1273     * @see #getDrawableState()
1274     */
1275    protected static final int[] ENABLED_STATE_SET;
1276    /**
1277     * Indicates the view is focused. States are used with
1278     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1279     * view depending on its state.
1280     *
1281     * @see android.graphics.drawable.Drawable
1282     * @see #getDrawableState()
1283     */
1284    protected static final int[] FOCUSED_STATE_SET;
1285    /**
1286     * Indicates the view is selected. States are used with
1287     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1288     * view depending on its state.
1289     *
1290     * @see android.graphics.drawable.Drawable
1291     * @see #getDrawableState()
1292     */
1293    protected static final int[] SELECTED_STATE_SET;
1294    /**
1295     * Indicates the view is pressed. States are used with
1296     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1297     * view depending on its state.
1298     *
1299     * @see android.graphics.drawable.Drawable
1300     * @see #getDrawableState()
1301     */
1302    protected static final int[] PRESSED_STATE_SET;
1303    /**
1304     * Indicates the view's window has focus. States are used with
1305     * {@link android.graphics.drawable.Drawable} to change the drawing of the
1306     * view depending on its state.
1307     *
1308     * @see android.graphics.drawable.Drawable
1309     * @see #getDrawableState()
1310     */
1311    protected static final int[] WINDOW_FOCUSED_STATE_SET;
1312    // Doubles
1313    /**
1314     * Indicates the view is enabled and has the focus.
1315     *
1316     * @see #ENABLED_STATE_SET
1317     * @see #FOCUSED_STATE_SET
1318     */
1319    protected static final int[] ENABLED_FOCUSED_STATE_SET;
1320    /**
1321     * Indicates the view is enabled and selected.
1322     *
1323     * @see #ENABLED_STATE_SET
1324     * @see #SELECTED_STATE_SET
1325     */
1326    protected static final int[] ENABLED_SELECTED_STATE_SET;
1327    /**
1328     * Indicates the view is enabled and that its window has focus.
1329     *
1330     * @see #ENABLED_STATE_SET
1331     * @see #WINDOW_FOCUSED_STATE_SET
1332     */
1333    protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
1334    /**
1335     * Indicates the view is focused and selected.
1336     *
1337     * @see #FOCUSED_STATE_SET
1338     * @see #SELECTED_STATE_SET
1339     */
1340    protected static final int[] FOCUSED_SELECTED_STATE_SET;
1341    /**
1342     * Indicates the view has the focus and that its window has the focus.
1343     *
1344     * @see #FOCUSED_STATE_SET
1345     * @see #WINDOW_FOCUSED_STATE_SET
1346     */
1347    protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
1348    /**
1349     * Indicates the view is selected and that its window has the focus.
1350     *
1351     * @see #SELECTED_STATE_SET
1352     * @see #WINDOW_FOCUSED_STATE_SET
1353     */
1354    protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
1355    // Triples
1356    /**
1357     * Indicates the view is enabled, focused and selected.
1358     *
1359     * @see #ENABLED_STATE_SET
1360     * @see #FOCUSED_STATE_SET
1361     * @see #SELECTED_STATE_SET
1362     */
1363    protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
1364    /**
1365     * Indicates the view is enabled, focused and its window has the focus.
1366     *
1367     * @see #ENABLED_STATE_SET
1368     * @see #FOCUSED_STATE_SET
1369     * @see #WINDOW_FOCUSED_STATE_SET
1370     */
1371    protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1372    /**
1373     * Indicates the view is enabled, selected and its window has the focus.
1374     *
1375     * @see #ENABLED_STATE_SET
1376     * @see #SELECTED_STATE_SET
1377     * @see #WINDOW_FOCUSED_STATE_SET
1378     */
1379    protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1380    /**
1381     * Indicates the view is focused, selected and its window has the focus.
1382     *
1383     * @see #FOCUSED_STATE_SET
1384     * @see #SELECTED_STATE_SET
1385     * @see #WINDOW_FOCUSED_STATE_SET
1386     */
1387    protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1388    /**
1389     * Indicates the view is enabled, focused, selected and its window
1390     * has the focus.
1391     *
1392     * @see #ENABLED_STATE_SET
1393     * @see #FOCUSED_STATE_SET
1394     * @see #SELECTED_STATE_SET
1395     * @see #WINDOW_FOCUSED_STATE_SET
1396     */
1397    protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1398    /**
1399     * Indicates the view is pressed and its window has the focus.
1400     *
1401     * @see #PRESSED_STATE_SET
1402     * @see #WINDOW_FOCUSED_STATE_SET
1403     */
1404    protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
1405    /**
1406     * Indicates the view is pressed and selected.
1407     *
1408     * @see #PRESSED_STATE_SET
1409     * @see #SELECTED_STATE_SET
1410     */
1411    protected static final int[] PRESSED_SELECTED_STATE_SET;
1412    /**
1413     * Indicates the view is pressed, selected and its window has the focus.
1414     *
1415     * @see #PRESSED_STATE_SET
1416     * @see #SELECTED_STATE_SET
1417     * @see #WINDOW_FOCUSED_STATE_SET
1418     */
1419    protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1420    /**
1421     * Indicates the view is pressed and focused.
1422     *
1423     * @see #PRESSED_STATE_SET
1424     * @see #FOCUSED_STATE_SET
1425     */
1426    protected static final int[] PRESSED_FOCUSED_STATE_SET;
1427    /**
1428     * Indicates the view is pressed, focused and its window has the focus.
1429     *
1430     * @see #PRESSED_STATE_SET
1431     * @see #FOCUSED_STATE_SET
1432     * @see #WINDOW_FOCUSED_STATE_SET
1433     */
1434    protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1435    /**
1436     * Indicates the view is pressed, focused and selected.
1437     *
1438     * @see #PRESSED_STATE_SET
1439     * @see #SELECTED_STATE_SET
1440     * @see #FOCUSED_STATE_SET
1441     */
1442    protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
1443    /**
1444     * Indicates the view is pressed, focused, selected and its window has the focus.
1445     *
1446     * @see #PRESSED_STATE_SET
1447     * @see #FOCUSED_STATE_SET
1448     * @see #SELECTED_STATE_SET
1449     * @see #WINDOW_FOCUSED_STATE_SET
1450     */
1451    protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1452    /**
1453     * Indicates the view is pressed and enabled.
1454     *
1455     * @see #PRESSED_STATE_SET
1456     * @see #ENABLED_STATE_SET
1457     */
1458    protected static final int[] PRESSED_ENABLED_STATE_SET;
1459    /**
1460     * Indicates the view is pressed, enabled and its window has the focus.
1461     *
1462     * @see #PRESSED_STATE_SET
1463     * @see #ENABLED_STATE_SET
1464     * @see #WINDOW_FOCUSED_STATE_SET
1465     */
1466    protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
1467    /**
1468     * Indicates the view is pressed, enabled and selected.
1469     *
1470     * @see #PRESSED_STATE_SET
1471     * @see #ENABLED_STATE_SET
1472     * @see #SELECTED_STATE_SET
1473     */
1474    protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
1475    /**
1476     * Indicates the view is pressed, enabled, selected and its window has the
1477     * focus.
1478     *
1479     * @see #PRESSED_STATE_SET
1480     * @see #ENABLED_STATE_SET
1481     * @see #SELECTED_STATE_SET
1482     * @see #WINDOW_FOCUSED_STATE_SET
1483     */
1484    protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1485    /**
1486     * Indicates the view is pressed, enabled and focused.
1487     *
1488     * @see #PRESSED_STATE_SET
1489     * @see #ENABLED_STATE_SET
1490     * @see #FOCUSED_STATE_SET
1491     */
1492    protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
1493    /**
1494     * Indicates the view is pressed, enabled, focused and its window has the
1495     * focus.
1496     *
1497     * @see #PRESSED_STATE_SET
1498     * @see #ENABLED_STATE_SET
1499     * @see #FOCUSED_STATE_SET
1500     * @see #WINDOW_FOCUSED_STATE_SET
1501     */
1502    protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
1503    /**
1504     * Indicates the view is pressed, enabled, focused and selected.
1505     *
1506     * @see #PRESSED_STATE_SET
1507     * @see #ENABLED_STATE_SET
1508     * @see #SELECTED_STATE_SET
1509     * @see #FOCUSED_STATE_SET
1510     */
1511    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
1512    /**
1513     * Indicates the view is pressed, enabled, focused, selected and its window
1514     * has the focus.
1515     *
1516     * @see #PRESSED_STATE_SET
1517     * @see #ENABLED_STATE_SET
1518     * @see #SELECTED_STATE_SET
1519     * @see #FOCUSED_STATE_SET
1520     * @see #WINDOW_FOCUSED_STATE_SET
1521     */
1522    protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
1523
1524    static {
1525        EMPTY_STATE_SET = StateSet.get(0);
1526
1527        WINDOW_FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_WINDOW_FOCUSED);
1528
1529        SELECTED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_SELECTED);
1530        SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1531                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED);
1532
1533        FOCUSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_FOCUSED);
1534        FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1535                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED);
1536        FOCUSED_SELECTED_STATE_SET = StateSet.get(
1537                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED);
1538        FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1539                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1540                        | StateSet.VIEW_STATE_FOCUSED);
1541
1542        ENABLED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_ENABLED);
1543        ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1544                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1545        ENABLED_SELECTED_STATE_SET = StateSet.get(
1546                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED);
1547        ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1548                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1549                        | StateSet.VIEW_STATE_ENABLED);
1550        ENABLED_FOCUSED_STATE_SET = StateSet.get(
1551                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED);
1552        ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1553                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1554                        | StateSet.VIEW_STATE_ENABLED);
1555        ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1556                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1557                        | StateSet.VIEW_STATE_ENABLED);
1558        ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1559                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1560                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED);
1561
1562        PRESSED_STATE_SET = StateSet.get(StateSet.VIEW_STATE_PRESSED);
1563        PRESSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1564                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1565        PRESSED_SELECTED_STATE_SET = StateSet.get(
1566                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_PRESSED);
1567        PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1568                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1569                        | StateSet.VIEW_STATE_PRESSED);
1570        PRESSED_FOCUSED_STATE_SET = StateSet.get(
1571                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1572        PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1573                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1574                        | StateSet.VIEW_STATE_PRESSED);
1575        PRESSED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1576                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1577                        | StateSet.VIEW_STATE_PRESSED);
1578        PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1579                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1580                        | StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_PRESSED);
1581        PRESSED_ENABLED_STATE_SET = StateSet.get(
1582                StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1583        PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1584                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_ENABLED
1585                        | StateSet.VIEW_STATE_PRESSED);
1586        PRESSED_ENABLED_SELECTED_STATE_SET = StateSet.get(
1587                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_ENABLED
1588                        | StateSet.VIEW_STATE_PRESSED);
1589        PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1590                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1591                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1592        PRESSED_ENABLED_FOCUSED_STATE_SET = StateSet.get(
1593                StateSet.VIEW_STATE_FOCUSED | StateSet.VIEW_STATE_ENABLED
1594                        | StateSet.VIEW_STATE_PRESSED);
1595        PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1596                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_FOCUSED
1597                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1598        PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = StateSet.get(
1599                StateSet.VIEW_STATE_SELECTED | StateSet.VIEW_STATE_FOCUSED
1600                        | StateSet.VIEW_STATE_ENABLED | StateSet.VIEW_STATE_PRESSED);
1601        PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = StateSet.get(
1602                StateSet.VIEW_STATE_WINDOW_FOCUSED | StateSet.VIEW_STATE_SELECTED
1603                        | StateSet.VIEW_STATE_FOCUSED| StateSet.VIEW_STATE_ENABLED
1604                        | StateSet.VIEW_STATE_PRESSED);
1605    }
1606
1607    /**
1608     * Accessibility event types that are dispatched for text population.
1609     */
1610    private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1611            AccessibilityEvent.TYPE_VIEW_CLICKED
1612            | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1613            | AccessibilityEvent.TYPE_VIEW_SELECTED
1614            | AccessibilityEvent.TYPE_VIEW_FOCUSED
1615            | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1616            | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
1617            | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
1618            | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
1619            | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
1620            | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1621            | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
1622
1623    /**
1624     * Temporary Rect currently for use in setBackground().  This will probably
1625     * be extended in the future to hold our own class with more than just
1626     * a Rect. :)
1627     */
1628    static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
1629
1630    /**
1631     * Map used to store views' tags.
1632     */
1633    private SparseArray<Object> mKeyedTags;
1634
1635    /**
1636     * The next available accessibility id.
1637     */
1638    private static int sNextAccessibilityViewId;
1639
1640    /**
1641     * The animation currently associated with this view.
1642     * @hide
1643     */
1644    protected Animation mCurrentAnimation = null;
1645
1646    /**
1647     * Width as measured during measure pass.
1648     * {@hide}
1649     */
1650    @ViewDebug.ExportedProperty(category = "measurement")
1651    int mMeasuredWidth;
1652
1653    /**
1654     * Height as measured during measure pass.
1655     * {@hide}
1656     */
1657    @ViewDebug.ExportedProperty(category = "measurement")
1658    int mMeasuredHeight;
1659
1660    /**
1661     * Flag to indicate that this view was marked INVALIDATED, or had its display list
1662     * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1663     * its display list. This flag, used only when hw accelerated, allows us to clear the
1664     * flag while retaining this information until it's needed (at getDisplayList() time and
1665     * in drawChild(), when we decide to draw a view's children's display lists into our own).
1666     *
1667     * {@hide}
1668     */
1669    boolean mRecreateDisplayList = false;
1670
1671    /**
1672     * The view's identifier.
1673     * {@hide}
1674     *
1675     * @see #setId(int)
1676     * @see #getId()
1677     */
1678    @IdRes
1679    @ViewDebug.ExportedProperty(resolveId = true)
1680    int mID = NO_ID;
1681
1682    /**
1683     * The stable ID of this view for accessibility purposes.
1684     */
1685    int mAccessibilityViewId = NO_ID;
1686
1687    private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
1688
1689    SendViewStateChangedAccessibilityEvent mSendViewStateChangedAccessibilityEvent;
1690
1691    /**
1692     * The view's tag.
1693     * {@hide}
1694     *
1695     * @see #setTag(Object)
1696     * @see #getTag()
1697     */
1698    protected Object mTag = null;
1699
1700    // for mPrivateFlags:
1701    /** {@hide} */
1702    static final int PFLAG_WANTS_FOCUS                 = 0x00000001;
1703    /** {@hide} */
1704    static final int PFLAG_FOCUSED                     = 0x00000002;
1705    /** {@hide} */
1706    static final int PFLAG_SELECTED                    = 0x00000004;
1707    /** {@hide} */
1708    static final int PFLAG_IS_ROOT_NAMESPACE           = 0x00000008;
1709    /** {@hide} */
1710    static final int PFLAG_HAS_BOUNDS                  = 0x00000010;
1711    /** {@hide} */
1712    static final int PFLAG_DRAWN                       = 0x00000020;
1713    /**
1714     * When this flag is set, this view is running an animation on behalf of its
1715     * children and should therefore not cancel invalidate requests, even if they
1716     * lie outside of this view's bounds.
1717     *
1718     * {@hide}
1719     */
1720    static final int PFLAG_DRAW_ANIMATION              = 0x00000040;
1721    /** {@hide} */
1722    static final int PFLAG_SKIP_DRAW                   = 0x00000080;
1723    /** {@hide} */
1724    static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
1725    /** {@hide} */
1726    static final int PFLAG_DRAWABLE_STATE_DIRTY        = 0x00000400;
1727    /** {@hide} */
1728    static final int PFLAG_MEASURED_DIMENSION_SET      = 0x00000800;
1729    /** {@hide} */
1730    static final int PFLAG_FORCE_LAYOUT                = 0x00001000;
1731    /** {@hide} */
1732    static final int PFLAG_LAYOUT_REQUIRED             = 0x00002000;
1733
1734    private static final int PFLAG_PRESSED             = 0x00004000;
1735
1736    /** {@hide} */
1737    static final int PFLAG_DRAWING_CACHE_VALID         = 0x00008000;
1738    /**
1739     * Flag used to indicate that this view should be drawn once more (and only once
1740     * more) after its animation has completed.
1741     * {@hide}
1742     */
1743    static final int PFLAG_ANIMATION_STARTED           = 0x00010000;
1744
1745    private static final int PFLAG_SAVE_STATE_CALLED   = 0x00020000;
1746
1747    /**
1748     * Indicates that the View returned true when onSetAlpha() was called and that
1749     * the alpha must be restored.
1750     * {@hide}
1751     */
1752    static final int PFLAG_ALPHA_SET                   = 0x00040000;
1753
1754    /**
1755     * Set by {@link #setScrollContainer(boolean)}.
1756     */
1757    static final int PFLAG_SCROLL_CONTAINER            = 0x00080000;
1758
1759    /**
1760     * Set by {@link #setScrollContainer(boolean)}.
1761     */
1762    static final int PFLAG_SCROLL_CONTAINER_ADDED      = 0x00100000;
1763
1764    /**
1765     * View flag indicating whether this view was invalidated (fully or partially.)
1766     *
1767     * @hide
1768     */
1769    static final int PFLAG_DIRTY                       = 0x00200000;
1770
1771    /**
1772     * View flag indicating whether this view was invalidated by an opaque
1773     * invalidate request.
1774     *
1775     * @hide
1776     */
1777    static final int PFLAG_DIRTY_OPAQUE                = 0x00400000;
1778
1779    /**
1780     * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
1781     *
1782     * @hide
1783     */
1784    static final int PFLAG_DIRTY_MASK                  = 0x00600000;
1785
1786    /**
1787     * Indicates whether the background is opaque.
1788     *
1789     * @hide
1790     */
1791    static final int PFLAG_OPAQUE_BACKGROUND           = 0x00800000;
1792
1793    /**
1794     * Indicates whether the scrollbars are opaque.
1795     *
1796     * @hide
1797     */
1798    static final int PFLAG_OPAQUE_SCROLLBARS           = 0x01000000;
1799
1800    /**
1801     * Indicates whether the view is opaque.
1802     *
1803     * @hide
1804     */
1805    static final int PFLAG_OPAQUE_MASK                 = 0x01800000;
1806
1807    /**
1808     * Indicates a prepressed state;
1809     * the short time between ACTION_DOWN and recognizing
1810     * a 'real' press. Prepressed is used to recognize quick taps
1811     * even when they are shorter than ViewConfiguration.getTapTimeout().
1812     *
1813     * @hide
1814     */
1815    private static final int PFLAG_PREPRESSED          = 0x02000000;
1816
1817    /**
1818     * Indicates whether the view is temporarily detached.
1819     *
1820     * @hide
1821     */
1822    static final int PFLAG_CANCEL_NEXT_UP_EVENT        = 0x04000000;
1823
1824    /**
1825     * Indicates that we should awaken scroll bars once attached
1826     *
1827     * PLEASE NOTE: This flag is now unused as we now send onVisibilityChanged
1828     * during window attachment and it is no longer needed. Feel free to repurpose it.
1829     *
1830     * @hide
1831     */
1832    private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
1833
1834    /**
1835     * Indicates that the view has received HOVER_ENTER.  Cleared on HOVER_EXIT.
1836     * @hide
1837     */
1838    private static final int PFLAG_HOVERED             = 0x10000000;
1839
1840    /**
1841     * no longer needed, should be reused
1842     */
1843    private static final int PFLAG_DOES_NOTHING_REUSE_PLEASE = 0x20000000;
1844
1845    /** {@hide} */
1846    static final int PFLAG_ACTIVATED                   = 0x40000000;
1847
1848    /**
1849     * Indicates that this view was specifically invalidated, not just dirtied because some
1850     * child view was invalidated. The flag is used to determine when we need to recreate
1851     * a view's display list (as opposed to just returning a reference to its existing
1852     * display list).
1853     *
1854     * @hide
1855     */
1856    static final int PFLAG_INVALIDATED                 = 0x80000000;
1857
1858    /**
1859     * Masks for mPrivateFlags2, as generated by dumpFlags():
1860     *
1861     * |-------|-------|-------|-------|
1862     *                                 1 PFLAG2_DRAG_CAN_ACCEPT
1863     *                                1  PFLAG2_DRAG_HOVERED
1864     *                              11   PFLAG2_LAYOUT_DIRECTION_MASK
1865     *                             1     PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL
1866     *                            1      PFLAG2_LAYOUT_DIRECTION_RESOLVED
1867     *                            11     PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK
1868     *                           1       PFLAG2_TEXT_DIRECTION_FLAGS[1]
1869     *                          1        PFLAG2_TEXT_DIRECTION_FLAGS[2]
1870     *                          11       PFLAG2_TEXT_DIRECTION_FLAGS[3]
1871     *                         1         PFLAG2_TEXT_DIRECTION_FLAGS[4]
1872     *                         1 1       PFLAG2_TEXT_DIRECTION_FLAGS[5]
1873     *                         11        PFLAG2_TEXT_DIRECTION_FLAGS[6]
1874     *                         111       PFLAG2_TEXT_DIRECTION_FLAGS[7]
1875     *                         111       PFLAG2_TEXT_DIRECTION_MASK
1876     *                        1          PFLAG2_TEXT_DIRECTION_RESOLVED
1877     *                       1           PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT
1878     *                     111           PFLAG2_TEXT_DIRECTION_RESOLVED_MASK
1879     *                    1              PFLAG2_TEXT_ALIGNMENT_FLAGS[1]
1880     *                   1               PFLAG2_TEXT_ALIGNMENT_FLAGS[2]
1881     *                   11              PFLAG2_TEXT_ALIGNMENT_FLAGS[3]
1882     *                  1                PFLAG2_TEXT_ALIGNMENT_FLAGS[4]
1883     *                  1 1              PFLAG2_TEXT_ALIGNMENT_FLAGS[5]
1884     *                  11               PFLAG2_TEXT_ALIGNMENT_FLAGS[6]
1885     *                  111              PFLAG2_TEXT_ALIGNMENT_MASK
1886     *                 1                 PFLAG2_TEXT_ALIGNMENT_RESOLVED
1887     *                1                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT
1888     *              111                  PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK
1889     *           111                     PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK
1890     *         11                        PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK
1891     *       1                           PFLAG2_ACCESSIBILITY_FOCUSED
1892     *      1                            PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED
1893     *     1                             PFLAG2_VIEW_QUICK_REJECTED
1894     *    1                              PFLAG2_PADDING_RESOLVED
1895     *   1                               PFLAG2_DRAWABLE_RESOLVED
1896     *  1                                PFLAG2_HAS_TRANSIENT_STATE
1897     * |-------|-------|-------|-------|
1898     */
1899
1900    /**
1901     * Indicates that this view has reported that it can accept the current drag's content.
1902     * Cleared when the drag operation concludes.
1903     * @hide
1904     */
1905    static final int PFLAG2_DRAG_CAN_ACCEPT            = 0x00000001;
1906
1907    /**
1908     * Indicates that this view is currently directly under the drag location in a
1909     * drag-and-drop operation involving content that it can accept.  Cleared when
1910     * the drag exits the view, or when the drag operation concludes.
1911     * @hide
1912     */
1913    static final int PFLAG2_DRAG_HOVERED               = 0x00000002;
1914
1915    /** @hide */
1916    @IntDef({
1917        LAYOUT_DIRECTION_LTR,
1918        LAYOUT_DIRECTION_RTL,
1919        LAYOUT_DIRECTION_INHERIT,
1920        LAYOUT_DIRECTION_LOCALE
1921    })
1922    @Retention(RetentionPolicy.SOURCE)
1923    // Not called LayoutDirection to avoid conflict with android.util.LayoutDirection
1924    public @interface LayoutDir {}
1925
1926    /** @hide */
1927    @IntDef({
1928        LAYOUT_DIRECTION_LTR,
1929        LAYOUT_DIRECTION_RTL
1930    })
1931    @Retention(RetentionPolicy.SOURCE)
1932    public @interface ResolvedLayoutDir {}
1933
1934    /**
1935     * A flag to indicate that the layout direction of this view has not been defined yet.
1936     * @hide
1937     */
1938    public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
1939
1940    /**
1941     * Horizontal layout direction of this view is from Left to Right.
1942     * Use with {@link #setLayoutDirection}.
1943     */
1944    public static final int LAYOUT_DIRECTION_LTR = LayoutDirection.LTR;
1945
1946    /**
1947     * Horizontal layout direction of this view is from Right to Left.
1948     * Use with {@link #setLayoutDirection}.
1949     */
1950    public static final int LAYOUT_DIRECTION_RTL = LayoutDirection.RTL;
1951
1952    /**
1953     * Horizontal layout direction of this view is inherited from its parent.
1954     * Use with {@link #setLayoutDirection}.
1955     */
1956    public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection.INHERIT;
1957
1958    /**
1959     * Horizontal layout direction of this view is from deduced from the default language
1960     * script for the locale. Use with {@link #setLayoutDirection}.
1961     */
1962    public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection.LOCALE;
1963
1964    /**
1965     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1966     * @hide
1967     */
1968    static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
1969
1970    /**
1971     * Mask for use with private flags indicating bits used for horizontal layout direction.
1972     * @hide
1973     */
1974    static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1975
1976    /**
1977     * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1978     * right-to-left direction.
1979     * @hide
1980     */
1981    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1982
1983    /**
1984     * Indicates whether the view horizontal layout direction has been resolved.
1985     * @hide
1986     */
1987    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1988
1989    /**
1990     * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1991     * @hide
1992     */
1993    static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1994            << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
1995
1996    /*
1997     * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1998     * flag value.
1999     * @hide
2000     */
2001    private static final int[] LAYOUT_DIRECTION_FLAGS = {
2002            LAYOUT_DIRECTION_LTR,
2003            LAYOUT_DIRECTION_RTL,
2004            LAYOUT_DIRECTION_INHERIT,
2005            LAYOUT_DIRECTION_LOCALE
2006    };
2007
2008    /**
2009     * Default horizontal layout direction.
2010     */
2011    private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
2012
2013    /**
2014     * Default horizontal layout direction.
2015     * @hide
2016     */
2017    static final int LAYOUT_DIRECTION_RESOLVED_DEFAULT = LAYOUT_DIRECTION_LTR;
2018
2019    /**
2020     * Text direction is inherited through {@link ViewGroup}
2021     */
2022    public static final int TEXT_DIRECTION_INHERIT = 0;
2023
2024    /**
2025     * Text direction is using "first strong algorithm". The first strong directional character
2026     * determines the paragraph direction. If there is no strong directional character, the
2027     * paragraph direction is the view's resolved layout direction.
2028     */
2029    public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
2030
2031    /**
2032     * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
2033     * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
2034     * If there are neither, the paragraph direction is the view's resolved layout direction.
2035     */
2036    public static final int TEXT_DIRECTION_ANY_RTL = 2;
2037
2038    /**
2039     * Text direction is forced to LTR.
2040     */
2041    public static final int TEXT_DIRECTION_LTR = 3;
2042
2043    /**
2044     * Text direction is forced to RTL.
2045     */
2046    public static final int TEXT_DIRECTION_RTL = 4;
2047
2048    /**
2049     * Text direction is coming from the system Locale.
2050     */
2051    public static final int TEXT_DIRECTION_LOCALE = 5;
2052
2053    /**
2054     * Text direction is using "first strong algorithm". The first strong directional character
2055     * determines the paragraph direction. If there is no strong directional character, the
2056     * paragraph direction is LTR.
2057     */
2058    public static final int TEXT_DIRECTION_FIRST_STRONG_LTR = 6;
2059
2060    /**
2061     * Text direction is using "first strong algorithm". The first strong directional character
2062     * determines the paragraph direction. If there is no strong directional character, the
2063     * paragraph direction is RTL.
2064     */
2065    public static final int TEXT_DIRECTION_FIRST_STRONG_RTL = 7;
2066
2067    /**
2068     * Default text direction is inherited
2069     */
2070    private static final int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
2071
2072    /**
2073     * Default resolved text direction
2074     * @hide
2075     */
2076    static final int TEXT_DIRECTION_RESOLVED_DEFAULT = TEXT_DIRECTION_FIRST_STRONG;
2077
2078    /**
2079     * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
2080     * @hide
2081     */
2082    static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
2083
2084    /**
2085     * Mask for use with private flags indicating bits used for text direction.
2086     * @hide
2087     */
2088    static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
2089            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2090
2091    /**
2092     * Array of text direction flags for mapping attribute "textDirection" to correct
2093     * flag value.
2094     * @hide
2095     */
2096    private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
2097            TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2098            TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2099            TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2100            TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2101            TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2102            TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2103            TEXT_DIRECTION_FIRST_STRONG_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
2104            TEXT_DIRECTION_FIRST_STRONG_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
2105    };
2106
2107    /**
2108     * Indicates whether the view text direction has been resolved.
2109     * @hide
2110     */
2111    static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
2112            << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
2113
2114    /**
2115     * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2116     * @hide
2117     */
2118    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
2119
2120    /**
2121     * Mask for use with private flags indicating bits used for resolved text direction.
2122     * @hide
2123     */
2124    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
2125            << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2126
2127    /**
2128     * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
2129     * @hide
2130     */
2131    static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
2132            TEXT_DIRECTION_RESOLVED_DEFAULT << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
2133
2134    /** @hide */
2135    @IntDef({
2136        TEXT_ALIGNMENT_INHERIT,
2137        TEXT_ALIGNMENT_GRAVITY,
2138        TEXT_ALIGNMENT_CENTER,
2139        TEXT_ALIGNMENT_TEXT_START,
2140        TEXT_ALIGNMENT_TEXT_END,
2141        TEXT_ALIGNMENT_VIEW_START,
2142        TEXT_ALIGNMENT_VIEW_END
2143    })
2144    @Retention(RetentionPolicy.SOURCE)
2145    public @interface TextAlignment {}
2146
2147    /**
2148     * Default text alignment. The text alignment of this View is inherited from its parent.
2149     * Use with {@link #setTextAlignment(int)}
2150     */
2151    public static final int TEXT_ALIGNMENT_INHERIT = 0;
2152
2153    /**
2154     * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
2155     * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
2156     *
2157     * Use with {@link #setTextAlignment(int)}
2158     */
2159    public static final int TEXT_ALIGNMENT_GRAVITY = 1;
2160
2161    /**
2162     * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
2163     *
2164     * Use with {@link #setTextAlignment(int)}
2165     */
2166    public static final int TEXT_ALIGNMENT_TEXT_START = 2;
2167
2168    /**
2169     * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
2170     *
2171     * Use with {@link #setTextAlignment(int)}
2172     */
2173    public static final int TEXT_ALIGNMENT_TEXT_END = 3;
2174
2175    /**
2176     * Center the paragraph, e.g. ALIGN_CENTER.
2177     *
2178     * Use with {@link #setTextAlignment(int)}
2179     */
2180    public static final int TEXT_ALIGNMENT_CENTER = 4;
2181
2182    /**
2183     * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
2184     * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
2185     *
2186     * Use with {@link #setTextAlignment(int)}
2187     */
2188    public static final int TEXT_ALIGNMENT_VIEW_START = 5;
2189
2190    /**
2191     * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
2192     * layoutDirection is LTR, and ALIGN_LEFT otherwise.
2193     *
2194     * Use with {@link #setTextAlignment(int)}
2195     */
2196    public static final int TEXT_ALIGNMENT_VIEW_END = 6;
2197
2198    /**
2199     * Default text alignment is inherited
2200     */
2201    private static final int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2202
2203    /**
2204     * Default resolved text alignment
2205     * @hide
2206     */
2207    static final int TEXT_ALIGNMENT_RESOLVED_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
2208
2209    /**
2210      * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
2211      * @hide
2212      */
2213    static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
2214
2215    /**
2216      * Mask for use with private flags indicating bits used for text alignment.
2217      * @hide
2218      */
2219    static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2220
2221    /**
2222     * Array of text direction flags for mapping attribute "textAlignment" to correct
2223     * flag value.
2224     * @hide
2225     */
2226    private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
2227            TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2228            TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2229            TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2230            TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2231            TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2232            TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2233            TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
2234    };
2235
2236    /**
2237     * Indicates whether the view text alignment has been resolved.
2238     * @hide
2239     */
2240    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
2241
2242    /**
2243     * Bit shift to get the resolved text alignment.
2244     * @hide
2245     */
2246    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
2247
2248    /**
2249     * Mask for use with private flags indicating bits used for text alignment.
2250     * @hide
2251     */
2252    static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2253            << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2254
2255    /**
2256     * Indicates whether if the view text alignment has been resolved to gravity
2257     */
2258    private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2259            TEXT_ALIGNMENT_RESOLVED_DEFAULT << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
2260
2261    // Accessiblity constants for mPrivateFlags2
2262
2263    /**
2264     * Shift for the bits in {@link #mPrivateFlags2} related to the
2265     * "importantForAccessibility" attribute.
2266     */
2267    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
2268
2269    /**
2270     * Automatically determine whether a view is important for accessibility.
2271     */
2272    public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2273
2274    /**
2275     * The view is important for accessibility.
2276     */
2277    public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2278
2279    /**
2280     * The view is not important for accessibility.
2281     */
2282    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2283
2284    /**
2285     * The view is not important for accessibility, nor are any of its
2286     * descendant views.
2287     */
2288    public static final int IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS = 0x00000004;
2289
2290    /**
2291     * The default whether the view is important for accessibility.
2292     */
2293    static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2294
2295    /**
2296     * Mask for obtainig the bits which specify how to determine
2297     * whether a view is important for accessibility.
2298     */
2299    static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
2300        | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO
2301        | IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS)
2302        << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
2303
2304    /**
2305     * Shift for the bits in {@link #mPrivateFlags2} related to the
2306     * "accessibilityLiveRegion" attribute.
2307     */
2308    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT = 23;
2309
2310    /**
2311     * Live region mode specifying that accessibility services should not
2312     * automatically announce changes to this view. This is the default live
2313     * region mode for most views.
2314     * <p>
2315     * Use with {@link #setAccessibilityLiveRegion(int)}.
2316     */
2317    public static final int ACCESSIBILITY_LIVE_REGION_NONE = 0x00000000;
2318
2319    /**
2320     * Live region mode specifying that accessibility services should announce
2321     * changes to this view.
2322     * <p>
2323     * Use with {@link #setAccessibilityLiveRegion(int)}.
2324     */
2325    public static final int ACCESSIBILITY_LIVE_REGION_POLITE = 0x00000001;
2326
2327    /**
2328     * Live region mode specifying that accessibility services should interrupt
2329     * ongoing speech to immediately announce changes to this view.
2330     * <p>
2331     * Use with {@link #setAccessibilityLiveRegion(int)}.
2332     */
2333    public static final int ACCESSIBILITY_LIVE_REGION_ASSERTIVE = 0x00000002;
2334
2335    /**
2336     * The default whether the view is important for accessibility.
2337     */
2338    static final int ACCESSIBILITY_LIVE_REGION_DEFAULT = ACCESSIBILITY_LIVE_REGION_NONE;
2339
2340    /**
2341     * Mask for obtaining the bits which specify a view's accessibility live
2342     * region mode.
2343     */
2344    static final int PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK = (ACCESSIBILITY_LIVE_REGION_NONE
2345            | ACCESSIBILITY_LIVE_REGION_POLITE | ACCESSIBILITY_LIVE_REGION_ASSERTIVE)
2346            << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
2347
2348    /**
2349     * Flag indicating whether a view has accessibility focus.
2350     */
2351    static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x04000000;
2352
2353    /**
2354     * Flag whether the accessibility state of the subtree rooted at this view changed.
2355     */
2356    static final int PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED = 0x08000000;
2357
2358    /**
2359     * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2360     * is used to check whether later changes to the view's transform should invalidate the
2361     * view to force the quickReject test to run again.
2362     */
2363    static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
2364
2365    /**
2366     * Flag indicating that start/end padding has been resolved into left/right padding
2367     * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2368     * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2369     * during measurement. In some special cases this is required such as when an adapter-based
2370     * view measures prospective children without attaching them to a window.
2371     */
2372    static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
2373
2374    /**
2375     * Flag indicating that the start/end drawables has been resolved into left/right ones.
2376     */
2377    static final int PFLAG2_DRAWABLE_RESOLVED = 0x40000000;
2378
2379    /**
2380     * Indicates that the view is tracking some sort of transient state
2381     * that the app should not need to be aware of, but that the framework
2382     * should take special care to preserve.
2383     */
2384    static final int PFLAG2_HAS_TRANSIENT_STATE = 0x80000000;
2385
2386    /**
2387     * Group of bits indicating that RTL properties resolution is done.
2388     */
2389    static final int ALL_RTL_PROPERTIES_RESOLVED = PFLAG2_LAYOUT_DIRECTION_RESOLVED |
2390            PFLAG2_TEXT_DIRECTION_RESOLVED |
2391            PFLAG2_TEXT_ALIGNMENT_RESOLVED |
2392            PFLAG2_PADDING_RESOLVED |
2393            PFLAG2_DRAWABLE_RESOLVED;
2394
2395    // There are a couple of flags left in mPrivateFlags2
2396
2397    /* End of masks for mPrivateFlags2 */
2398
2399    /**
2400     * Masks for mPrivateFlags3, as generated by dumpFlags():
2401     *
2402     * |-------|-------|-------|-------|
2403     *                                 1 PFLAG3_VIEW_IS_ANIMATING_TRANSFORM
2404     *                                1  PFLAG3_VIEW_IS_ANIMATING_ALPHA
2405     *                               1   PFLAG3_IS_LAID_OUT
2406     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
2407     *                             1     PFLAG3_CALLED_SUPER
2408     *                            1      PFLAG3_APPLYING_INSETS
2409     *                           1       PFLAG3_FITTING_SYSTEM_WINDOWS
2410     *                          1        PFLAG3_NESTED_SCROLLING_ENABLED
2411     *                         1         PFLAG3_SCROLL_INDICATOR_TOP
2412     *                        1          PFLAG3_SCROLL_INDICATOR_BOTTOM
2413     *                       1           PFLAG3_SCROLL_INDICATOR_LEFT
2414     *                      1            PFLAG3_SCROLL_INDICATOR_RIGHT
2415     *                     1             PFLAG3_SCROLL_INDICATOR_START
2416     *                    1              PFLAG3_SCROLL_INDICATOR_END
2417     *                   1               PFLAG3_ASSIST_BLOCKED
2418     *            1111111                PFLAG3_POINTER_ICON_MASK
2419     * |-------|-------|-------|-------|
2420     */
2421
2422    /**
2423     * Flag indicating that view has a transform animation set on it. This is used to track whether
2424     * an animation is cleared between successive frames, in order to tell the associated
2425     * DisplayList to clear its animation matrix.
2426     */
2427    static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
2428
2429    /**
2430     * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2431     * animation is cleared between successive frames, in order to tell the associated
2432     * DisplayList to restore its alpha value.
2433     */
2434    static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
2435
2436    /**
2437     * Flag indicating that the view has been through at least one layout since it
2438     * was last attached to a window.
2439     */
2440    static final int PFLAG3_IS_LAID_OUT = 0x4;
2441
2442    /**
2443     * Flag indicating that a call to measure() was skipped and should be done
2444     * instead when layout() is invoked.
2445     */
2446    static final int PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT = 0x8;
2447
2448    /**
2449     * Flag indicating that an overridden method correctly called down to
2450     * the superclass implementation as required by the API spec.
2451     */
2452    static final int PFLAG3_CALLED_SUPER = 0x10;
2453
2454    /**
2455     * Flag indicating that we're in the process of applying window insets.
2456     */
2457    static final int PFLAG3_APPLYING_INSETS = 0x20;
2458
2459    /**
2460     * Flag indicating that we're in the process of fitting system windows using the old method.
2461     */
2462    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x40;
2463
2464    /**
2465     * Flag indicating that nested scrolling is enabled for this view.
2466     * The view will optionally cooperate with views up its parent chain to allow for
2467     * integrated nested scrolling along the same axis.
2468     */
2469    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x80;
2470
2471    /**
2472     * Flag indicating that the bottom scroll indicator should be displayed
2473     * when this view can scroll up.
2474     */
2475    static final int PFLAG3_SCROLL_INDICATOR_TOP = 0x0100;
2476
2477    /**
2478     * Flag indicating that the bottom scroll indicator should be displayed
2479     * when this view can scroll down.
2480     */
2481    static final int PFLAG3_SCROLL_INDICATOR_BOTTOM = 0x0200;
2482
2483    /**
2484     * Flag indicating that the left scroll indicator should be displayed
2485     * when this view can scroll left.
2486     */
2487    static final int PFLAG3_SCROLL_INDICATOR_LEFT = 0x0400;
2488
2489    /**
2490     * Flag indicating that the right scroll indicator should be displayed
2491     * when this view can scroll right.
2492     */
2493    static final int PFLAG3_SCROLL_INDICATOR_RIGHT = 0x0800;
2494
2495    /**
2496     * Flag indicating that the start scroll indicator should be displayed
2497     * when this view can scroll in the start direction.
2498     */
2499    static final int PFLAG3_SCROLL_INDICATOR_START = 0x1000;
2500
2501    /**
2502     * Flag indicating that the end scroll indicator should be displayed
2503     * when this view can scroll in the end direction.
2504     */
2505    static final int PFLAG3_SCROLL_INDICATOR_END = 0x2000;
2506
2507    /* End of masks for mPrivateFlags3 */
2508
2509    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
2510
2511    static final int SCROLL_INDICATORS_NONE = 0x0000;
2512
2513    /**
2514     * Mask for use with setFlags indicating bits used for indicating which
2515     * scroll indicators are enabled.
2516     */
2517    static final int SCROLL_INDICATORS_PFLAG3_MASK = PFLAG3_SCROLL_INDICATOR_TOP
2518            | PFLAG3_SCROLL_INDICATOR_BOTTOM | PFLAG3_SCROLL_INDICATOR_LEFT
2519            | PFLAG3_SCROLL_INDICATOR_RIGHT | PFLAG3_SCROLL_INDICATOR_START
2520            | PFLAG3_SCROLL_INDICATOR_END;
2521
2522    /**
2523     * Left-shift required to translate between public scroll indicator flags
2524     * and internal PFLAGS3 flags. When used as a right-shift, translates
2525     * PFLAGS3 flags to public flags.
2526     */
2527    static final int SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT = 8;
2528
2529    /** @hide */
2530    @Retention(RetentionPolicy.SOURCE)
2531    @IntDef(flag = true,
2532            value = {
2533                    SCROLL_INDICATOR_TOP,
2534                    SCROLL_INDICATOR_BOTTOM,
2535                    SCROLL_INDICATOR_LEFT,
2536                    SCROLL_INDICATOR_RIGHT,
2537                    SCROLL_INDICATOR_START,
2538                    SCROLL_INDICATOR_END,
2539            })
2540    public @interface ScrollIndicators {}
2541
2542    /**
2543     * Scroll indicator direction for the top edge of the view.
2544     *
2545     * @see #setScrollIndicators(int)
2546     * @see #setScrollIndicators(int, int)
2547     * @see #getScrollIndicators()
2548     */
2549    public static final int SCROLL_INDICATOR_TOP =
2550            PFLAG3_SCROLL_INDICATOR_TOP >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2551
2552    /**
2553     * Scroll indicator direction for the bottom edge of the view.
2554     *
2555     * @see #setScrollIndicators(int)
2556     * @see #setScrollIndicators(int, int)
2557     * @see #getScrollIndicators()
2558     */
2559    public static final int SCROLL_INDICATOR_BOTTOM =
2560            PFLAG3_SCROLL_INDICATOR_BOTTOM >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2561
2562    /**
2563     * Scroll indicator direction for the left edge of the view.
2564     *
2565     * @see #setScrollIndicators(int)
2566     * @see #setScrollIndicators(int, int)
2567     * @see #getScrollIndicators()
2568     */
2569    public static final int SCROLL_INDICATOR_LEFT =
2570            PFLAG3_SCROLL_INDICATOR_LEFT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2571
2572    /**
2573     * Scroll indicator direction for the right edge of the view.
2574     *
2575     * @see #setScrollIndicators(int)
2576     * @see #setScrollIndicators(int, int)
2577     * @see #getScrollIndicators()
2578     */
2579    public static final int SCROLL_INDICATOR_RIGHT =
2580            PFLAG3_SCROLL_INDICATOR_RIGHT >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2581
2582    /**
2583     * Scroll indicator direction for the starting edge of the view.
2584     * <p>
2585     * Resolved according to the view's layout direction, see
2586     * {@link #getLayoutDirection()} for more information.
2587     *
2588     * @see #setScrollIndicators(int)
2589     * @see #setScrollIndicators(int, int)
2590     * @see #getScrollIndicators()
2591     */
2592    public static final int SCROLL_INDICATOR_START =
2593            PFLAG3_SCROLL_INDICATOR_START >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2594
2595    /**
2596     * Scroll indicator direction for the ending edge of the view.
2597     * <p>
2598     * Resolved according to the view's layout direction, see
2599     * {@link #getLayoutDirection()} for more information.
2600     *
2601     * @see #setScrollIndicators(int)
2602     * @see #setScrollIndicators(int, int)
2603     * @see #getScrollIndicators()
2604     */
2605    public static final int SCROLL_INDICATOR_END =
2606            PFLAG3_SCROLL_INDICATOR_END >> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
2607
2608    /**
2609     * <p>Indicates that we are allowing {@link ViewStructure} to traverse
2610     * into this view.<p>
2611     */
2612    static final int PFLAG3_ASSIST_BLOCKED = 0x4000;
2613
2614    /**
2615     * The mask for use with private flags indicating bits used for pointer icon shapes.
2616     */
2617    static final int PFLAG3_POINTER_ICON_MASK = 0x7f8000;
2618
2619    /**
2620     * Left-shift used for pointer icon shape values in private flags.
2621     */
2622    static final int PFLAG3_POINTER_ICON_LSHIFT = 15;
2623
2624    /**
2625     * Value indicating {@link PointerIcon.STYLE_NOT_SPECIFIED}.
2626     */
2627    private static final int PFLAG3_POINTER_ICON_NOT_SPECIFIED = 0 << PFLAG3_POINTER_ICON_LSHIFT;
2628
2629    /**
2630     * Value indicating {@link PointerIcon.STYLE_NULL}.
2631     */
2632    private static final int PFLAG3_POINTER_ICON_NULL = 1 << PFLAG3_POINTER_ICON_LSHIFT;
2633
2634    /**
2635     * Value incicating {@link PointerIcon.STYLE_CUSTOM}.
2636     */
2637    private static final int PFLAG3_POINTER_ICON_CUSTOM = 2 << PFLAG3_POINTER_ICON_LSHIFT;
2638
2639    /**
2640     * The base value for other pointer icon shapes.
2641     */
2642    private static final int PFLAG3_POINTER_ICON_VALUE_START = 3 << PFLAG3_POINTER_ICON_LSHIFT;
2643
2644    /**
2645     * Always allow a user to over-scroll this view, provided it is a
2646     * view that can scroll.
2647     *
2648     * @see #getOverScrollMode()
2649     * @see #setOverScrollMode(int)
2650     */
2651    public static final int OVER_SCROLL_ALWAYS = 0;
2652
2653    /**
2654     * Allow a user to over-scroll this view only if the content is large
2655     * enough to meaningfully scroll, provided it is a view that can scroll.
2656     *
2657     * @see #getOverScrollMode()
2658     * @see #setOverScrollMode(int)
2659     */
2660    public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2661
2662    /**
2663     * Never allow a user to over-scroll this view.
2664     *
2665     * @see #getOverScrollMode()
2666     * @see #setOverScrollMode(int)
2667     */
2668    public static final int OVER_SCROLL_NEVER = 2;
2669
2670    /**
2671     * Special constant for {@link #setSystemUiVisibility(int)}: View has
2672     * requested the system UI (status bar) to be visible (the default).
2673     *
2674     * @see #setSystemUiVisibility(int)
2675     */
2676    public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
2677
2678    /**
2679     * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2680     * system UI to enter an unobtrusive "low profile" mode.
2681     *
2682     * <p>This is for use in games, book readers, video players, or any other
2683     * "immersive" application where the usual system chrome is deemed too distracting.
2684     *
2685     * <p>In low profile mode, the status bar and/or navigation icons may dim.
2686     *
2687     * @see #setSystemUiVisibility(int)
2688     */
2689    public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2690
2691    /**
2692     * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2693     * system navigation be temporarily hidden.
2694     *
2695     * <p>This is an even less obtrusive state than that called for by
2696     * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2697     * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2698     * those to disappear. This is useful (in conjunction with the
2699     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
2700     * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2701     * window flags) for displaying content using every last pixel on the display.
2702     *
2703     * <p>There is a limitation: because navigation controls are so important, the least user
2704     * interaction will cause them to reappear immediately.  When this happens, both
2705     * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2706     * so that both elements reappear at the same time.
2707     *
2708     * @see #setSystemUiVisibility(int)
2709     */
2710    public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2711
2712    /**
2713     * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2714     * into the normal fullscreen mode so that its content can take over the screen
2715     * while still allowing the user to interact with the application.
2716     *
2717     * <p>This has the same visual effect as
2718     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2719     * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2720     * meaning that non-critical screen decorations (such as the status bar) will be
2721     * hidden while the user is in the View's window, focusing the experience on
2722     * that content.  Unlike the window flag, if you are using ActionBar in
2723     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2724     * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2725     * hide the action bar.
2726     *
2727     * <p>This approach to going fullscreen is best used over the window flag when
2728     * it is a transient state -- that is, the application does this at certain
2729     * points in its user interaction where it wants to allow the user to focus
2730     * on content, but not as a continuous state.  For situations where the application
2731     * would like to simply stay full screen the entire time (such as a game that
2732     * wants to take over the screen), the
2733     * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2734     * is usually a better approach.  The state set here will be removed by the system
2735     * in various situations (such as the user moving to another application) like
2736     * the other system UI states.
2737     *
2738     * <p>When using this flag, the application should provide some easy facility
2739     * for the user to go out of it.  A common example would be in an e-book
2740     * reader, where tapping on the screen brings back whatever screen and UI
2741     * decorations that had been hidden while the user was immersed in reading
2742     * the book.
2743     *
2744     * @see #setSystemUiVisibility(int)
2745     */
2746    public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2747
2748    /**
2749     * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2750     * flags, we would like a stable view of the content insets given to
2751     * {@link #fitSystemWindows(Rect)}.  This means that the insets seen there
2752     * will always represent the worst case that the application can expect
2753     * as a continuous state.  In the stock Android UI this is the space for
2754     * the system bar, nav bar, and status bar, but not more transient elements
2755     * such as an input method.
2756     *
2757     * The stable layout your UI sees is based on the system UI modes you can
2758     * switch to.  That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2759     * then you will get a stable layout for changes of the
2760     * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2761     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2762     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2763     * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2764     * with a stable layout.  (Note that you should avoid using
2765     * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2766     *
2767     * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
2768     * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2769     * then a hidden status bar will be considered a "stable" state for purposes
2770     * here.  This allows your UI to continually hide the status bar, while still
2771     * using the system UI flags to hide the action bar while still retaining
2772     * a stable layout.  Note that changing the window fullscreen flag will never
2773     * provide a stable layout for a clean transition.
2774     *
2775     * <p>If you are using ActionBar in
2776     * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2777     * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2778     * insets it adds to those given to the application.
2779     */
2780    public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2781
2782    /**
2783     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2784     * to be laid out as if it has requested
2785     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't.  This
2786     * allows it to avoid artifacts when switching in and out of that mode, at
2787     * the expense that some of its user interface may be covered by screen
2788     * decorations when they are shown.  You can perform layout of your inner
2789     * UI elements to account for the navigation system UI through the
2790     * {@link #fitSystemWindows(Rect)} method.
2791     */
2792    public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2793
2794    /**
2795     * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2796     * to be laid out as if it has requested
2797     * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't.  This
2798     * allows it to avoid artifacts when switching in and out of that mode, at
2799     * the expense that some of its user interface may be covered by screen
2800     * decorations when they are shown.  You can perform layout of your inner
2801     * UI elements to account for non-fullscreen system UI through the
2802     * {@link #fitSystemWindows(Rect)} method.
2803     */
2804    public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2805
2806    /**
2807     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2808     * hiding the navigation bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  If this flag is
2809     * not set, {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any
2810     * user interaction.
2811     * <p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only
2812     * has an effect when used in combination with that flag.</p>
2813     */
2814    public static final int SYSTEM_UI_FLAG_IMMERSIVE = 0x00000800;
2815
2816    /**
2817     * Flag for {@link #setSystemUiVisibility(int)}: View would like to remain interactive when
2818     * hiding the status bar with {@link #SYSTEM_UI_FLAG_FULLSCREEN} and/or hiding the navigation
2819     * bar with {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}.  Use this flag to create an immersive
2820     * experience while also hiding the system bars.  If this flag is not set,
2821     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION} will be force cleared by the system on any user
2822     * interaction, and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be force-cleared by the system
2823     * if the user swipes from the top of the screen.
2824     * <p>When system bars are hidden in immersive mode, they can be revealed temporarily with
2825     * system gestures, such as swiping from the top of the screen.  These transient system bars
2826     * will overlay app’s content, may have some degree of transparency, and will automatically
2827     * hide after a short timeout.
2828     * </p><p>Since this flag is a modifier for {@link #SYSTEM_UI_FLAG_FULLSCREEN} and
2829     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, it only has an effect when used in combination
2830     * with one or both of those flags.</p>
2831     */
2832    public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
2833
2834    /**
2835     * Flag for {@link #setSystemUiVisibility(int)}: Requests the status bar to draw in a mode that
2836     * is compatible with light status bar backgrounds.
2837     *
2838     * <p>For this to take effect, the window must request
2839     * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
2840     *         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} but not
2841     * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_STATUS
2842     *         FLAG_TRANSLUCENT_STATUS}.
2843     *
2844     * @see android.R.attr#windowLightStatusBar
2845     */
2846    public static final int SYSTEM_UI_FLAG_LIGHT_STATUS_BAR = 0x00002000;
2847
2848    /**
2849     * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2850     */
2851    public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2852
2853    /**
2854     * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2855     */
2856    public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
2857
2858    /**
2859     * @hide
2860     *
2861     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2862     * out of the public fields to keep the undefined bits out of the developer's way.
2863     *
2864     * Flag to make the status bar not expandable.  Unless you also
2865     * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2866     */
2867    public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2868
2869    /**
2870     * @hide
2871     *
2872     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2873     * out of the public fields to keep the undefined bits out of the developer's way.
2874     *
2875     * Flag to hide notification icons and scrolling ticker text.
2876     */
2877    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2878
2879    /**
2880     * @hide
2881     *
2882     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2883     * out of the public fields to keep the undefined bits out of the developer's way.
2884     *
2885     * Flag to disable incoming notification alerts.  This will not block
2886     * icons, but it will block sound, vibrating and other visual or aural notifications.
2887     */
2888    public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2889
2890    /**
2891     * @hide
2892     *
2893     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2894     * out of the public fields to keep the undefined bits out of the developer's way.
2895     *
2896     * Flag to hide only the scrolling ticker.  Note that
2897     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2898     * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2899     */
2900    public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2901
2902    /**
2903     * @hide
2904     *
2905     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2906     * out of the public fields to keep the undefined bits out of the developer's way.
2907     *
2908     * Flag to hide the center system info area.
2909     */
2910    public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2911
2912    /**
2913     * @hide
2914     *
2915     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2916     * out of the public fields to keep the undefined bits out of the developer's way.
2917     *
2918     * Flag to hide only the home button.  Don't use this
2919     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2920     */
2921    public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
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 hide only the back button. Don't use this
2930     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2931     */
2932    public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2933
2934    /**
2935     * @hide
2936     *
2937     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2938     * out of the public fields to keep the undefined bits out of the developer's way.
2939     *
2940     * Flag to hide only the clock.  You might use this if your activity has
2941     * its own clock making the status bar's clock redundant.
2942     */
2943    public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2944
2945    /**
2946     * @hide
2947     *
2948     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2949     * out of the public fields to keep the undefined bits out of the developer's way.
2950     *
2951     * Flag to hide only the recent apps button. Don't use this
2952     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2953     */
2954    public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2955
2956    /**
2957     * @hide
2958     *
2959     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2960     * out of the public fields to keep the undefined bits out of the developer's way.
2961     *
2962     * Flag to disable the global search gesture. Don't use this
2963     * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2964     */
2965    public static final int STATUS_BAR_DISABLE_SEARCH = 0x02000000;
2966
2967    /**
2968     * @hide
2969     *
2970     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2971     * out of the public fields to keep the undefined bits out of the developer's way.
2972     *
2973     * Flag to specify that the status bar is displayed in transient mode.
2974     */
2975    public static final int STATUS_BAR_TRANSIENT = 0x04000000;
2976
2977    /**
2978     * @hide
2979     *
2980     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2981     * out of the public fields to keep the undefined bits out of the developer's way.
2982     *
2983     * Flag to specify that the navigation bar is displayed in transient mode.
2984     */
2985    public static final int NAVIGATION_BAR_TRANSIENT = 0x08000000;
2986
2987    /**
2988     * @hide
2989     *
2990     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2991     * out of the public fields to keep the undefined bits out of the developer's way.
2992     *
2993     * Flag to specify that the hidden status bar would like to be shown.
2994     */
2995    public static final int STATUS_BAR_UNHIDE = 0x10000000;
2996
2997    /**
2998     * @hide
2999     *
3000     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3001     * out of the public fields to keep the undefined bits out of the developer's way.
3002     *
3003     * Flag to specify that the hidden navigation bar would like to be shown.
3004     */
3005    public static final int NAVIGATION_BAR_UNHIDE = 0x20000000;
3006
3007    /**
3008     * @hide
3009     *
3010     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3011     * out of the public fields to keep the undefined bits out of the developer's way.
3012     *
3013     * Flag to specify that the status bar is displayed in translucent mode.
3014     */
3015    public static final int STATUS_BAR_TRANSLUCENT = 0x40000000;
3016
3017    /**
3018     * @hide
3019     *
3020     * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
3021     * out of the public fields to keep the undefined bits out of the developer's way.
3022     *
3023     * Flag to specify that the navigation bar is displayed in translucent mode.
3024     */
3025    public static final int NAVIGATION_BAR_TRANSLUCENT = 0x80000000;
3026
3027    /**
3028     * @hide
3029     *
3030     * Whether Recents is visible or not.
3031     */
3032    public static final int RECENT_APPS_VISIBLE = 0x00004000;
3033
3034    /**
3035     * @hide
3036     *
3037     * Makes system ui transparent.
3038     */
3039    public static final int SYSTEM_UI_TRANSPARENT = 0x00008000;
3040
3041    /**
3042     * @hide
3043     */
3044    public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x00003FFF;
3045
3046    /**
3047     * These are the system UI flags that can be cleared by events outside
3048     * of an application.  Currently this is just the ability to tap on the
3049     * screen while hiding the navigation bar to have it return.
3050     * @hide
3051     */
3052    public static final int SYSTEM_UI_CLEARABLE_FLAGS =
3053            SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
3054            | SYSTEM_UI_FLAG_FULLSCREEN;
3055
3056    /**
3057     * Flags that can impact the layout in relation to system UI.
3058     */
3059    public static final int SYSTEM_UI_LAYOUT_FLAGS =
3060            SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
3061            | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
3062
3063    /** @hide */
3064    @IntDef(flag = true,
3065            value = { FIND_VIEWS_WITH_TEXT, FIND_VIEWS_WITH_CONTENT_DESCRIPTION })
3066    @Retention(RetentionPolicy.SOURCE)
3067    public @interface FindViewFlags {}
3068
3069    /**
3070     * Find views that render the specified text.
3071     *
3072     * @see #findViewsWithText(ArrayList, CharSequence, int)
3073     */
3074    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
3075
3076    /**
3077     * Find find views that contain the specified content description.
3078     *
3079     * @see #findViewsWithText(ArrayList, CharSequence, int)
3080     */
3081    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
3082
3083    /**
3084     * Find views that contain {@link AccessibilityNodeProvider}. Such
3085     * a View is a root of virtual view hierarchy and may contain the searched
3086     * text. If this flag is set Views with providers are automatically
3087     * added and it is a responsibility of the client to call the APIs of
3088     * the provider to determine whether the virtual tree rooted at this View
3089     * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
3090     * representing the virtual views with this text.
3091     *
3092     * @see #findViewsWithText(ArrayList, CharSequence, int)
3093     *
3094     * @hide
3095     */
3096    public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
3097
3098    /**
3099     * The undefined cursor position.
3100     *
3101     * @hide
3102     */
3103    public static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
3104
3105    /**
3106     * Indicates that the screen has changed state and is now off.
3107     *
3108     * @see #onScreenStateChanged(int)
3109     */
3110    public static final int SCREEN_STATE_OFF = 0x0;
3111
3112    /**
3113     * Indicates that the screen has changed state and is now on.
3114     *
3115     * @see #onScreenStateChanged(int)
3116     */
3117    public static final int SCREEN_STATE_ON = 0x1;
3118
3119    /**
3120     * Indicates no axis of view scrolling.
3121     */
3122    public static final int SCROLL_AXIS_NONE = 0;
3123
3124    /**
3125     * Indicates scrolling along the horizontal axis.
3126     */
3127    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
3128
3129    /**
3130     * Indicates scrolling along the vertical axis.
3131     */
3132    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
3133
3134    /**
3135     * Controls the over-scroll mode for this view.
3136     * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
3137     * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
3138     * and {@link #OVER_SCROLL_NEVER}.
3139     */
3140    private int mOverScrollMode;
3141
3142    /**
3143     * The parent this view is attached to.
3144     * {@hide}
3145     *
3146     * @see #getParent()
3147     */
3148    protected ViewParent mParent;
3149
3150    /**
3151     * {@hide}
3152     */
3153    AttachInfo mAttachInfo;
3154
3155    /**
3156     * {@hide}
3157     */
3158    @ViewDebug.ExportedProperty(flagMapping = {
3159        @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
3160                name = "FORCE_LAYOUT"),
3161        @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
3162                name = "LAYOUT_REQUIRED"),
3163        @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
3164            name = "DRAWING_CACHE_INVALID", outputIf = false),
3165        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
3166        @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
3167        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
3168        @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
3169    }, formatToHexString = true)
3170    int mPrivateFlags;
3171    int mPrivateFlags2;
3172    int mPrivateFlags3;
3173
3174    /**
3175     * This view's request for the visibility of the status bar.
3176     * @hide
3177     */
3178    @ViewDebug.ExportedProperty(flagMapping = {
3179        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
3180                                equals = SYSTEM_UI_FLAG_LOW_PROFILE,
3181                                name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
3182        @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3183                                equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
3184                                name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
3185        @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
3186                                equals = SYSTEM_UI_FLAG_VISIBLE,
3187                                name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
3188    }, formatToHexString = true)
3189    int mSystemUiVisibility;
3190
3191    /**
3192     * Reference count for transient state.
3193     * @see #setHasTransientState(boolean)
3194     */
3195    int mTransientStateCount = 0;
3196
3197    /**
3198     * Count of how many windows this view has been attached to.
3199     */
3200    int mWindowAttachCount;
3201
3202    /**
3203     * The layout parameters associated with this view and used by the parent
3204     * {@link android.view.ViewGroup} to determine how this view should be
3205     * laid out.
3206     * {@hide}
3207     */
3208    protected ViewGroup.LayoutParams mLayoutParams;
3209
3210    /**
3211     * The view flags hold various views states.
3212     * {@hide}
3213     */
3214    @ViewDebug.ExportedProperty(formatToHexString = true)
3215    int mViewFlags;
3216
3217    static class TransformationInfo {
3218        /**
3219         * The transform matrix for the View. This transform is calculated internally
3220         * based on the translation, rotation, and scale properties.
3221         *
3222         * Do *not* use this variable directly; instead call getMatrix(), which will
3223         * load the value from the View's RenderNode.
3224         */
3225        private final Matrix mMatrix = new Matrix();
3226
3227        /**
3228         * The inverse transform matrix for the View. This transform is calculated
3229         * internally based on the translation, rotation, and scale properties.
3230         *
3231         * Do *not* use this variable directly; instead call getInverseMatrix(),
3232         * which will load the value from the View's RenderNode.
3233         */
3234        private Matrix mInverseMatrix;
3235
3236        /**
3237         * The opacity of the View. This is a value from 0 to 1, where 0 means
3238         * completely transparent and 1 means completely opaque.
3239         */
3240        @ViewDebug.ExportedProperty
3241        float mAlpha = 1f;
3242
3243        /**
3244         * The opacity of the view as manipulated by the Fade transition. This is a hidden
3245         * property only used by transitions, which is composited with the other alpha
3246         * values to calculate the final visual alpha value.
3247         */
3248        float mTransitionAlpha = 1f;
3249    }
3250
3251    TransformationInfo mTransformationInfo;
3252
3253    /**
3254     * Current clip bounds. to which all drawing of this view are constrained.
3255     */
3256    Rect mClipBounds = null;
3257
3258    private boolean mLastIsOpaque;
3259
3260    /**
3261     * The distance in pixels from the left edge of this view's parent
3262     * to the left edge of this view.
3263     * {@hide}
3264     */
3265    @ViewDebug.ExportedProperty(category = "layout")
3266    protected int mLeft;
3267    /**
3268     * The distance in pixels from the left edge of this view's parent
3269     * to the right edge of this view.
3270     * {@hide}
3271     */
3272    @ViewDebug.ExportedProperty(category = "layout")
3273    protected int mRight;
3274    /**
3275     * The distance in pixels from the top edge of this view's parent
3276     * to the top edge of this view.
3277     * {@hide}
3278     */
3279    @ViewDebug.ExportedProperty(category = "layout")
3280    protected int mTop;
3281    /**
3282     * The distance in pixels from the top edge of this view's parent
3283     * to the bottom edge of this view.
3284     * {@hide}
3285     */
3286    @ViewDebug.ExportedProperty(category = "layout")
3287    protected int mBottom;
3288
3289    /**
3290     * The offset, in pixels, by which the content of this view is scrolled
3291     * horizontally.
3292     * {@hide}
3293     */
3294    @ViewDebug.ExportedProperty(category = "scrolling")
3295    protected int mScrollX;
3296    /**
3297     * The offset, in pixels, by which the content of this view is scrolled
3298     * vertically.
3299     * {@hide}
3300     */
3301    @ViewDebug.ExportedProperty(category = "scrolling")
3302    protected int mScrollY;
3303
3304    /**
3305     * The left padding in pixels, that is the distance in pixels between the
3306     * left edge of this view and the left edge of its content.
3307     * {@hide}
3308     */
3309    @ViewDebug.ExportedProperty(category = "padding")
3310    protected int mPaddingLeft = 0;
3311    /**
3312     * The right padding in pixels, that is the distance in pixels between the
3313     * right edge of this view and the right edge of its content.
3314     * {@hide}
3315     */
3316    @ViewDebug.ExportedProperty(category = "padding")
3317    protected int mPaddingRight = 0;
3318    /**
3319     * The top padding in pixels, that is the distance in pixels between the
3320     * top edge of this view and the top edge of its content.
3321     * {@hide}
3322     */
3323    @ViewDebug.ExportedProperty(category = "padding")
3324    protected int mPaddingTop;
3325    /**
3326     * The bottom padding in pixels, that is the distance in pixels between the
3327     * bottom edge of this view and the bottom edge of its content.
3328     * {@hide}
3329     */
3330    @ViewDebug.ExportedProperty(category = "padding")
3331    protected int mPaddingBottom;
3332
3333    /**
3334     * The layout insets in pixels, that is the distance in pixels between the
3335     * visible edges of this view its bounds.
3336     */
3337    private Insets mLayoutInsets;
3338
3339    /**
3340     * Briefly describes the view and is primarily used for accessibility support.
3341     */
3342    private CharSequence mContentDescription;
3343
3344    /**
3345     * Specifies the id of a view for which this view serves as a label for
3346     * accessibility purposes.
3347     */
3348    private int mLabelForId = View.NO_ID;
3349
3350    /**
3351     * Predicate for matching labeled view id with its label for
3352     * accessibility purposes.
3353     */
3354    private MatchLabelForPredicate mMatchLabelForPredicate;
3355
3356    /**
3357     * Specifies a view before which this one is visited in accessibility traversal.
3358     */
3359    private int mAccessibilityTraversalBeforeId = NO_ID;
3360
3361    /**
3362     * Specifies a view after which this one is visited in accessibility traversal.
3363     */
3364    private int mAccessibilityTraversalAfterId = NO_ID;
3365
3366    /**
3367     * Predicate for matching a view by its id.
3368     */
3369    private MatchIdPredicate mMatchIdPredicate;
3370
3371    /**
3372     * Cache the paddingRight set by the user to append to the scrollbar's size.
3373     *
3374     * @hide
3375     */
3376    @ViewDebug.ExportedProperty(category = "padding")
3377    protected int mUserPaddingRight;
3378
3379    /**
3380     * Cache the paddingBottom set by the user to append to the scrollbar's size.
3381     *
3382     * @hide
3383     */
3384    @ViewDebug.ExportedProperty(category = "padding")
3385    protected int mUserPaddingBottom;
3386
3387    /**
3388     * Cache the paddingLeft set by the user to append to the scrollbar's size.
3389     *
3390     * @hide
3391     */
3392    @ViewDebug.ExportedProperty(category = "padding")
3393    protected int mUserPaddingLeft;
3394
3395    /**
3396     * Cache the paddingStart set by the user to append to the scrollbar's size.
3397     *
3398     */
3399    @ViewDebug.ExportedProperty(category = "padding")
3400    int mUserPaddingStart;
3401
3402    /**
3403     * Cache the paddingEnd set by the user to append to the scrollbar's size.
3404     *
3405     */
3406    @ViewDebug.ExportedProperty(category = "padding")
3407    int mUserPaddingEnd;
3408
3409    /**
3410     * Cache initial left padding.
3411     *
3412     * @hide
3413     */
3414    int mUserPaddingLeftInitial;
3415
3416    /**
3417     * Cache initial right padding.
3418     *
3419     * @hide
3420     */
3421    int mUserPaddingRightInitial;
3422
3423    /**
3424     * Default undefined padding
3425     */
3426    private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
3427
3428    /**
3429     * Cache if a left padding has been defined
3430     */
3431    private boolean mLeftPaddingDefined = false;
3432
3433    /**
3434     * Cache if a right padding has been defined
3435     */
3436    private boolean mRightPaddingDefined = false;
3437
3438    /**
3439     * @hide
3440     */
3441    int mOldWidthMeasureSpec = Integer.MIN_VALUE;
3442    /**
3443     * @hide
3444     */
3445    int mOldHeightMeasureSpec = Integer.MIN_VALUE;
3446
3447    private LongSparseLongArray mMeasureCache;
3448
3449    @ViewDebug.ExportedProperty(deepExport = true, prefix = "bg_")
3450    private Drawable mBackground;
3451    private TintInfo mBackgroundTint;
3452
3453    @ViewDebug.ExportedProperty(deepExport = true, prefix = "fg_")
3454    private ForegroundInfo mForegroundInfo;
3455
3456    private Drawable mScrollIndicatorDrawable;
3457
3458    /**
3459     * RenderNode used for backgrounds.
3460     * <p>
3461     * When non-null and valid, this is expected to contain an up-to-date copy
3462     * of the background drawable. It is cleared on temporary detach, and reset
3463     * on cleanup.
3464     */
3465    private RenderNode mBackgroundRenderNode;
3466
3467    private int mBackgroundResource;
3468    private boolean mBackgroundSizeChanged;
3469
3470    private String mTransitionName;
3471
3472    static class TintInfo {
3473        ColorStateList mTintList;
3474        PorterDuff.Mode mTintMode;
3475        boolean mHasTintMode;
3476        boolean mHasTintList;
3477    }
3478
3479    private static class ForegroundInfo {
3480        private Drawable mDrawable;
3481        private TintInfo mTintInfo;
3482        private int mGravity = Gravity.FILL;
3483        private boolean mInsidePadding = true;
3484        private boolean mBoundsChanged = true;
3485        private final Rect mSelfBounds = new Rect();
3486        private final Rect mOverlayBounds = new Rect();
3487    }
3488
3489    static class ListenerInfo {
3490        /**
3491         * Listener used to dispatch focus change events.
3492         * This field should be made private, so it is hidden from the SDK.
3493         * {@hide}
3494         */
3495        protected OnFocusChangeListener mOnFocusChangeListener;
3496
3497        /**
3498         * Listeners for layout change events.
3499         */
3500        private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
3501
3502        protected OnScrollChangeListener mOnScrollChangeListener;
3503
3504        /**
3505         * Listeners for attach events.
3506         */
3507        private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
3508
3509        /**
3510         * Listener used to dispatch click events.
3511         * This field should be made private, so it is hidden from the SDK.
3512         * {@hide}
3513         */
3514        public OnClickListener mOnClickListener;
3515
3516        /**
3517         * Listener used to dispatch long click events.
3518         * This field should be made private, so it is hidden from the SDK.
3519         * {@hide}
3520         */
3521        protected OnLongClickListener mOnLongClickListener;
3522
3523        /**
3524         * Listener used to dispatch context click events. This field should be made private, so it
3525         * is hidden from the SDK.
3526         * {@hide}
3527         */
3528        protected OnContextClickListener mOnContextClickListener;
3529
3530        /**
3531         * Listener used to build the context menu.
3532         * This field should be made private, so it is hidden from the SDK.
3533         * {@hide}
3534         */
3535        protected OnCreateContextMenuListener mOnCreateContextMenuListener;
3536
3537        private OnKeyListener mOnKeyListener;
3538
3539        private OnTouchListener mOnTouchListener;
3540
3541        private OnHoverListener mOnHoverListener;
3542
3543        private OnGenericMotionListener mOnGenericMotionListener;
3544
3545        private OnDragListener mOnDragListener;
3546
3547        private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
3548
3549        OnApplyWindowInsetsListener mOnApplyWindowInsetsListener;
3550    }
3551
3552    ListenerInfo mListenerInfo;
3553
3554    // Temporary values used to hold (x,y) coordinates when delegating from the
3555    // two-arg performLongClick() method to the legacy no-arg version.
3556    private float mLongClickX = Float.NaN;
3557    private float mLongClickY = Float.NaN;
3558
3559    /**
3560     * The application environment this view lives in.
3561     * This field should be made private, so it is hidden from the SDK.
3562     * {@hide}
3563     */
3564    @ViewDebug.ExportedProperty(deepExport = true)
3565    protected Context mContext;
3566
3567    private final Resources mResources;
3568
3569    private ScrollabilityCache mScrollCache;
3570
3571    private int[] mDrawableState = null;
3572
3573    ViewOutlineProvider mOutlineProvider = ViewOutlineProvider.BACKGROUND;
3574
3575    /**
3576     * Animator that automatically runs based on state changes.
3577     */
3578    private StateListAnimator mStateListAnimator;
3579
3580    /**
3581     * When this view has focus and the next focus is {@link #FOCUS_LEFT},
3582     * the user may specify which view to go to next.
3583     */
3584    private int mNextFocusLeftId = View.NO_ID;
3585
3586    /**
3587     * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
3588     * the user may specify which view to go to next.
3589     */
3590    private int mNextFocusRightId = View.NO_ID;
3591
3592    /**
3593     * When this view has focus and the next focus is {@link #FOCUS_UP},
3594     * the user may specify which view to go to next.
3595     */
3596    private int mNextFocusUpId = View.NO_ID;
3597
3598    /**
3599     * When this view has focus and the next focus is {@link #FOCUS_DOWN},
3600     * the user may specify which view to go to next.
3601     */
3602    private int mNextFocusDownId = View.NO_ID;
3603
3604    /**
3605     * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
3606     * the user may specify which view to go to next.
3607     */
3608    int mNextFocusForwardId = View.NO_ID;
3609
3610    private CheckForLongPress mPendingCheckForLongPress;
3611    private CheckForTap mPendingCheckForTap = null;
3612    private PerformClick mPerformClick;
3613    private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
3614
3615    private UnsetPressedState mUnsetPressedState;
3616
3617    /**
3618     * Whether the long press's action has been invoked.  The tap's action is invoked on the
3619     * up event while a long press is invoked as soon as the long press duration is reached, so
3620     * a long press could be performed before the tap is checked, in which case the tap's action
3621     * should not be invoked.
3622     */
3623    private boolean mHasPerformedLongPress;
3624
3625    /**
3626     * Whether a context click button is currently pressed down. This is true when the stylus is
3627     * touching the screen and the primary button has been pressed, or if a mouse's right button is
3628     * pressed. This is false once the button is released or if the stylus has been lifted.
3629     */
3630    private boolean mInContextButtonPress;
3631
3632    /**
3633     * Whether the next up event should be ignored for the purposes of gesture recognition. This is
3634     * true after a stylus button press has occured, when the next up event should not be recognized
3635     * as a tap.
3636     */
3637    private boolean mIgnoreNextUpEvent;
3638
3639    /**
3640     * The minimum height of the view. We'll try our best to have the height
3641     * of this view to at least this amount.
3642     */
3643    @ViewDebug.ExportedProperty(category = "measurement")
3644    private int mMinHeight;
3645
3646    /**
3647     * The minimum width of the view. We'll try our best to have the width
3648     * of this view to at least this amount.
3649     */
3650    @ViewDebug.ExportedProperty(category = "measurement")
3651    private int mMinWidth;
3652
3653    /**
3654     * The delegate to handle touch events that are physically in this view
3655     * but should be handled by another view.
3656     */
3657    private TouchDelegate mTouchDelegate = null;
3658
3659    /**
3660     * Solid color to use as a background when creating the drawing cache. Enables
3661     * the cache to use 16 bit bitmaps instead of 32 bit.
3662     */
3663    private int mDrawingCacheBackgroundColor = 0;
3664
3665    /**
3666     * Special tree observer used when mAttachInfo is null.
3667     */
3668    private ViewTreeObserver mFloatingTreeObserver;
3669
3670    /**
3671     * Cache the touch slop from the context that created the view.
3672     */
3673    private int mTouchSlop;
3674
3675    /**
3676     * Object that handles automatic animation of view properties.
3677     */
3678    private ViewPropertyAnimator mAnimator = null;
3679
3680    /**
3681     * Flag indicating that a drag can cross window boundaries.  When
3682     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3683     * with this flag set, all visible applications will be able to participate
3684     * in the drag operation and receive the dragged content.
3685     *
3686     * If this is the only flag set, then the drag recipient will only have access to text data
3687     * and intents contained in the {@link ClipData} object. Access to URIs contained in the
3688     * {@link ClipData} is determined by other DRAG_FLAG_GLOBAL_* flags.
3689     */
3690    public static final int DRAG_FLAG_GLOBAL = 1 << 8;  // 256
3691
3692    /**
3693     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3694     * request read access to the content URI(s) contained in the {@link ClipData} object.
3695     * @see android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION
3696     */
3697    public static final int DRAG_FLAG_GLOBAL_URI_READ = Intent.FLAG_GRANT_READ_URI_PERMISSION;
3698
3699    /**
3700     * When this flag is used with {@link #DRAG_FLAG_GLOBAL}, the drag recipient will be able to
3701     * request write access to the content URI(s) contained in the {@link ClipData} object.
3702     * @see android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION
3703     */
3704    public static final int DRAG_FLAG_GLOBAL_URI_WRITE = Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
3705
3706    /**
3707     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3708     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant can be persisted across device
3709     * reboots until explicitly revoked with
3710     * {@link android.content.Context#revokeUriPermission(Uri,int) Context.revokeUriPermission}.
3711     * @see android.content.Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
3712     */
3713    public static final int DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION =
3714            Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
3715
3716    /**
3717     * When this flag is used with {@link #DRAG_FLAG_GLOBAL_URI_READ} and/or {@link
3718     * #DRAG_FLAG_GLOBAL_URI_WRITE}, the URI permission grant applies to any URI that is a prefix
3719     * match against the original granted URI.
3720     * @see android.content.Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
3721     */
3722    public static final int DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION =
3723            Intent.FLAG_GRANT_PREFIX_URI_PERMISSION;
3724
3725    /**
3726     * Flag indicating that the drag shadow will be opaque.  When
3727     * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3728     * with this flag set, the drag shadow will be opaque, otherwise, it will be semitransparent.
3729     */
3730    public static final int DRAG_FLAG_OPAQUE = 1 << 9;
3731
3732    /**
3733     * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3734     */
3735    private float mVerticalScrollFactor;
3736
3737    /**
3738     * Position of the vertical scroll bar.
3739     */
3740    private int mVerticalScrollbarPosition;
3741
3742    /**
3743     * Position the scroll bar at the default position as determined by the system.
3744     */
3745    public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3746
3747    /**
3748     * Position the scroll bar along the left edge.
3749     */
3750    public static final int SCROLLBAR_POSITION_LEFT = 1;
3751
3752    /**
3753     * Position the scroll bar along the right edge.
3754     */
3755    public static final int SCROLLBAR_POSITION_RIGHT = 2;
3756
3757    /**
3758     * Indicates that the view does not have a layer.
3759     *
3760     * @see #getLayerType()
3761     * @see #setLayerType(int, android.graphics.Paint)
3762     * @see #LAYER_TYPE_SOFTWARE
3763     * @see #LAYER_TYPE_HARDWARE
3764     */
3765    public static final int LAYER_TYPE_NONE = 0;
3766
3767    /**
3768     * <p>Indicates that the view has a software layer. A software layer is backed
3769     * by a bitmap and causes the view to be rendered using Android's software
3770     * rendering pipeline, even if hardware acceleration is enabled.</p>
3771     *
3772     * <p>Software layers have various usages:</p>
3773     * <p>When the application is not using hardware acceleration, a software layer
3774     * is useful to apply a specific color filter and/or blending mode and/or
3775     * translucency to a view and all its children.</p>
3776     * <p>When the application is using hardware acceleration, a software layer
3777     * is useful to render drawing primitives not supported by the hardware
3778     * accelerated pipeline. It can also be used to cache a complex view tree
3779     * into a texture and reduce the complexity of drawing operations. For instance,
3780     * when animating a complex view tree with a translation, a software layer can
3781     * be used to render the view tree only once.</p>
3782     * <p>Software layers should be avoided when the affected view tree updates
3783     * often. Every update will require to re-render the software layer, which can
3784     * potentially be slow (particularly when hardware acceleration is turned on
3785     * since the layer will have to be uploaded into a hardware texture after every
3786     * update.)</p>
3787     *
3788     * @see #getLayerType()
3789     * @see #setLayerType(int, android.graphics.Paint)
3790     * @see #LAYER_TYPE_NONE
3791     * @see #LAYER_TYPE_HARDWARE
3792     */
3793    public static final int LAYER_TYPE_SOFTWARE = 1;
3794
3795    /**
3796     * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3797     * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3798     * OpenGL hardware) and causes the view to be rendered using Android's hardware
3799     * rendering pipeline, but only if hardware acceleration is turned on for the
3800     * view hierarchy. When hardware acceleration is turned off, hardware layers
3801     * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
3802     *
3803     * <p>A hardware layer is useful to apply a specific color filter and/or
3804     * blending mode and/or translucency to a view and all its children.</p>
3805     * <p>A hardware layer can be used to cache a complex view tree into a
3806     * texture and reduce the complexity of drawing operations. For instance,
3807     * when animating a complex view tree with a translation, a hardware layer can
3808     * be used to render the view tree only once.</p>
3809     * <p>A hardware layer can also be used to increase the rendering quality when
3810     * rotation transformations are applied on a view. It can also be used to
3811     * prevent potential clipping issues when applying 3D transforms on a view.</p>
3812     *
3813     * @see #getLayerType()
3814     * @see #setLayerType(int, android.graphics.Paint)
3815     * @see #LAYER_TYPE_NONE
3816     * @see #LAYER_TYPE_SOFTWARE
3817     */
3818    public static final int LAYER_TYPE_HARDWARE = 2;
3819
3820    @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3821            @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3822            @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3823            @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3824    })
3825    int mLayerType = LAYER_TYPE_NONE;
3826    Paint mLayerPaint;
3827
3828    /**
3829     * Set to true when drawing cache is enabled and cannot be created.
3830     *
3831     * @hide
3832     */
3833    public boolean mCachingFailed;
3834    private Bitmap mDrawingCache;
3835    private Bitmap mUnscaledDrawingCache;
3836
3837    /**
3838     * RenderNode holding View properties, potentially holding a DisplayList of View content.
3839     * <p>
3840     * When non-null and valid, this is expected to contain an up-to-date copy
3841     * of the View content. Its DisplayList content is cleared on temporary detach and reset on
3842     * cleanup.
3843     */
3844    final RenderNode mRenderNode;
3845
3846    /**
3847     * Set to true when the view is sending hover accessibility events because it
3848     * is the innermost hovered view.
3849     */
3850    private boolean mSendingHoverAccessibilityEvents;
3851
3852    /**
3853     * Delegate for injecting accessibility functionality.
3854     */
3855    AccessibilityDelegate mAccessibilityDelegate;
3856
3857    /**
3858     * The view's overlay layer. Developers get a reference to the overlay via getOverlay()
3859     * and add/remove objects to/from the overlay directly through the Overlay methods.
3860     */
3861    ViewOverlay mOverlay;
3862
3863    /**
3864     * The currently active parent view for receiving delegated nested scrolling events.
3865     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
3866     * by {@link #stopNestedScroll()} at the same point where we clear
3867     * requestDisallowInterceptTouchEvent.
3868     */
3869    private ViewParent mNestedScrollingParent;
3870
3871    /**
3872     * Consistency verifier for debugging purposes.
3873     * @hide
3874     */
3875    protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3876            InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3877                    new InputEventConsistencyVerifier(this, 0) : null;
3878
3879    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3880
3881    private int[] mTempNestedScrollConsumed;
3882
3883    /**
3884     * An overlay is going to draw this View instead of being drawn as part of this
3885     * View's parent. mGhostView is the View in the Overlay that must be invalidated
3886     * when this view is invalidated.
3887     */
3888    GhostView mGhostView;
3889
3890    /**
3891     * Holds pairs of adjacent attribute data: attribute name followed by its value.
3892     * @hide
3893     */
3894    @ViewDebug.ExportedProperty(category = "attributes", hasAdjacentMapping = true)
3895    public String[] mAttributes;
3896
3897    /**
3898     * Maps a Resource id to its name.
3899     */
3900    private static SparseArray<String> mAttributeMap;
3901
3902    /**
3903     * Queue of pending runnables. Used to postpone calls to post() until this
3904     * view is attached and has a handler.
3905     */
3906    private HandlerActionQueue mRunQueue;
3907
3908    /**
3909     * @hide
3910     */
3911    String mStartActivityRequestWho;
3912
3913    /**
3914     * Simple constructor to use when creating a view from code.
3915     *
3916     * @param context The Context the view is running in, through which it can
3917     *        access the current theme, resources, etc.
3918     */
3919    public View(Context context) {
3920        mContext = context;
3921        mResources = context != null ? context.getResources() : null;
3922        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
3923        // Set some flags defaults
3924        mPrivateFlags2 =
3925                (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3926                (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3927                (PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT) |
3928                (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3929                (PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT) |
3930                (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
3931        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
3932        setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
3933        mUserPaddingStart = UNDEFINED_PADDING;
3934        mUserPaddingEnd = UNDEFINED_PADDING;
3935        mRenderNode = RenderNode.create(getClass().getName(), this);
3936
3937        if (!sCompatibilityDone && context != null) {
3938            final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3939
3940            // Older apps may need this compatibility hack for measurement.
3941            sUseBrokenMakeMeasureSpec = targetSdkVersion <= JELLY_BEAN_MR1;
3942
3943            // Older apps expect onMeasure() to always be called on a layout pass, regardless
3944            // of whether a layout was requested on that View.
3945            sIgnoreMeasureCache = targetSdkVersion < KITKAT;
3946
3947            Canvas.sCompatibilityRestore = targetSdkVersion < M;
3948
3949            // In M and newer, our widgets can pass a "hint" value in the size
3950            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
3951            // know what the expected parent size is going to be, so e.g. list items can size
3952            // themselves at 1/3 the size of their container. It breaks older apps though,
3953            // specifically apps that use some popular open source libraries.
3954            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < M;
3955
3956            // Old versions of the platform would give different results from
3957            // LinearLayout measurement passes using EXACTLY and non-EXACTLY
3958            // modes, so we always need to run an additional EXACTLY pass.
3959            sAlwaysRemeasureExactly = targetSdkVersion <= M;
3960
3961            sCompatibilityDone = true;
3962        }
3963    }
3964
3965    /**
3966     * Constructor that is called when inflating a view from XML. This is called
3967     * when a view is being constructed from an XML file, supplying attributes
3968     * that were specified in the XML file. This version uses a default style of
3969     * 0, so the only attribute values applied are those in the Context's Theme
3970     * and the given AttributeSet.
3971     *
3972     * <p>
3973     * The method onFinishInflate() will be called after all children have been
3974     * added.
3975     *
3976     * @param context The Context the view is running in, through which it can
3977     *        access the current theme, resources, etc.
3978     * @param attrs The attributes of the XML tag that is inflating the view.
3979     * @see #View(Context, AttributeSet, int)
3980     */
3981    public View(Context context, @Nullable AttributeSet attrs) {
3982        this(context, attrs, 0);
3983    }
3984
3985    /**
3986     * Perform inflation from XML and apply a class-specific base style from a
3987     * theme attribute. This constructor of View allows subclasses to use their
3988     * own base style when they are inflating. For example, a Button class's
3989     * constructor would call this version of the super class constructor and
3990     * supply <code>R.attr.buttonStyle</code> for <var>defStyleAttr</var>; this
3991     * allows the theme's button style to modify all of the base view attributes
3992     * (in particular its background) as well as the Button class's attributes.
3993     *
3994     * @param context The Context the view is running in, through which it can
3995     *        access the current theme, resources, etc.
3996     * @param attrs The attributes of the XML tag that is inflating the view.
3997     * @param defStyleAttr An attribute in the current theme that contains a
3998     *        reference to a style resource that supplies default values for
3999     *        the view. Can be 0 to not look for defaults.
4000     * @see #View(Context, AttributeSet)
4001     */
4002    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
4003        this(context, attrs, defStyleAttr, 0);
4004    }
4005
4006    /**
4007     * Perform inflation from XML and apply a class-specific base style from a
4008     * theme attribute or style resource. This constructor of View allows
4009     * subclasses to use their own base style when they are inflating.
4010     * <p>
4011     * When determining the final value of a particular attribute, there are
4012     * four inputs that come into play:
4013     * <ol>
4014     * <li>Any attribute values in the given AttributeSet.
4015     * <li>The style resource specified in the AttributeSet (named "style").
4016     * <li>The default style specified by <var>defStyleAttr</var>.
4017     * <li>The default style specified by <var>defStyleRes</var>.
4018     * <li>The base values in this theme.
4019     * </ol>
4020     * <p>
4021     * Each of these inputs is considered in-order, with the first listed taking
4022     * precedence over the following ones. In other words, if in the
4023     * AttributeSet you have supplied <code>&lt;Button * textColor="#ff000000"&gt;</code>
4024     * , then the button's text will <em>always</em> be black, regardless of
4025     * what is specified in any of the styles.
4026     *
4027     * @param context The Context the view is running in, through which it can
4028     *        access the current theme, resources, etc.
4029     * @param attrs The attributes of the XML tag that is inflating the view.
4030     * @param defStyleAttr An attribute in the current theme that contains a
4031     *        reference to a style resource that supplies default values for
4032     *        the view. Can be 0 to not look for defaults.
4033     * @param defStyleRes A resource identifier of a style resource that
4034     *        supplies default values for the view, used only if
4035     *        defStyleAttr is 0 or can not be found in the theme. Can be 0
4036     *        to not look for defaults.
4037     * @see #View(Context, AttributeSet, int)
4038     */
4039    public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
4040        this(context);
4041
4042        final TypedArray a = context.obtainStyledAttributes(
4043                attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);
4044
4045        if (mDebugViewAttributes) {
4046            saveAttributeData(attrs, a);
4047        }
4048
4049        Drawable background = null;
4050
4051        int leftPadding = -1;
4052        int topPadding = -1;
4053        int rightPadding = -1;
4054        int bottomPadding = -1;
4055        int startPadding = UNDEFINED_PADDING;
4056        int endPadding = UNDEFINED_PADDING;
4057
4058        int padding = -1;
4059
4060        int viewFlagValues = 0;
4061        int viewFlagMasks = 0;
4062
4063        boolean setScrollContainer = false;
4064
4065        int x = 0;
4066        int y = 0;
4067
4068        float tx = 0;
4069        float ty = 0;
4070        float tz = 0;
4071        float elevation = 0;
4072        float rotation = 0;
4073        float rotationX = 0;
4074        float rotationY = 0;
4075        float sx = 1f;
4076        float sy = 1f;
4077        boolean transformSet = false;
4078
4079        int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
4080        int overScrollMode = mOverScrollMode;
4081        boolean initializeScrollbars = false;
4082        boolean initializeScrollIndicators = false;
4083
4084        boolean startPaddingDefined = false;
4085        boolean endPaddingDefined = false;
4086        boolean leftPaddingDefined = false;
4087        boolean rightPaddingDefined = false;
4088
4089        final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
4090
4091        final int N = a.getIndexCount();
4092        for (int i = 0; i < N; i++) {
4093            int attr = a.getIndex(i);
4094            switch (attr) {
4095                case com.android.internal.R.styleable.View_background:
4096                    background = a.getDrawable(attr);
4097                    break;
4098                case com.android.internal.R.styleable.View_padding:
4099                    padding = a.getDimensionPixelSize(attr, -1);
4100                    mUserPaddingLeftInitial = padding;
4101                    mUserPaddingRightInitial = padding;
4102                    leftPaddingDefined = true;
4103                    rightPaddingDefined = true;
4104                    break;
4105                 case com.android.internal.R.styleable.View_paddingLeft:
4106                    leftPadding = a.getDimensionPixelSize(attr, -1);
4107                    mUserPaddingLeftInitial = leftPadding;
4108                    leftPaddingDefined = true;
4109                    break;
4110                case com.android.internal.R.styleable.View_paddingTop:
4111                    topPadding = a.getDimensionPixelSize(attr, -1);
4112                    break;
4113                case com.android.internal.R.styleable.View_paddingRight:
4114                    rightPadding = a.getDimensionPixelSize(attr, -1);
4115                    mUserPaddingRightInitial = rightPadding;
4116                    rightPaddingDefined = true;
4117                    break;
4118                case com.android.internal.R.styleable.View_paddingBottom:
4119                    bottomPadding = a.getDimensionPixelSize(attr, -1);
4120                    break;
4121                case com.android.internal.R.styleable.View_paddingStart:
4122                    startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4123                    startPaddingDefined = (startPadding != UNDEFINED_PADDING);
4124                    break;
4125                case com.android.internal.R.styleable.View_paddingEnd:
4126                    endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
4127                    endPaddingDefined = (endPadding != UNDEFINED_PADDING);
4128                    break;
4129                case com.android.internal.R.styleable.View_scrollX:
4130                    x = a.getDimensionPixelOffset(attr, 0);
4131                    break;
4132                case com.android.internal.R.styleable.View_scrollY:
4133                    y = a.getDimensionPixelOffset(attr, 0);
4134                    break;
4135                case com.android.internal.R.styleable.View_alpha:
4136                    setAlpha(a.getFloat(attr, 1f));
4137                    break;
4138                case com.android.internal.R.styleable.View_transformPivotX:
4139                    setPivotX(a.getDimensionPixelOffset(attr, 0));
4140                    break;
4141                case com.android.internal.R.styleable.View_transformPivotY:
4142                    setPivotY(a.getDimensionPixelOffset(attr, 0));
4143                    break;
4144                case com.android.internal.R.styleable.View_translationX:
4145                    tx = a.getDimensionPixelOffset(attr, 0);
4146                    transformSet = true;
4147                    break;
4148                case com.android.internal.R.styleable.View_translationY:
4149                    ty = a.getDimensionPixelOffset(attr, 0);
4150                    transformSet = true;
4151                    break;
4152                case com.android.internal.R.styleable.View_translationZ:
4153                    tz = a.getDimensionPixelOffset(attr, 0);
4154                    transformSet = true;
4155                    break;
4156                case com.android.internal.R.styleable.View_elevation:
4157                    elevation = a.getDimensionPixelOffset(attr, 0);
4158                    transformSet = true;
4159                    break;
4160                case com.android.internal.R.styleable.View_rotation:
4161                    rotation = a.getFloat(attr, 0);
4162                    transformSet = true;
4163                    break;
4164                case com.android.internal.R.styleable.View_rotationX:
4165                    rotationX = a.getFloat(attr, 0);
4166                    transformSet = true;
4167                    break;
4168                case com.android.internal.R.styleable.View_rotationY:
4169                    rotationY = a.getFloat(attr, 0);
4170                    transformSet = true;
4171                    break;
4172                case com.android.internal.R.styleable.View_scaleX:
4173                    sx = a.getFloat(attr, 1f);
4174                    transformSet = true;
4175                    break;
4176                case com.android.internal.R.styleable.View_scaleY:
4177                    sy = a.getFloat(attr, 1f);
4178                    transformSet = true;
4179                    break;
4180                case com.android.internal.R.styleable.View_id:
4181                    mID = a.getResourceId(attr, NO_ID);
4182                    break;
4183                case com.android.internal.R.styleable.View_tag:
4184                    mTag = a.getText(attr);
4185                    break;
4186                case com.android.internal.R.styleable.View_fitsSystemWindows:
4187                    if (a.getBoolean(attr, false)) {
4188                        viewFlagValues |= FITS_SYSTEM_WINDOWS;
4189                        viewFlagMasks |= FITS_SYSTEM_WINDOWS;
4190                    }
4191                    break;
4192                case com.android.internal.R.styleable.View_focusable:
4193                    if (a.getBoolean(attr, false)) {
4194                        viewFlagValues |= FOCUSABLE;
4195                        viewFlagMasks |= FOCUSABLE_MASK;
4196                    }
4197                    break;
4198                case com.android.internal.R.styleable.View_focusableInTouchMode:
4199                    if (a.getBoolean(attr, false)) {
4200                        viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
4201                        viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
4202                    }
4203                    break;
4204                case com.android.internal.R.styleable.View_clickable:
4205                    if (a.getBoolean(attr, false)) {
4206                        viewFlagValues |= CLICKABLE;
4207                        viewFlagMasks |= CLICKABLE;
4208                    }
4209                    break;
4210                case com.android.internal.R.styleable.View_longClickable:
4211                    if (a.getBoolean(attr, false)) {
4212                        viewFlagValues |= LONG_CLICKABLE;
4213                        viewFlagMasks |= LONG_CLICKABLE;
4214                    }
4215                    break;
4216                case com.android.internal.R.styleable.View_contextClickable:
4217                    if (a.getBoolean(attr, false)) {
4218                        viewFlagValues |= CONTEXT_CLICKABLE;
4219                        viewFlagMasks |= CONTEXT_CLICKABLE;
4220                    }
4221                    break;
4222                case com.android.internal.R.styleable.View_saveEnabled:
4223                    if (!a.getBoolean(attr, true)) {
4224                        viewFlagValues |= SAVE_DISABLED;
4225                        viewFlagMasks |= SAVE_DISABLED_MASK;
4226                    }
4227                    break;
4228                case com.android.internal.R.styleable.View_duplicateParentState:
4229                    if (a.getBoolean(attr, false)) {
4230                        viewFlagValues |= DUPLICATE_PARENT_STATE;
4231                        viewFlagMasks |= DUPLICATE_PARENT_STATE;
4232                    }
4233                    break;
4234                case com.android.internal.R.styleable.View_visibility:
4235                    final int visibility = a.getInt(attr, 0);
4236                    if (visibility != 0) {
4237                        viewFlagValues |= VISIBILITY_FLAGS[visibility];
4238                        viewFlagMasks |= VISIBILITY_MASK;
4239                    }
4240                    break;
4241                case com.android.internal.R.styleable.View_layoutDirection:
4242                    // Clear any layout direction flags (included resolved bits) already set
4243                    mPrivateFlags2 &=
4244                            ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
4245                    // Set the layout direction flags depending on the value of the attribute
4246                    final int layoutDirection = a.getInt(attr, -1);
4247                    final int value = (layoutDirection != -1) ?
4248                            LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
4249                    mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
4250                    break;
4251                case com.android.internal.R.styleable.View_drawingCacheQuality:
4252                    final int cacheQuality = a.getInt(attr, 0);
4253                    if (cacheQuality != 0) {
4254                        viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
4255                        viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
4256                    }
4257                    break;
4258                case com.android.internal.R.styleable.View_contentDescription:
4259                    setContentDescription(a.getString(attr));
4260                    break;
4261                case com.android.internal.R.styleable.View_accessibilityTraversalBefore:
4262                    setAccessibilityTraversalBefore(a.getResourceId(attr, NO_ID));
4263                    break;
4264                case com.android.internal.R.styleable.View_accessibilityTraversalAfter:
4265                    setAccessibilityTraversalAfter(a.getResourceId(attr, NO_ID));
4266                    break;
4267                case com.android.internal.R.styleable.View_labelFor:
4268                    setLabelFor(a.getResourceId(attr, NO_ID));
4269                    break;
4270                case com.android.internal.R.styleable.View_soundEffectsEnabled:
4271                    if (!a.getBoolean(attr, true)) {
4272                        viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
4273                        viewFlagMasks |= SOUND_EFFECTS_ENABLED;
4274                    }
4275                    break;
4276                case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
4277                    if (!a.getBoolean(attr, true)) {
4278                        viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
4279                        viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
4280                    }
4281                    break;
4282                case R.styleable.View_scrollbars:
4283                    final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
4284                    if (scrollbars != SCROLLBARS_NONE) {
4285                        viewFlagValues |= scrollbars;
4286                        viewFlagMasks |= SCROLLBARS_MASK;
4287                        initializeScrollbars = true;
4288                    }
4289                    break;
4290                //noinspection deprecation
4291                case R.styleable.View_fadingEdge:
4292                    if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
4293                        // Ignore the attribute starting with ICS
4294                        break;
4295                    }
4296                    // With builds < ICS, fall through and apply fading edges
4297                case R.styleable.View_requiresFadingEdge:
4298                    final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
4299                    if (fadingEdge != FADING_EDGE_NONE) {
4300                        viewFlagValues |= fadingEdge;
4301                        viewFlagMasks |= FADING_EDGE_MASK;
4302                        initializeFadingEdgeInternal(a);
4303                    }
4304                    break;
4305                case R.styleable.View_scrollbarStyle:
4306                    scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
4307                    if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4308                        viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
4309                        viewFlagMasks |= SCROLLBARS_STYLE_MASK;
4310                    }
4311                    break;
4312                case R.styleable.View_isScrollContainer:
4313                    setScrollContainer = true;
4314                    if (a.getBoolean(attr, false)) {
4315                        setScrollContainer(true);
4316                    }
4317                    break;
4318                case com.android.internal.R.styleable.View_keepScreenOn:
4319                    if (a.getBoolean(attr, false)) {
4320                        viewFlagValues |= KEEP_SCREEN_ON;
4321                        viewFlagMasks |= KEEP_SCREEN_ON;
4322                    }
4323                    break;
4324                case R.styleable.View_filterTouchesWhenObscured:
4325                    if (a.getBoolean(attr, false)) {
4326                        viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
4327                        viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
4328                    }
4329                    break;
4330                case R.styleable.View_nextFocusLeft:
4331                    mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
4332                    break;
4333                case R.styleable.View_nextFocusRight:
4334                    mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
4335                    break;
4336                case R.styleable.View_nextFocusUp:
4337                    mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
4338                    break;
4339                case R.styleable.View_nextFocusDown:
4340                    mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
4341                    break;
4342                case R.styleable.View_nextFocusForward:
4343                    mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
4344                    break;
4345                case R.styleable.View_minWidth:
4346                    mMinWidth = a.getDimensionPixelSize(attr, 0);
4347                    break;
4348                case R.styleable.View_minHeight:
4349                    mMinHeight = a.getDimensionPixelSize(attr, 0);
4350                    break;
4351                case R.styleable.View_onClick:
4352                    if (context.isRestricted()) {
4353                        throw new IllegalStateException("The android:onClick attribute cannot "
4354                                + "be used within a restricted context");
4355                    }
4356
4357                    final String handlerName = a.getString(attr);
4358                    if (handlerName != null) {
4359                        setOnClickListener(new DeclaredOnClickListener(this, handlerName));
4360                    }
4361                    break;
4362                case R.styleable.View_overScrollMode:
4363                    overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
4364                    break;
4365                case R.styleable.View_verticalScrollbarPosition:
4366                    mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
4367                    break;
4368                case R.styleable.View_layerType:
4369                    setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
4370                    break;
4371                case R.styleable.View_textDirection:
4372                    // Clear any text direction flag already set
4373                    mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
4374                    // Set the text direction flags depending on the value of the attribute
4375                    final int textDirection = a.getInt(attr, -1);
4376                    if (textDirection != -1) {
4377                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
4378                    }
4379                    break;
4380                case R.styleable.View_textAlignment:
4381                    // Clear any text alignment flag already set
4382                    mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
4383                    // Set the text alignment flag depending on the value of the attribute
4384                    final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
4385                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
4386                    break;
4387                case R.styleable.View_importantForAccessibility:
4388                    setImportantForAccessibility(a.getInt(attr,
4389                            IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
4390                    break;
4391                case R.styleable.View_accessibilityLiveRegion:
4392                    setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
4393                    break;
4394                case R.styleable.View_transitionName:
4395                    setTransitionName(a.getString(attr));
4396                    break;
4397                case R.styleable.View_nestedScrollingEnabled:
4398                    setNestedScrollingEnabled(a.getBoolean(attr, false));
4399                    break;
4400                case R.styleable.View_stateListAnimator:
4401                    setStateListAnimator(AnimatorInflater.loadStateListAnimator(context,
4402                            a.getResourceId(attr, 0)));
4403                    break;
4404                case R.styleable.View_backgroundTint:
4405                    // This will get applied later during setBackground().
4406                    if (mBackgroundTint == null) {
4407                        mBackgroundTint = new TintInfo();
4408                    }
4409                    mBackgroundTint.mTintList = a.getColorStateList(
4410                            R.styleable.View_backgroundTint);
4411                    mBackgroundTint.mHasTintList = true;
4412                    break;
4413                case R.styleable.View_backgroundTintMode:
4414                    // This will get applied later during setBackground().
4415                    if (mBackgroundTint == null) {
4416                        mBackgroundTint = new TintInfo();
4417                    }
4418                    mBackgroundTint.mTintMode = Drawable.parseTintMode(a.getInt(
4419                            R.styleable.View_backgroundTintMode, -1), null);
4420                    mBackgroundTint.mHasTintMode = true;
4421                    break;
4422                case R.styleable.View_outlineProvider:
4423                    setOutlineProviderFromAttribute(a.getInt(R.styleable.View_outlineProvider,
4424                            PROVIDER_BACKGROUND));
4425                    break;
4426                case R.styleable.View_foreground:
4427                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4428                        setForeground(a.getDrawable(attr));
4429                    }
4430                    break;
4431                case R.styleable.View_foregroundGravity:
4432                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4433                        setForegroundGravity(a.getInt(attr, Gravity.NO_GRAVITY));
4434                    }
4435                    break;
4436                case R.styleable.View_foregroundTintMode:
4437                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4438                        setForegroundTintMode(Drawable.parseTintMode(a.getInt(attr, -1), null));
4439                    }
4440                    break;
4441                case R.styleable.View_foregroundTint:
4442                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4443                        setForegroundTintList(a.getColorStateList(attr));
4444                    }
4445                    break;
4446                case R.styleable.View_foregroundInsidePadding:
4447                    if (targetSdkVersion >= VERSION_CODES.M || this instanceof FrameLayout) {
4448                        if (mForegroundInfo == null) {
4449                            mForegroundInfo = new ForegroundInfo();
4450                        }
4451                        mForegroundInfo.mInsidePadding = a.getBoolean(attr,
4452                                mForegroundInfo.mInsidePadding);
4453                    }
4454                    break;
4455                case R.styleable.View_scrollIndicators:
4456                    final int scrollIndicators =
4457                            (a.getInt(attr, 0) << SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT)
4458                                    & SCROLL_INDICATORS_PFLAG3_MASK;
4459                    if (scrollIndicators != 0) {
4460                        mPrivateFlags3 |= scrollIndicators;
4461                        initializeScrollIndicators = true;
4462                    }
4463                    break;
4464            }
4465        }
4466
4467        setOverScrollMode(overScrollMode);
4468
4469        // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
4470        // the resolved layout direction). Those cached values will be used later during padding
4471        // resolution.
4472        mUserPaddingStart = startPadding;
4473        mUserPaddingEnd = endPadding;
4474
4475        if (background != null) {
4476            setBackground(background);
4477        }
4478
4479        // setBackground above will record that padding is currently provided by the background.
4480        // If we have padding specified via xml, record that here instead and use it.
4481        mLeftPaddingDefined = leftPaddingDefined;
4482        mRightPaddingDefined = rightPaddingDefined;
4483
4484        if (padding >= 0) {
4485            leftPadding = padding;
4486            topPadding = padding;
4487            rightPadding = padding;
4488            bottomPadding = padding;
4489            mUserPaddingLeftInitial = padding;
4490            mUserPaddingRightInitial = padding;
4491        }
4492
4493        if (isRtlCompatibilityMode()) {
4494            // RTL compatibility mode: pre Jelly Bean MR1 case OR no RTL support case.
4495            // left / right padding are used if defined (meaning here nothing to do). If they are not
4496            // defined and start / end padding are defined (e.g. in Frameworks resources), then we use
4497            // start / end and resolve them as left / right (layout direction is not taken into account).
4498            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4499            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4500            // defined.
4501            if (!mLeftPaddingDefined && startPaddingDefined) {
4502                leftPadding = startPadding;
4503            }
4504            mUserPaddingLeftInitial = (leftPadding >= 0) ? leftPadding : mUserPaddingLeftInitial;
4505            if (!mRightPaddingDefined && endPaddingDefined) {
4506                rightPadding = endPadding;
4507            }
4508            mUserPaddingRightInitial = (rightPadding >= 0) ? rightPadding : mUserPaddingRightInitial;
4509        } else {
4510            // Jelly Bean MR1 and after case: if start/end defined, they will override any left/right
4511            // values defined. Otherwise, left /right values are used.
4512            // Padding from the background drawable is stored at this point in mUserPaddingLeftInitial
4513            // and mUserPaddingRightInitial) so drawable padding will be used as ultimate default if
4514            // defined.
4515            final boolean hasRelativePadding = startPaddingDefined || endPaddingDefined;
4516
4517            if (mLeftPaddingDefined && !hasRelativePadding) {
4518                mUserPaddingLeftInitial = leftPadding;
4519            }
4520            if (mRightPaddingDefined && !hasRelativePadding) {
4521                mUserPaddingRightInitial = rightPadding;
4522            }
4523        }
4524
4525        internalSetPadding(
4526                mUserPaddingLeftInitial,
4527                topPadding >= 0 ? topPadding : mPaddingTop,
4528                mUserPaddingRightInitial,
4529                bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
4530
4531        if (viewFlagMasks != 0) {
4532            setFlags(viewFlagValues, viewFlagMasks);
4533        }
4534
4535        if (initializeScrollbars) {
4536            initializeScrollbarsInternal(a);
4537        }
4538
4539        if (initializeScrollIndicators) {
4540            initializeScrollIndicatorsInternal();
4541        }
4542
4543        a.recycle();
4544
4545        // Needs to be called after mViewFlags is set
4546        if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
4547            recomputePadding();
4548        }
4549
4550        if (x != 0 || y != 0) {
4551            scrollTo(x, y);
4552        }
4553
4554        if (transformSet) {
4555            setTranslationX(tx);
4556            setTranslationY(ty);
4557            setTranslationZ(tz);
4558            setElevation(elevation);
4559            setRotation(rotation);
4560            setRotationX(rotationX);
4561            setRotationY(rotationY);
4562            setScaleX(sx);
4563            setScaleY(sy);
4564        }
4565
4566        if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
4567            setScrollContainer(true);
4568        }
4569
4570        computeOpaqueFlags();
4571    }
4572
4573    /**
4574     * An implementation of OnClickListener that attempts to lazily load a
4575     * named click handling method from a parent or ancestor context.
4576     */
4577    private static class DeclaredOnClickListener implements OnClickListener {
4578        private final View mHostView;
4579        private final String mMethodName;
4580
4581        private Method mResolvedMethod;
4582        private Context mResolvedContext;
4583
4584        public DeclaredOnClickListener(@NonNull View hostView, @NonNull String methodName) {
4585            mHostView = hostView;
4586            mMethodName = methodName;
4587        }
4588
4589        @Override
4590        public void onClick(@NonNull View v) {
4591            if (mResolvedMethod == null) {
4592                resolveMethod(mHostView.getContext(), mMethodName);
4593            }
4594
4595            try {
4596                mResolvedMethod.invoke(mResolvedContext, v);
4597            } catch (IllegalAccessException e) {
4598                throw new IllegalStateException(
4599                        "Could not execute non-public method for android:onClick", e);
4600            } catch (InvocationTargetException e) {
4601                throw new IllegalStateException(
4602                        "Could not execute method for android:onClick", e);
4603            }
4604        }
4605
4606        @NonNull
4607        private void resolveMethod(@Nullable Context context, @NonNull String name) {
4608            while (context != null) {
4609                try {
4610                    if (!context.isRestricted()) {
4611                        final Method method = context.getClass().getMethod(mMethodName, View.class);
4612                        if (method != null) {
4613                            mResolvedMethod = method;
4614                            mResolvedContext = context;
4615                            return;
4616                        }
4617                    }
4618                } catch (NoSuchMethodException e) {
4619                    // Failed to find method, keep searching up the hierarchy.
4620                }
4621
4622                if (context instanceof ContextWrapper) {
4623                    context = ((ContextWrapper) context).getBaseContext();
4624                } else {
4625                    // Can't search up the hierarchy, null out and fail.
4626                    context = null;
4627                }
4628            }
4629
4630            final int id = mHostView.getId();
4631            final String idText = id == NO_ID ? "" : " with id '"
4632                    + mHostView.getContext().getResources().getResourceEntryName(id) + "'";
4633            throw new IllegalStateException("Could not find method " + mMethodName
4634                    + "(View) in a parent or ancestor Context for android:onClick "
4635                    + "attribute defined on view " + mHostView.getClass() + idText);
4636        }
4637    }
4638
4639    /**
4640     * Non-public constructor for use in testing
4641     */
4642    View() {
4643        mResources = null;
4644        mRenderNode = RenderNode.create(getClass().getName(), this);
4645    }
4646
4647    private static SparseArray<String> getAttributeMap() {
4648        if (mAttributeMap == null) {
4649            mAttributeMap = new SparseArray<>();
4650        }
4651        return mAttributeMap;
4652    }
4653
4654    private void saveAttributeData(@Nullable AttributeSet attrs, @NonNull TypedArray t) {
4655        final int attrsCount = attrs == null ? 0 : attrs.getAttributeCount();
4656        final int indexCount = t.getIndexCount();
4657        final String[] attributes = new String[(attrsCount + indexCount) * 2];
4658
4659        int i = 0;
4660
4661        // Store raw XML attributes.
4662        for (int j = 0; j < attrsCount; ++j) {
4663            attributes[i] = attrs.getAttributeName(j);
4664            attributes[i + 1] = attrs.getAttributeValue(j);
4665            i += 2;
4666        }
4667
4668        // Store resolved styleable attributes.
4669        final Resources res = t.getResources();
4670        final SparseArray<String> attributeMap = getAttributeMap();
4671        for (int j = 0; j < indexCount; ++j) {
4672            final int index = t.getIndex(j);
4673            if (!t.hasValueOrEmpty(index)) {
4674                // Value is undefined. Skip it.
4675                continue;
4676            }
4677
4678            final int resourceId = t.getResourceId(index, 0);
4679            if (resourceId == 0) {
4680                // Value is not a reference. Skip it.
4681                continue;
4682            }
4683
4684            String resourceName = attributeMap.get(resourceId);
4685            if (resourceName == null) {
4686                try {
4687                    resourceName = res.getResourceName(resourceId);
4688                } catch (Resources.NotFoundException e) {
4689                    resourceName = "0x" + Integer.toHexString(resourceId);
4690                }
4691                attributeMap.put(resourceId, resourceName);
4692            }
4693
4694            attributes[i] = resourceName;
4695            attributes[i + 1] = t.getString(index);
4696            i += 2;
4697        }
4698
4699        // Trim to fit contents.
4700        final String[] trimmed = new String[i];
4701        System.arraycopy(attributes, 0, trimmed, 0, i);
4702        mAttributes = trimmed;
4703    }
4704
4705    public String toString() {
4706        StringBuilder out = new StringBuilder(128);
4707        out.append(getClass().getName());
4708        out.append('{');
4709        out.append(Integer.toHexString(System.identityHashCode(this)));
4710        out.append(' ');
4711        switch (mViewFlags&VISIBILITY_MASK) {
4712            case VISIBLE: out.append('V'); break;
4713            case INVISIBLE: out.append('I'); break;
4714            case GONE: out.append('G'); break;
4715            default: out.append('.'); break;
4716        }
4717        out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
4718        out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
4719        out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
4720        out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
4721        out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
4722        out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
4723        out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
4724        out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
4725        out.append(' ');
4726        out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
4727        out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
4728        out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
4729        if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
4730            out.append('p');
4731        } else {
4732            out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
4733        }
4734        out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
4735        out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
4736        out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
4737        out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
4738        out.append(' ');
4739        out.append(mLeft);
4740        out.append(',');
4741        out.append(mTop);
4742        out.append('-');
4743        out.append(mRight);
4744        out.append(',');
4745        out.append(mBottom);
4746        final int id = getId();
4747        if (id != NO_ID) {
4748            out.append(" #");
4749            out.append(Integer.toHexString(id));
4750            final Resources r = mResources;
4751            if (id > 0 && Resources.resourceHasPackage(id) && r != null) {
4752                try {
4753                    String pkgname;
4754                    switch (id&0xff000000) {
4755                        case 0x7f000000:
4756                            pkgname="app";
4757                            break;
4758                        case 0x01000000:
4759                            pkgname="android";
4760                            break;
4761                        default:
4762                            pkgname = r.getResourcePackageName(id);
4763                            break;
4764                    }
4765                    String typename = r.getResourceTypeName(id);
4766                    String entryname = r.getResourceEntryName(id);
4767                    out.append(" ");
4768                    out.append(pkgname);
4769                    out.append(":");
4770                    out.append(typename);
4771                    out.append("/");
4772                    out.append(entryname);
4773                } catch (Resources.NotFoundException e) {
4774                }
4775            }
4776        }
4777        out.append("}");
4778        return out.toString();
4779    }
4780
4781    /**
4782     * <p>
4783     * Initializes the fading edges from a given set of styled attributes. This
4784     * method should be called by subclasses that need fading edges and when an
4785     * instance of these subclasses is created programmatically rather than
4786     * being inflated from XML. This method is automatically called when the XML
4787     * is inflated.
4788     * </p>
4789     *
4790     * @param a the styled attributes set to initialize the fading edges from
4791     *
4792     * @removed
4793     */
4794    protected void initializeFadingEdge(TypedArray a) {
4795        // This method probably shouldn't have been included in the SDK to begin with.
4796        // It relies on 'a' having been initialized using an attribute filter array that is
4797        // not publicly available to the SDK. The old method has been renamed
4798        // to initializeFadingEdgeInternal and hidden for framework use only;
4799        // this one initializes using defaults to make it safe to call for apps.
4800
4801        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4802
4803        initializeFadingEdgeInternal(arr);
4804
4805        arr.recycle();
4806    }
4807
4808    /**
4809     * <p>
4810     * Initializes the fading edges from a given set of styled attributes. This
4811     * method should be called by subclasses that need fading edges and when an
4812     * instance of these subclasses is created programmatically rather than
4813     * being inflated from XML. This method is automatically called when the XML
4814     * is inflated.
4815     * </p>
4816     *
4817     * @param a the styled attributes set to initialize the fading edges from
4818     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
4819     */
4820    protected void initializeFadingEdgeInternal(TypedArray a) {
4821        initScrollCache();
4822
4823        mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
4824                R.styleable.View_fadingEdgeLength,
4825                ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
4826    }
4827
4828    /**
4829     * Returns the size of the vertical faded edges used to indicate that more
4830     * content in this view is visible.
4831     *
4832     * @return The size in pixels of the vertical faded edge or 0 if vertical
4833     *         faded edges are not enabled for this view.
4834     * @attr ref android.R.styleable#View_fadingEdgeLength
4835     */
4836    public int getVerticalFadingEdgeLength() {
4837        if (isVerticalFadingEdgeEnabled()) {
4838            ScrollabilityCache cache = mScrollCache;
4839            if (cache != null) {
4840                return cache.fadingEdgeLength;
4841            }
4842        }
4843        return 0;
4844    }
4845
4846    /**
4847     * Set the size of the faded edge used to indicate that more content in this
4848     * view is available.  Will not change whether the fading edge is enabled; use
4849     * {@link #setVerticalFadingEdgeEnabled(boolean)} or
4850     * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
4851     * for the vertical or horizontal fading edges.
4852     *
4853     * @param length The size in pixels of the faded edge used to indicate that more
4854     *        content in this view is visible.
4855     */
4856    public void setFadingEdgeLength(int length) {
4857        initScrollCache();
4858        mScrollCache.fadingEdgeLength = length;
4859    }
4860
4861    /**
4862     * Returns the size of the horizontal faded edges used to indicate that more
4863     * content in this view is visible.
4864     *
4865     * @return The size in pixels of the horizontal faded edge or 0 if horizontal
4866     *         faded edges are not enabled for this view.
4867     * @attr ref android.R.styleable#View_fadingEdgeLength
4868     */
4869    public int getHorizontalFadingEdgeLength() {
4870        if (isHorizontalFadingEdgeEnabled()) {
4871            ScrollabilityCache cache = mScrollCache;
4872            if (cache != null) {
4873                return cache.fadingEdgeLength;
4874            }
4875        }
4876        return 0;
4877    }
4878
4879    /**
4880     * Returns the width of the vertical scrollbar.
4881     *
4882     * @return The width in pixels of the vertical scrollbar or 0 if there
4883     *         is no vertical scrollbar.
4884     */
4885    public int getVerticalScrollbarWidth() {
4886        ScrollabilityCache cache = mScrollCache;
4887        if (cache != null) {
4888            ScrollBarDrawable scrollBar = cache.scrollBar;
4889            if (scrollBar != null) {
4890                int size = scrollBar.getSize(true);
4891                if (size <= 0) {
4892                    size = cache.scrollBarSize;
4893                }
4894                return size;
4895            }
4896            return 0;
4897        }
4898        return 0;
4899    }
4900
4901    /**
4902     * Returns the height of the horizontal scrollbar.
4903     *
4904     * @return The height in pixels of the horizontal scrollbar or 0 if
4905     *         there is no horizontal scrollbar.
4906     */
4907    protected int getHorizontalScrollbarHeight() {
4908        ScrollabilityCache cache = mScrollCache;
4909        if (cache != null) {
4910            ScrollBarDrawable scrollBar = cache.scrollBar;
4911            if (scrollBar != null) {
4912                int size = scrollBar.getSize(false);
4913                if (size <= 0) {
4914                    size = cache.scrollBarSize;
4915                }
4916                return size;
4917            }
4918            return 0;
4919        }
4920        return 0;
4921    }
4922
4923    /**
4924     * <p>
4925     * Initializes the scrollbars from a given set of styled attributes. This
4926     * method should be called by subclasses that need scrollbars and when an
4927     * instance of these subclasses is created programmatically rather than
4928     * being inflated from XML. This method is automatically called when the XML
4929     * is inflated.
4930     * </p>
4931     *
4932     * @param a the styled attributes set to initialize the scrollbars from
4933     *
4934     * @removed
4935     */
4936    protected void initializeScrollbars(TypedArray a) {
4937        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
4938        // using the View filter array which is not available to the SDK. As such, internal
4939        // framework usage now uses initializeScrollbarsInternal and we grab a default
4940        // TypedArray with the right filter instead here.
4941        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
4942
4943        initializeScrollbarsInternal(arr);
4944
4945        // We ignored the method parameter. Recycle the one we actually did use.
4946        arr.recycle();
4947    }
4948
4949    /**
4950     * <p>
4951     * Initializes the scrollbars from a given set of styled attributes. This
4952     * method should be called by subclasses that need scrollbars and when an
4953     * instance of these subclasses is created programmatically rather than
4954     * being inflated from XML. This method is automatically called when the XML
4955     * is inflated.
4956     * </p>
4957     *
4958     * @param a the styled attributes set to initialize the scrollbars from
4959     * @hide
4960     */
4961    protected void initializeScrollbarsInternal(TypedArray a) {
4962        initScrollCache();
4963
4964        final ScrollabilityCache scrollabilityCache = mScrollCache;
4965
4966        if (scrollabilityCache.scrollBar == null) {
4967            scrollabilityCache.scrollBar = new ScrollBarDrawable();
4968            scrollabilityCache.scrollBar.setCallback(this);
4969            scrollabilityCache.scrollBar.setState(getDrawableState());
4970        }
4971
4972        final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
4973
4974        if (!fadeScrollbars) {
4975            scrollabilityCache.state = ScrollabilityCache.ON;
4976        }
4977        scrollabilityCache.fadeScrollBars = fadeScrollbars;
4978
4979
4980        scrollabilityCache.scrollBarFadeDuration = a.getInt(
4981                R.styleable.View_scrollbarFadeDuration, ViewConfiguration
4982                        .getScrollBarFadeDuration());
4983        scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
4984                R.styleable.View_scrollbarDefaultDelayBeforeFade,
4985                ViewConfiguration.getScrollDefaultDelay());
4986
4987
4988        scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
4989                com.android.internal.R.styleable.View_scrollbarSize,
4990                ViewConfiguration.get(mContext).getScaledScrollBarSize());
4991
4992        Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
4993        scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
4994
4995        Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
4996        if (thumb != null) {
4997            scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
4998        }
4999
5000        boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
5001                false);
5002        if (alwaysDraw) {
5003            scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
5004        }
5005
5006        track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
5007        scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
5008
5009        thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
5010        if (thumb != null) {
5011            scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
5012        }
5013
5014        alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
5015                false);
5016        if (alwaysDraw) {
5017            scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
5018        }
5019
5020        // Apply layout direction to the new Drawables if needed
5021        final int layoutDirection = getLayoutDirection();
5022        if (track != null) {
5023            track.setLayoutDirection(layoutDirection);
5024        }
5025        if (thumb != null) {
5026            thumb.setLayoutDirection(layoutDirection);
5027        }
5028
5029        // Re-apply user/background padding so that scrollbar(s) get added
5030        resolvePadding();
5031    }
5032
5033    private void initializeScrollIndicatorsInternal() {
5034        // Some day maybe we'll break this into top/left/start/etc. and let the
5035        // client control it. Until then, you can have any scroll indicator you
5036        // want as long as it's a 1dp foreground-colored rectangle.
5037        if (mScrollIndicatorDrawable == null) {
5038            mScrollIndicatorDrawable = mContext.getDrawable(R.drawable.scroll_indicator_material);
5039        }
5040    }
5041
5042    /**
5043     * <p>
5044     * Initalizes the scrollability cache if necessary.
5045     * </p>
5046     */
5047    private void initScrollCache() {
5048        if (mScrollCache == null) {
5049            mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
5050        }
5051    }
5052
5053    private ScrollabilityCache getScrollCache() {
5054        initScrollCache();
5055        return mScrollCache;
5056    }
5057
5058    /**
5059     * Set the position of the vertical scroll bar. Should be one of
5060     * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
5061     * {@link #SCROLLBAR_POSITION_RIGHT}.
5062     *
5063     * @param position Where the vertical scroll bar should be positioned.
5064     */
5065    public void setVerticalScrollbarPosition(int position) {
5066        if (mVerticalScrollbarPosition != position) {
5067            mVerticalScrollbarPosition = position;
5068            computeOpaqueFlags();
5069            resolvePadding();
5070        }
5071    }
5072
5073    /**
5074     * @return The position where the vertical scroll bar will show, if applicable.
5075     * @see #setVerticalScrollbarPosition(int)
5076     */
5077    public int getVerticalScrollbarPosition() {
5078        return mVerticalScrollbarPosition;
5079    }
5080
5081    /**
5082     * Sets the state of all scroll indicators.
5083     * <p>
5084     * See {@link #setScrollIndicators(int, int)} for usage information.
5085     *
5086     * @param indicators a bitmask of indicators that should be enabled, or
5087     *                   {@code 0} to disable all indicators
5088     * @see #setScrollIndicators(int, int)
5089     * @see #getScrollIndicators()
5090     * @attr ref android.R.styleable#View_scrollIndicators
5091     */
5092    public void setScrollIndicators(@ScrollIndicators int indicators) {
5093        setScrollIndicators(indicators,
5094                SCROLL_INDICATORS_PFLAG3_MASK >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT);
5095    }
5096
5097    /**
5098     * Sets the state of the scroll indicators specified by the mask. To change
5099     * all scroll indicators at once, see {@link #setScrollIndicators(int)}.
5100     * <p>
5101     * When a scroll indicator is enabled, it will be displayed if the view
5102     * can scroll in the direction of the indicator.
5103     * <p>
5104     * Multiple indicator types may be enabled or disabled by passing the
5105     * logical OR of the desired types. If multiple types are specified, they
5106     * will all be set to the same enabled state.
5107     * <p>
5108     * For example, to enable the top scroll indicatorExample: {@code setScrollIndicators
5109     *
5110     * @param indicators the indicator direction, or the logical OR of multiple
5111     *             indicator directions. One or more of:
5112     *             <ul>
5113     *               <li>{@link #SCROLL_INDICATOR_TOP}</li>
5114     *               <li>{@link #SCROLL_INDICATOR_BOTTOM}</li>
5115     *               <li>{@link #SCROLL_INDICATOR_LEFT}</li>
5116     *               <li>{@link #SCROLL_INDICATOR_RIGHT}</li>
5117     *               <li>{@link #SCROLL_INDICATOR_START}</li>
5118     *               <li>{@link #SCROLL_INDICATOR_END}</li>
5119     *             </ul>
5120     * @see #setScrollIndicators(int)
5121     * @see #getScrollIndicators()
5122     * @attr ref android.R.styleable#View_scrollIndicators
5123     */
5124    public void setScrollIndicators(@ScrollIndicators int indicators, @ScrollIndicators int mask) {
5125        // Shift and sanitize mask.
5126        mask <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5127        mask &= SCROLL_INDICATORS_PFLAG3_MASK;
5128
5129        // Shift and mask indicators.
5130        indicators <<= SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5131        indicators &= mask;
5132
5133        // Merge with non-masked flags.
5134        final int updatedFlags = indicators | (mPrivateFlags3 & ~mask);
5135
5136        if (mPrivateFlags3 != updatedFlags) {
5137            mPrivateFlags3 = updatedFlags;
5138
5139            if (indicators != 0) {
5140                initializeScrollIndicatorsInternal();
5141            }
5142            invalidate();
5143        }
5144    }
5145
5146    /**
5147     * Returns a bitmask representing the enabled scroll indicators.
5148     * <p>
5149     * For example, if the top and left scroll indicators are enabled and all
5150     * other indicators are disabled, the return value will be
5151     * {@code View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_LEFT}.
5152     * <p>
5153     * To check whether the bottom scroll indicator is enabled, use the value
5154     * of {@code (getScrollIndicators() & View.SCROLL_INDICATOR_BOTTOM) != 0}.
5155     *
5156     * @return a bitmask representing the enabled scroll indicators
5157     */
5158    @ScrollIndicators
5159    public int getScrollIndicators() {
5160        return (mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK)
5161                >>> SCROLL_INDICATORS_TO_PFLAGS3_LSHIFT;
5162    }
5163
5164    ListenerInfo getListenerInfo() {
5165        if (mListenerInfo != null) {
5166            return mListenerInfo;
5167        }
5168        mListenerInfo = new ListenerInfo();
5169        return mListenerInfo;
5170    }
5171
5172    /**
5173     * Register a callback to be invoked when the scroll X or Y positions of
5174     * this view change.
5175     * <p>
5176     * <b>Note:</b> Some views handle scrolling independently from View and may
5177     * have their own separate listeners for scroll-type events. For example,
5178     * {@link android.widget.ListView ListView} allows clients to register an
5179     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
5180     * to listen for changes in list scroll position.
5181     *
5182     * @param l The listener to notify when the scroll X or Y position changes.
5183     * @see android.view.View#getScrollX()
5184     * @see android.view.View#getScrollY()
5185     */
5186    public void setOnScrollChangeListener(OnScrollChangeListener l) {
5187        getListenerInfo().mOnScrollChangeListener = l;
5188    }
5189
5190    /**
5191     * Register a callback to be invoked when focus of this view changed.
5192     *
5193     * @param l The callback that will run.
5194     */
5195    public void setOnFocusChangeListener(OnFocusChangeListener l) {
5196        getListenerInfo().mOnFocusChangeListener = l;
5197    }
5198
5199    /**
5200     * Add a listener that will be called when the bounds of the view change due to
5201     * layout processing.
5202     *
5203     * @param listener The listener that will be called when layout bounds change.
5204     */
5205    public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
5206        ListenerInfo li = getListenerInfo();
5207        if (li.mOnLayoutChangeListeners == null) {
5208            li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
5209        }
5210        if (!li.mOnLayoutChangeListeners.contains(listener)) {
5211            li.mOnLayoutChangeListeners.add(listener);
5212        }
5213    }
5214
5215    /**
5216     * Remove a listener for layout changes.
5217     *
5218     * @param listener The listener for layout bounds change.
5219     */
5220    public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
5221        ListenerInfo li = mListenerInfo;
5222        if (li == null || li.mOnLayoutChangeListeners == null) {
5223            return;
5224        }
5225        li.mOnLayoutChangeListeners.remove(listener);
5226    }
5227
5228    /**
5229     * Add a listener for attach state changes.
5230     *
5231     * This listener will be called whenever this view is attached or detached
5232     * from a window. Remove the listener using
5233     * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
5234     *
5235     * @param listener Listener to attach
5236     * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
5237     */
5238    public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5239        ListenerInfo li = getListenerInfo();
5240        if (li.mOnAttachStateChangeListeners == null) {
5241            li.mOnAttachStateChangeListeners
5242                    = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
5243        }
5244        li.mOnAttachStateChangeListeners.add(listener);
5245    }
5246
5247    /**
5248     * Remove a listener for attach state changes. The listener will receive no further
5249     * notification of window attach/detach events.
5250     *
5251     * @param listener Listener to remove
5252     * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
5253     */
5254    public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
5255        ListenerInfo li = mListenerInfo;
5256        if (li == null || li.mOnAttachStateChangeListeners == null) {
5257            return;
5258        }
5259        li.mOnAttachStateChangeListeners.remove(listener);
5260    }
5261
5262    /**
5263     * Returns the focus-change callback registered for this view.
5264     *
5265     * @return The callback, or null if one is not registered.
5266     */
5267    public OnFocusChangeListener getOnFocusChangeListener() {
5268        ListenerInfo li = mListenerInfo;
5269        return li != null ? li.mOnFocusChangeListener : null;
5270    }
5271
5272    /**
5273     * Register a callback to be invoked when this view is clicked. If this view is not
5274     * clickable, it becomes clickable.
5275     *
5276     * @param l The callback that will run
5277     *
5278     * @see #setClickable(boolean)
5279     */
5280    public void setOnClickListener(@Nullable OnClickListener l) {
5281        if (!isClickable()) {
5282            setClickable(true);
5283        }
5284        getListenerInfo().mOnClickListener = l;
5285    }
5286
5287    /**
5288     * Return whether this view has an attached OnClickListener.  Returns
5289     * true if there is a listener, false if there is none.
5290     */
5291    public boolean hasOnClickListeners() {
5292        ListenerInfo li = mListenerInfo;
5293        return (li != null && li.mOnClickListener != null);
5294    }
5295
5296    /**
5297     * Register a callback to be invoked when this view is clicked and held. If this view is not
5298     * long clickable, it becomes long clickable.
5299     *
5300     * @param l The callback that will run
5301     *
5302     * @see #setLongClickable(boolean)
5303     */
5304    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
5305        if (!isLongClickable()) {
5306            setLongClickable(true);
5307        }
5308        getListenerInfo().mOnLongClickListener = l;
5309    }
5310
5311    /**
5312     * Register a callback to be invoked when this view is context clicked. If the view is not
5313     * context clickable, it becomes context clickable.
5314     *
5315     * @param l The callback that will run
5316     * @see #setContextClickable(boolean)
5317     */
5318    public void setOnContextClickListener(@Nullable OnContextClickListener l) {
5319        if (!isContextClickable()) {
5320            setContextClickable(true);
5321        }
5322        getListenerInfo().mOnContextClickListener = l;
5323    }
5324
5325    /**
5326     * Register a callback to be invoked when the context menu for this view is
5327     * being built. If this view is not long clickable, it becomes long clickable.
5328     *
5329     * @param l The callback that will run
5330     *
5331     */
5332    public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
5333        if (!isLongClickable()) {
5334            setLongClickable(true);
5335        }
5336        getListenerInfo().mOnCreateContextMenuListener = l;
5337    }
5338
5339    /**
5340     * Call this view's OnClickListener, if it is defined.  Performs all normal
5341     * actions associated with clicking: reporting accessibility event, playing
5342     * a sound, etc.
5343     *
5344     * @return True there was an assigned OnClickListener that was called, false
5345     *         otherwise is returned.
5346     */
5347    public boolean performClick() {
5348        final boolean result;
5349        final ListenerInfo li = mListenerInfo;
5350        if (li != null && li.mOnClickListener != null) {
5351            playSoundEffect(SoundEffectConstants.CLICK);
5352            li.mOnClickListener.onClick(this);
5353            result = true;
5354        } else {
5355            result = false;
5356        }
5357
5358        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
5359        return result;
5360    }
5361
5362    /**
5363     * Directly call any attached OnClickListener.  Unlike {@link #performClick()},
5364     * this only calls the listener, and does not do any associated clicking
5365     * actions like reporting an accessibility event.
5366     *
5367     * @return True there was an assigned OnClickListener that was called, false
5368     *         otherwise is returned.
5369     */
5370    public boolean callOnClick() {
5371        ListenerInfo li = mListenerInfo;
5372        if (li != null && li.mOnClickListener != null) {
5373            li.mOnClickListener.onClick(this);
5374            return true;
5375        }
5376        return false;
5377    }
5378
5379    /**
5380     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5381     * context menu if the OnLongClickListener did not consume the event.
5382     *
5383     * @return {@code true} if one of the above receivers consumed the event,
5384     *         {@code false} otherwise
5385     */
5386    public boolean performLongClick() {
5387        return performLongClickInternal(mLongClickX, mLongClickY);
5388    }
5389
5390    /**
5391     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5392     * context menu if the OnLongClickListener did not consume the event,
5393     * anchoring it to an (x,y) coordinate.
5394     *
5395     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5396     *          to disable anchoring
5397     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5398     *          to disable anchoring
5399     * @return {@code true} if one of the above receivers consumed the event,
5400     *         {@code false} otherwise
5401     */
5402    public boolean performLongClick(float x, float y) {
5403        mLongClickX = x;
5404        mLongClickY = y;
5405        final boolean handled = performLongClick();
5406        mLongClickX = Float.NaN;
5407        mLongClickY = Float.NaN;
5408        return handled;
5409    }
5410
5411    /**
5412     * Calls this view's OnLongClickListener, if it is defined. Invokes the
5413     * context menu if the OnLongClickListener did not consume the event,
5414     * optionally anchoring it to an (x,y) coordinate.
5415     *
5416     * @param x x coordinate of the anchoring touch event, or {@link Float#NaN}
5417     *          to disable anchoring
5418     * @param y y coordinate of the anchoring touch event, or {@link Float#NaN}
5419     *          to disable anchoring
5420     * @return {@code true} if one of the above receivers consumed the event,
5421     *         {@code false} otherwise
5422     */
5423    private boolean performLongClickInternal(float x, float y) {
5424        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
5425
5426        boolean handled = false;
5427        final ListenerInfo li = mListenerInfo;
5428        if (li != null && li.mOnLongClickListener != null) {
5429            handled = li.mOnLongClickListener.onLongClick(View.this);
5430        }
5431        if (!handled) {
5432            final boolean isAnchored = !Float.isNaN(x) && !Float.isNaN(y);
5433            handled = isAnchored ? showContextMenu(x, y) : showContextMenu();
5434        }
5435        if (handled) {
5436            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
5437        }
5438        return handled;
5439    }
5440
5441    /**
5442     * Call this view's OnContextClickListener, if it is defined.
5443     *
5444     * @return True if there was an assigned OnContextClickListener that consumed the event, false
5445     *         otherwise.
5446     */
5447    public boolean performContextClick() {
5448        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
5449
5450        boolean handled = false;
5451        ListenerInfo li = mListenerInfo;
5452        if (li != null && li.mOnContextClickListener != null) {
5453            handled = li.mOnContextClickListener.onContextClick(View.this);
5454        }
5455        if (handled) {
5456            performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
5457        }
5458        return handled;
5459    }
5460
5461    /**
5462     * Performs button-related actions during a touch down event.
5463     *
5464     * @param event The event.
5465     * @return True if the down was consumed.
5466     *
5467     * @hide
5468     */
5469    protected boolean performButtonActionOnTouchDown(MotionEvent event) {
5470        if (event.isFromSource(InputDevice.SOURCE_MOUSE) &&
5471            (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
5472            showContextMenu(event.getX(), event.getY());
5473            mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
5474            return true;
5475        }
5476        return false;
5477    }
5478
5479    /**
5480     * Bring up the context menu for this view.
5481     *
5482     * @return Whether a context menu was displayed.
5483     */
5484    public boolean showContextMenu() {
5485        return getParent().showContextMenuForChild(this);
5486    }
5487
5488    /**
5489     * Bring up the context menu for this view, referring to the item under the specified point.
5490     *
5491     * @param x The referenced x coordinate.
5492     * @param y The referenced y coordinate.
5493     * @return Whether a context menu was displayed.
5494     */
5495    public boolean showContextMenu(float x, float y) {
5496        return getParent().showContextMenuForChild(this, x, y);
5497    }
5498
5499    /**
5500     * Start an action mode with the default type {@link ActionMode#TYPE_PRIMARY}.
5501     *
5502     * @param callback Callback that will control the lifecycle of the action mode
5503     * @return The new action mode if it is started, null otherwise
5504     *
5505     * @see ActionMode
5506     * @see #startActionMode(android.view.ActionMode.Callback, int)
5507     */
5508    public ActionMode startActionMode(ActionMode.Callback callback) {
5509        return startActionMode(callback, ActionMode.TYPE_PRIMARY);
5510    }
5511
5512    /**
5513     * Start an action mode with the given type.
5514     *
5515     * @param callback Callback that will control the lifecycle of the action mode
5516     * @param type One of {@link ActionMode#TYPE_PRIMARY} or {@link ActionMode#TYPE_FLOATING}.
5517     * @return The new action mode if it is started, null otherwise
5518     *
5519     * @see ActionMode
5520     */
5521    public ActionMode startActionMode(ActionMode.Callback callback, int type) {
5522        ViewParent parent = getParent();
5523        if (parent == null) return null;
5524        try {
5525            return parent.startActionModeForChild(this, callback, type);
5526        } catch (AbstractMethodError ame) {
5527            // Older implementations of custom views might not implement this.
5528            return parent.startActionModeForChild(this, callback);
5529        }
5530    }
5531
5532    /**
5533     * Call {@link Context#startActivityForResult(String, Intent, int, Bundle)} for the View's
5534     * Context, creating a unique View identifier to retrieve the result.
5535     *
5536     * @param intent The Intent to be started.
5537     * @param requestCode The request code to use.
5538     * @hide
5539     */
5540    public void startActivityForResult(Intent intent, int requestCode) {
5541        mStartActivityRequestWho = "@android:view:" + System.identityHashCode(this);
5542        getContext().startActivityForResult(mStartActivityRequestWho, intent, requestCode, null);
5543    }
5544
5545    /**
5546     * If this View corresponds to the calling who, dispatches the activity result.
5547     * @param who The identifier for the targeted View to receive the result.
5548     * @param requestCode The integer request code originally supplied to
5549     *                    startActivityForResult(), allowing you to identify who this
5550     *                    result came from.
5551     * @param resultCode The integer result code returned by the child activity
5552     *                   through its setResult().
5553     * @param data An Intent, which can return result data to the caller
5554     *               (various data can be attached to Intent "extras").
5555     * @return {@code true} if the activity result was dispatched.
5556     * @hide
5557     */
5558    public boolean dispatchActivityResult(
5559            String who, int requestCode, int resultCode, Intent data) {
5560        if (mStartActivityRequestWho != null && mStartActivityRequestWho.equals(who)) {
5561            onActivityResult(requestCode, resultCode, data);
5562            mStartActivityRequestWho = null;
5563            return true;
5564        }
5565        return false;
5566    }
5567
5568    /**
5569     * Receive the result from a previous call to {@link #startActivityForResult(Intent, int)}.
5570     *
5571     * @param requestCode The integer request code originally supplied to
5572     *                    startActivityForResult(), allowing you to identify who this
5573     *                    result came from.
5574     * @param resultCode The integer result code returned by the child activity
5575     *                   through its setResult().
5576     * @param data An Intent, which can return result data to the caller
5577     *               (various data can be attached to Intent "extras").
5578     * @hide
5579     */
5580    public void onActivityResult(int requestCode, int resultCode, Intent data) {
5581        // Do nothing.
5582    }
5583
5584    /**
5585     * Register a callback to be invoked when a hardware key is pressed in this view.
5586     * Key presses in software input methods will generally not trigger the methods of
5587     * this listener.
5588     * @param l the key listener to attach to this view
5589     */
5590    public void setOnKeyListener(OnKeyListener l) {
5591        getListenerInfo().mOnKeyListener = l;
5592    }
5593
5594    /**
5595     * Register a callback to be invoked when a touch event is sent to this view.
5596     * @param l the touch listener to attach to this view
5597     */
5598    public void setOnTouchListener(OnTouchListener l) {
5599        getListenerInfo().mOnTouchListener = l;
5600    }
5601
5602    /**
5603     * Register a callback to be invoked when a generic motion event is sent to this view.
5604     * @param l the generic motion listener to attach to this view
5605     */
5606    public void setOnGenericMotionListener(OnGenericMotionListener l) {
5607        getListenerInfo().mOnGenericMotionListener = l;
5608    }
5609
5610    /**
5611     * Register a callback to be invoked when a hover event is sent to this view.
5612     * @param l the hover listener to attach to this view
5613     */
5614    public void setOnHoverListener(OnHoverListener l) {
5615        getListenerInfo().mOnHoverListener = l;
5616    }
5617
5618    /**
5619     * Register a drag event listener callback object for this View. The parameter is
5620     * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
5621     * View, the system calls the
5622     * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
5623     * @param l An implementation of {@link android.view.View.OnDragListener}.
5624     */
5625    public void setOnDragListener(OnDragListener l) {
5626        getListenerInfo().mOnDragListener = l;
5627    }
5628
5629    /**
5630     * Give this view focus. This will cause
5631     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
5632     *
5633     * Note: this does not check whether this {@link View} should get focus, it just
5634     * gives it focus no matter what.  It should only be called internally by framework
5635     * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
5636     *
5637     * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
5638     *        {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
5639     *        focus moved when requestFocus() is called. It may not always
5640     *        apply, in which case use the default View.FOCUS_DOWN.
5641     * @param previouslyFocusedRect The rectangle of the view that had focus
5642     *        prior in this View's coordinate system.
5643     */
5644    void handleFocusGainInternal(@FocusRealDirection int direction, Rect previouslyFocusedRect) {
5645        if (DBG) {
5646            System.out.println(this + " requestFocus()");
5647        }
5648
5649        if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
5650            mPrivateFlags |= PFLAG_FOCUSED;
5651
5652            View oldFocus = (mAttachInfo != null) ? getRootView().findFocus() : null;
5653
5654            if (mParent != null) {
5655                mParent.requestChildFocus(this, this);
5656            }
5657
5658            if (mAttachInfo != null) {
5659                mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, this);
5660            }
5661
5662            onFocusChanged(true, direction, previouslyFocusedRect);
5663            refreshDrawableState();
5664        }
5665    }
5666
5667    /**
5668     * Populates <code>outRect</code> with the hotspot bounds. By default,
5669     * the hotspot bounds are identical to the screen bounds.
5670     *
5671     * @param outRect rect to populate with hotspot bounds
5672     * @hide Only for internal use by views and widgets.
5673     */
5674    public void getHotspotBounds(Rect outRect) {
5675        final Drawable background = getBackground();
5676        if (background != null) {
5677            background.getHotspotBounds(outRect);
5678        } else {
5679            getBoundsOnScreen(outRect);
5680        }
5681    }
5682
5683    /**
5684     * Request that a rectangle of this view be visible on the screen,
5685     * scrolling if necessary just enough.
5686     *
5687     * <p>A View should call this if it maintains some notion of which part
5688     * of its content is interesting.  For example, a text editing view
5689     * should call this when its cursor moves.
5690     *
5691     * @param rectangle The rectangle.
5692     * @return Whether any parent scrolled.
5693     */
5694    public boolean requestRectangleOnScreen(Rect rectangle) {
5695        return requestRectangleOnScreen(rectangle, false);
5696    }
5697
5698    /**
5699     * Request that a rectangle of this view be visible on the screen,
5700     * scrolling if necessary just enough.
5701     *
5702     * <p>A View should call this if it maintains some notion of which part
5703     * of its content is interesting.  For example, a text editing view
5704     * should call this when its cursor moves.
5705     *
5706     * <p>When <code>immediate</code> is set to true, scrolling will not be
5707     * animated.
5708     *
5709     * @param rectangle The rectangle.
5710     * @param immediate True to forbid animated scrolling, false otherwise
5711     * @return Whether any parent scrolled.
5712     */
5713    public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
5714        if (mParent == null) {
5715            return false;
5716        }
5717
5718        View child = this;
5719
5720        RectF position = (mAttachInfo != null) ? mAttachInfo.mTmpTransformRect : new RectF();
5721        position.set(rectangle);
5722
5723        ViewParent parent = mParent;
5724        boolean scrolled = false;
5725        while (parent != null) {
5726            rectangle.set((int) position.left, (int) position.top,
5727                    (int) position.right, (int) position.bottom);
5728
5729            scrolled |= parent.requestChildRectangleOnScreen(child,
5730                    rectangle, immediate);
5731
5732            if (!child.hasIdentityMatrix()) {
5733                child.getMatrix().mapRect(position);
5734            }
5735
5736            position.offset(child.mLeft, child.mTop);
5737
5738            if (!(parent instanceof View)) {
5739                break;
5740            }
5741
5742            View parentView = (View) parent;
5743
5744            position.offset(-parentView.getScrollX(), -parentView.getScrollY());
5745
5746            child = parentView;
5747            parent = child.getParent();
5748        }
5749
5750        return scrolled;
5751    }
5752
5753    /**
5754     * Called when this view wants to give up focus. If focus is cleared
5755     * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
5756     * <p>
5757     * <strong>Note:</strong> When a View clears focus the framework is trying
5758     * to give focus to the first focusable View from the top. Hence, if this
5759     * View is the first from the top that can take focus, then all callbacks
5760     * related to clearing focus will be invoked after which the framework will
5761     * give focus to this view.
5762     * </p>
5763     */
5764    public void clearFocus() {
5765        if (DBG) {
5766            System.out.println(this + " clearFocus()");
5767        }
5768
5769        clearFocusInternal(null, true, true);
5770    }
5771
5772    /**
5773     * Clears focus from the view, optionally propagating the change up through
5774     * the parent hierarchy and requesting that the root view place new focus.
5775     *
5776     * @param propagate whether to propagate the change up through the parent
5777     *            hierarchy
5778     * @param refocus when propagate is true, specifies whether to request the
5779     *            root view place new focus
5780     */
5781    void clearFocusInternal(View focused, boolean propagate, boolean refocus) {
5782        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
5783            mPrivateFlags &= ~PFLAG_FOCUSED;
5784
5785            if (propagate && mParent != null) {
5786                mParent.clearChildFocus(this);
5787            }
5788
5789            onFocusChanged(false, 0, null);
5790            refreshDrawableState();
5791
5792            if (propagate && (!refocus || !rootViewRequestFocus())) {
5793                notifyGlobalFocusCleared(this);
5794            }
5795        }
5796    }
5797
5798    void notifyGlobalFocusCleared(View oldFocus) {
5799        if (oldFocus != null && mAttachInfo != null) {
5800            mAttachInfo.mTreeObserver.dispatchOnGlobalFocusChange(oldFocus, null);
5801        }
5802    }
5803
5804    boolean rootViewRequestFocus() {
5805        final View root = getRootView();
5806        return root != null && root.requestFocus();
5807    }
5808
5809    /**
5810     * Called internally by the view system when a new view is getting focus.
5811     * This is what clears the old focus.
5812     * <p>
5813     * <b>NOTE:</b> The parent view's focused child must be updated manually
5814     * after calling this method. Otherwise, the view hierarchy may be left in
5815     * an inconstent state.
5816     */
5817    void unFocus(View focused) {
5818        if (DBG) {
5819            System.out.println(this + " unFocus()");
5820        }
5821
5822        clearFocusInternal(focused, false, false);
5823    }
5824
5825    /**
5826     * Returns true if this view has focus itself, or is the ancestor of the
5827     * view that has focus.
5828     *
5829     * @return True if this view has or contains focus, false otherwise.
5830     */
5831    @ViewDebug.ExportedProperty(category = "focus")
5832    public boolean hasFocus() {
5833        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
5834    }
5835
5836    /**
5837     * Returns true if this view is focusable or if it contains a reachable View
5838     * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
5839     * is a View whose parents do not block descendants focus.
5840     *
5841     * Only {@link #VISIBLE} views are considered focusable.
5842     *
5843     * @return True if the view is focusable or if the view contains a focusable
5844     *         View, false otherwise.
5845     *
5846     * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
5847     * @see ViewGroup#getTouchscreenBlocksFocus()
5848     */
5849    public boolean hasFocusable() {
5850        if (!isFocusableInTouchMode()) {
5851            for (ViewParent p = mParent; p instanceof ViewGroup; p = p.getParent()) {
5852                final ViewGroup g = (ViewGroup) p;
5853                if (g.shouldBlockFocusForTouchscreen()) {
5854                    return false;
5855                }
5856            }
5857        }
5858        return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
5859    }
5860
5861    /**
5862     * Called by the view system when the focus state of this view changes.
5863     * When the focus change event is caused by directional navigation, direction
5864     * and previouslyFocusedRect provide insight into where the focus is coming from.
5865     * When overriding, be sure to call up through to the super class so that
5866     * the standard focus handling will occur.
5867     *
5868     * @param gainFocus True if the View has focus; false otherwise.
5869     * @param direction The direction focus has moved when requestFocus()
5870     *                  is called to give this view focus. Values are
5871     *                  {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
5872     *                  {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
5873     *                  It may not always apply, in which case use the default.
5874     * @param previouslyFocusedRect The rectangle, in this view's coordinate
5875     *        system, of the previously focused view.  If applicable, this will be
5876     *        passed in as finer grained information about where the focus is coming
5877     *        from (in addition to direction).  Will be <code>null</code> otherwise.
5878     */
5879    @CallSuper
5880    protected void onFocusChanged(boolean gainFocus, @FocusDirection int direction,
5881            @Nullable Rect previouslyFocusedRect) {
5882        if (gainFocus) {
5883            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
5884        } else {
5885            notifyViewAccessibilityStateChangedIfNeeded(
5886                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
5887        }
5888
5889        InputMethodManager imm = InputMethodManager.peekInstance();
5890        if (!gainFocus) {
5891            if (isPressed()) {
5892                setPressed(false);
5893            }
5894            if (imm != null && mAttachInfo != null
5895                    && mAttachInfo.mHasWindowFocus) {
5896                imm.focusOut(this);
5897            }
5898            onFocusLost();
5899        } else if (imm != null && mAttachInfo != null
5900                && mAttachInfo.mHasWindowFocus) {
5901            imm.focusIn(this);
5902        }
5903
5904        invalidate(true);
5905        ListenerInfo li = mListenerInfo;
5906        if (li != null && li.mOnFocusChangeListener != null) {
5907            li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
5908        }
5909
5910        if (mAttachInfo != null) {
5911            mAttachInfo.mKeyDispatchState.reset(this);
5912        }
5913    }
5914
5915    /**
5916     * Sends an accessibility event of the given type. If accessibility is
5917     * not enabled this method has no effect. The default implementation calls
5918     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
5919     * to populate information about the event source (this View), then calls
5920     * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
5921     * populate the text content of the event source including its descendants,
5922     * and last calls
5923     * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
5924     * on its parent to request sending of the event to interested parties.
5925     * <p>
5926     * If an {@link AccessibilityDelegate} has been specified via calling
5927     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5928     * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
5929     * responsible for handling this call.
5930     * </p>
5931     *
5932     * @param eventType The type of the event to send, as defined by several types from
5933     * {@link android.view.accessibility.AccessibilityEvent}, such as
5934     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
5935     * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
5936     *
5937     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
5938     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
5939     * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
5940     * @see AccessibilityDelegate
5941     */
5942    public void sendAccessibilityEvent(int eventType) {
5943        if (mAccessibilityDelegate != null) {
5944            mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
5945        } else {
5946            sendAccessibilityEventInternal(eventType);
5947        }
5948    }
5949
5950    /**
5951     * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
5952     * {@link AccessibilityEvent} to make an announcement which is related to some
5953     * sort of a context change for which none of the events representing UI transitions
5954     * is a good fit. For example, announcing a new page in a book. If accessibility
5955     * is not enabled this method does nothing.
5956     *
5957     * @param text The announcement text.
5958     */
5959    public void announceForAccessibility(CharSequence text) {
5960        if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
5961            AccessibilityEvent event = AccessibilityEvent.obtain(
5962                    AccessibilityEvent.TYPE_ANNOUNCEMENT);
5963            onInitializeAccessibilityEvent(event);
5964            event.getText().add(text);
5965            event.setContentDescription(null);
5966            mParent.requestSendAccessibilityEvent(this, event);
5967        }
5968    }
5969
5970    /**
5971     * @see #sendAccessibilityEvent(int)
5972     *
5973     * Note: Called from the default {@link AccessibilityDelegate}.
5974     *
5975     * @hide
5976     */
5977    public void sendAccessibilityEventInternal(int eventType) {
5978        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
5979            sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
5980        }
5981    }
5982
5983    /**
5984     * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
5985     * takes as an argument an empty {@link AccessibilityEvent} and does not
5986     * perform a check whether accessibility is enabled.
5987     * <p>
5988     * If an {@link AccessibilityDelegate} has been specified via calling
5989     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
5990     * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
5991     * is responsible for handling this call.
5992     * </p>
5993     *
5994     * @param event The event to send.
5995     *
5996     * @see #sendAccessibilityEvent(int)
5997     */
5998    public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
5999        if (mAccessibilityDelegate != null) {
6000            mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
6001        } else {
6002            sendAccessibilityEventUncheckedInternal(event);
6003        }
6004    }
6005
6006    /**
6007     * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
6008     *
6009     * Note: Called from the default {@link AccessibilityDelegate}.
6010     *
6011     * @hide
6012     */
6013    public void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
6014        if (!isShown()) {
6015            return;
6016        }
6017        onInitializeAccessibilityEvent(event);
6018        // Only a subset of accessibility events populates text content.
6019        if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
6020            dispatchPopulateAccessibilityEvent(event);
6021        }
6022        // In the beginning we called #isShown(), so we know that getParent() is not null.
6023        getParent().requestSendAccessibilityEvent(this, event);
6024    }
6025
6026    /**
6027     * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
6028     * to its children for adding their text content to the event. Note that the
6029     * event text is populated in a separate dispatch path since we add to the
6030     * event not only the text of the source but also the text of all its descendants.
6031     * A typical implementation will call
6032     * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
6033     * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6034     * on each child. Override this method if custom population of the event text
6035     * content is required.
6036     * <p>
6037     * If an {@link AccessibilityDelegate} has been specified via calling
6038     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6039     * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
6040     * is responsible for handling this call.
6041     * </p>
6042     * <p>
6043     * <em>Note:</em> Accessibility events of certain types are not dispatched for
6044     * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
6045     * </p>
6046     *
6047     * @param event The event.
6048     *
6049     * @return True if the event population was completed.
6050     */
6051    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
6052        if (mAccessibilityDelegate != null) {
6053            return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
6054        } else {
6055            return dispatchPopulateAccessibilityEventInternal(event);
6056        }
6057    }
6058
6059    /**
6060     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6061     *
6062     * Note: Called from the default {@link AccessibilityDelegate}.
6063     *
6064     * @hide
6065     */
6066    public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6067        onPopulateAccessibilityEvent(event);
6068        return false;
6069    }
6070
6071    /**
6072     * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
6073     * giving a chance to this View to populate the accessibility event with its
6074     * text content. While this method is free to modify event
6075     * attributes other than text content, doing so should normally be performed in
6076     * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
6077     * <p>
6078     * Example: Adding formatted date string to an accessibility event in addition
6079     *          to the text added by the super implementation:
6080     * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6081     *     super.onPopulateAccessibilityEvent(event);
6082     *     final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
6083     *     String selectedDateUtterance = DateUtils.formatDateTime(mContext,
6084     *         mCurrentDate.getTimeInMillis(), flags);
6085     *     event.getText().add(selectedDateUtterance);
6086     * }</pre>
6087     * <p>
6088     * If an {@link AccessibilityDelegate} has been specified via calling
6089     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6090     * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
6091     * is responsible for handling this call.
6092     * </p>
6093     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6094     * information to the event, in case the default implementation has basic information to add.
6095     * </p>
6096     *
6097     * @param event The accessibility event which to populate.
6098     *
6099     * @see #sendAccessibilityEvent(int)
6100     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6101     */
6102    @CallSuper
6103    public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
6104        if (mAccessibilityDelegate != null) {
6105            mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
6106        } else {
6107            onPopulateAccessibilityEventInternal(event);
6108        }
6109    }
6110
6111    /**
6112     * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
6113     *
6114     * Note: Called from the default {@link AccessibilityDelegate}.
6115     *
6116     * @hide
6117     */
6118    public void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
6119    }
6120
6121    /**
6122     * Initializes an {@link AccessibilityEvent} with information about
6123     * this View which is the event source. In other words, the source of
6124     * an accessibility event is the view whose state change triggered firing
6125     * the event.
6126     * <p>
6127     * Example: Setting the password property of an event in addition
6128     *          to properties set by the super implementation:
6129     * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6130     *     super.onInitializeAccessibilityEvent(event);
6131     *     event.setPassword(true);
6132     * }</pre>
6133     * <p>
6134     * If an {@link AccessibilityDelegate} has been specified via calling
6135     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6136     * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
6137     * is responsible for handling this call.
6138     * </p>
6139     * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
6140     * information to the event, in case the default implementation has basic information to add.
6141     * </p>
6142     * @param event The event to initialize.
6143     *
6144     * @see #sendAccessibilityEvent(int)
6145     * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
6146     */
6147    @CallSuper
6148    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
6149        if (mAccessibilityDelegate != null) {
6150            mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
6151        } else {
6152            onInitializeAccessibilityEventInternal(event);
6153        }
6154    }
6155
6156    /**
6157     * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
6158     *
6159     * Note: Called from the default {@link AccessibilityDelegate}.
6160     *
6161     * @hide
6162     */
6163    public void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
6164        event.setSource(this);
6165        event.setClassName(getAccessibilityClassName());
6166        event.setPackageName(getContext().getPackageName());
6167        event.setEnabled(isEnabled());
6168        event.setContentDescription(mContentDescription);
6169
6170        switch (event.getEventType()) {
6171            case AccessibilityEvent.TYPE_VIEW_FOCUSED: {
6172                ArrayList<View> focusablesTempList = (mAttachInfo != null)
6173                        ? mAttachInfo.mTempArrayList : new ArrayList<View>();
6174                getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD, FOCUSABLES_ALL);
6175                event.setItemCount(focusablesTempList.size());
6176                event.setCurrentItemIndex(focusablesTempList.indexOf(this));
6177                if (mAttachInfo != null) {
6178                    focusablesTempList.clear();
6179                }
6180            } break;
6181            case AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED: {
6182                CharSequence text = getIterableTextForAccessibility();
6183                if (text != null && text.length() > 0) {
6184                    event.setFromIndex(getAccessibilitySelectionStart());
6185                    event.setToIndex(getAccessibilitySelectionEnd());
6186                    event.setItemCount(text.length());
6187                }
6188            } break;
6189        }
6190    }
6191
6192    /**
6193     * Returns an {@link AccessibilityNodeInfo} representing this view from the
6194     * point of view of an {@link android.accessibilityservice.AccessibilityService}.
6195     * This method is responsible for obtaining an accessibility node info from a
6196     * pool of reusable instances and calling
6197     * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
6198     * initialize the former.
6199     * <p>
6200     * Note: The client is responsible for recycling the obtained instance by calling
6201     *       {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
6202     * </p>
6203     *
6204     * @return A populated {@link AccessibilityNodeInfo}.
6205     *
6206     * @see AccessibilityNodeInfo
6207     */
6208    public AccessibilityNodeInfo createAccessibilityNodeInfo() {
6209        if (mAccessibilityDelegate != null) {
6210            return mAccessibilityDelegate.createAccessibilityNodeInfo(this);
6211        } else {
6212            return createAccessibilityNodeInfoInternal();
6213        }
6214    }
6215
6216    /**
6217     * @see #createAccessibilityNodeInfo()
6218     *
6219     * @hide
6220     */
6221    public AccessibilityNodeInfo createAccessibilityNodeInfoInternal() {
6222        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6223        if (provider != null) {
6224            return provider.createAccessibilityNodeInfo(AccessibilityNodeProvider.HOST_VIEW_ID);
6225        } else {
6226            AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
6227            onInitializeAccessibilityNodeInfo(info);
6228            return info;
6229        }
6230    }
6231
6232    /**
6233     * Initializes an {@link AccessibilityNodeInfo} with information about this view.
6234     * The base implementation sets:
6235     * <ul>
6236     *   <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
6237     *   <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
6238     *   <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
6239     *   <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
6240     *   <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
6241     *   <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
6242     *   <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
6243     *   <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
6244     *   <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
6245     *   <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
6246     *   <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
6247     *   <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
6248     *   <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
6249     * </ul>
6250     * <p>
6251     * Subclasses should override this method, call the super implementation,
6252     * and set additional attributes.
6253     * </p>
6254     * <p>
6255     * If an {@link AccessibilityDelegate} has been specified via calling
6256     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6257     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
6258     * is responsible for handling this call.
6259     * </p>
6260     *
6261     * @param info The instance to initialize.
6262     */
6263    @CallSuper
6264    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
6265        if (mAccessibilityDelegate != null) {
6266            mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
6267        } else {
6268            onInitializeAccessibilityNodeInfoInternal(info);
6269        }
6270    }
6271
6272    /**
6273     * Gets the location of this view in screen coordinates.
6274     *
6275     * @param outRect The output location
6276     * @hide
6277     */
6278    public void getBoundsOnScreen(Rect outRect) {
6279        getBoundsOnScreen(outRect, false);
6280    }
6281
6282    /**
6283     * Gets the location of this view in screen coordinates.
6284     *
6285     * @param outRect The output location
6286     * @param clipToParent Whether to clip child bounds to the parent ones.
6287     * @hide
6288     */
6289    public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {
6290        if (mAttachInfo == null) {
6291            return;
6292        }
6293
6294        RectF position = mAttachInfo.mTmpTransformRect;
6295        position.set(0, 0, mRight - mLeft, mBottom - mTop);
6296
6297        if (!hasIdentityMatrix()) {
6298            getMatrix().mapRect(position);
6299        }
6300
6301        position.offset(mLeft, mTop);
6302
6303        ViewParent parent = mParent;
6304        while (parent instanceof View) {
6305            View parentView = (View) parent;
6306
6307            position.offset(-parentView.mScrollX, -parentView.mScrollY);
6308
6309            if (clipToParent) {
6310                position.left = Math.max(position.left, 0);
6311                position.top = Math.max(position.top, 0);
6312                position.right = Math.min(position.right, parentView.getWidth());
6313                position.bottom = Math.min(position.bottom, parentView.getHeight());
6314            }
6315
6316            if (!parentView.hasIdentityMatrix()) {
6317                parentView.getMatrix().mapRect(position);
6318            }
6319
6320            position.offset(parentView.mLeft, parentView.mTop);
6321
6322            parent = parentView.mParent;
6323        }
6324
6325        if (parent instanceof ViewRootImpl) {
6326            ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
6327            position.offset(0, -viewRootImpl.mCurScrollY);
6328        }
6329
6330        position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
6331
6332        outRect.set(Math.round(position.left), Math.round(position.top),
6333                Math.round(position.right), Math.round(position.bottom));
6334    }
6335
6336    /**
6337     * Return the class name of this object to be used for accessibility purposes.
6338     * Subclasses should only override this if they are implementing something that
6339     * should be seen as a completely new class of view when used by accessibility,
6340     * unrelated to the class it is deriving from.  This is used to fill in
6341     * {@link AccessibilityNodeInfo#setClassName AccessibilityNodeInfo.setClassName}.
6342     */
6343    public CharSequence getAccessibilityClassName() {
6344        return View.class.getName();
6345    }
6346
6347    /**
6348     * Called when assist structure is being retrieved from a view as part of
6349     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData}.
6350     * @param structure Fill in with structured view data.  The default implementation
6351     * fills in all data that can be inferred from the view itself.
6352     */
6353    public void onProvideStructure(ViewStructure structure) {
6354        final int id = mID;
6355        if (id > 0 && (id&0xff000000) != 0 && (id&0x00ff0000) != 0
6356                && (id&0x0000ffff) != 0) {
6357            String pkg, type, entry;
6358            try {
6359                final Resources res = getResources();
6360                entry = res.getResourceEntryName(id);
6361                type = res.getResourceTypeName(id);
6362                pkg = res.getResourcePackageName(id);
6363            } catch (Resources.NotFoundException e) {
6364                entry = type = pkg = null;
6365            }
6366            structure.setId(id, pkg, type, entry);
6367        } else {
6368            structure.setId(id, null, null, null);
6369        }
6370        structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
6371        if (!hasIdentityMatrix()) {
6372            structure.setTransformation(getMatrix());
6373        }
6374        structure.setElevation(getZ());
6375        structure.setVisibility(getVisibility());
6376        structure.setEnabled(isEnabled());
6377        if (isClickable()) {
6378            structure.setClickable(true);
6379        }
6380        if (isFocusable()) {
6381            structure.setFocusable(true);
6382        }
6383        if (isFocused()) {
6384            structure.setFocused(true);
6385        }
6386        if (isAccessibilityFocused()) {
6387            structure.setAccessibilityFocused(true);
6388        }
6389        if (isSelected()) {
6390            structure.setSelected(true);
6391        }
6392        if (isActivated()) {
6393            structure.setActivated(true);
6394        }
6395        if (isLongClickable()) {
6396            structure.setLongClickable(true);
6397        }
6398        if (this instanceof Checkable) {
6399            structure.setCheckable(true);
6400            if (((Checkable)this).isChecked()) {
6401                structure.setChecked(true);
6402            }
6403        }
6404        if (isContextClickable()) {
6405            structure.setContextClickable(true);
6406        }
6407        structure.setClassName(getAccessibilityClassName().toString());
6408        structure.setContentDescription(getContentDescription());
6409    }
6410
6411    /**
6412     * Called when assist structure is being retrieved from a view as part of
6413     * {@link android.app.Activity#onProvideAssistData Activity.onProvideAssistData} to
6414     * generate additional virtual structure under this view.  The defaullt implementation
6415     * uses {@link #getAccessibilityNodeProvider()} to try to generate this from the
6416     * view's virtual accessibility nodes, if any.  You can override this for a more
6417     * optimal implementation providing this data.
6418     */
6419    public void onProvideVirtualStructure(ViewStructure structure) {
6420        AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
6421        if (provider != null) {
6422            AccessibilityNodeInfo info = createAccessibilityNodeInfo();
6423            structure.setChildCount(1);
6424            ViewStructure root = structure.newChild(0);
6425            populateVirtualStructure(root, provider, info);
6426            info.recycle();
6427        }
6428    }
6429
6430    private void populateVirtualStructure(ViewStructure structure,
6431            AccessibilityNodeProvider provider, AccessibilityNodeInfo info) {
6432        structure.setId(AccessibilityNodeInfo.getVirtualDescendantId(info.getSourceNodeId()),
6433                null, null, null);
6434        Rect rect = structure.getTempRect();
6435        info.getBoundsInParent(rect);
6436        structure.setDimens(rect.left, rect.top, 0, 0, rect.width(), rect.height());
6437        structure.setVisibility(VISIBLE);
6438        structure.setEnabled(info.isEnabled());
6439        if (info.isClickable()) {
6440            structure.setClickable(true);
6441        }
6442        if (info.isFocusable()) {
6443            structure.setFocusable(true);
6444        }
6445        if (info.isFocused()) {
6446            structure.setFocused(true);
6447        }
6448        if (info.isAccessibilityFocused()) {
6449            structure.setAccessibilityFocused(true);
6450        }
6451        if (info.isSelected()) {
6452            structure.setSelected(true);
6453        }
6454        if (info.isLongClickable()) {
6455            structure.setLongClickable(true);
6456        }
6457        if (info.isCheckable()) {
6458            structure.setCheckable(true);
6459            if (info.isChecked()) {
6460                structure.setChecked(true);
6461            }
6462        }
6463        if (info.isContextClickable()) {
6464            structure.setContextClickable(true);
6465        }
6466        CharSequence cname = info.getClassName();
6467        structure.setClassName(cname != null ? cname.toString() : null);
6468        structure.setContentDescription(info.getContentDescription());
6469        if (info.getText() != null || info.getError() != null) {
6470            structure.setText(info.getText(), info.getTextSelectionStart(),
6471                    info.getTextSelectionEnd());
6472        }
6473        final int NCHILDREN = info.getChildCount();
6474        if (NCHILDREN > 0) {
6475            structure.setChildCount(NCHILDREN);
6476            for (int i=0; i<NCHILDREN; i++) {
6477                AccessibilityNodeInfo cinfo = provider.createAccessibilityNodeInfo(
6478                        AccessibilityNodeInfo.getVirtualDescendantId(info.getChildId(i)));
6479                ViewStructure child = structure.newChild(i);
6480                populateVirtualStructure(child, provider, cinfo);
6481                cinfo.recycle();
6482            }
6483        }
6484    }
6485
6486    /**
6487     * Dispatch creation of {@link ViewStructure} down the hierarchy.  The default
6488     * implementation calls {@link #onProvideStructure} and
6489     * {@link #onProvideVirtualStructure}.
6490     */
6491    public void dispatchProvideStructure(ViewStructure structure) {
6492        if (!isAssistBlocked()) {
6493            onProvideStructure(structure);
6494            onProvideVirtualStructure(structure);
6495        } else {
6496            structure.setClassName(getAccessibilityClassName().toString());
6497            structure.setAssistBlocked(true);
6498        }
6499    }
6500
6501    /**
6502     * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
6503     *
6504     * Note: Called from the default {@link AccessibilityDelegate}.
6505     *
6506     * @hide
6507     */
6508    public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
6509        if (mAttachInfo == null) {
6510            return;
6511        }
6512
6513        Rect bounds = mAttachInfo.mTmpInvalRect;
6514
6515        getDrawingRect(bounds);
6516        info.setBoundsInParent(bounds);
6517
6518        getBoundsOnScreen(bounds, true);
6519        info.setBoundsInScreen(bounds);
6520
6521        ViewParent parent = getParentForAccessibility();
6522        if (parent instanceof View) {
6523            info.setParent((View) parent);
6524        }
6525
6526        if (mID != View.NO_ID) {
6527            View rootView = getRootView();
6528            if (rootView == null) {
6529                rootView = this;
6530            }
6531
6532            View label = rootView.findLabelForView(this, mID);
6533            if (label != null) {
6534                info.setLabeledBy(label);
6535            }
6536
6537            if ((mAttachInfo.mAccessibilityFetchFlags
6538                    & AccessibilityNodeInfo.FLAG_REPORT_VIEW_IDS) != 0
6539                    && Resources.resourceHasPackage(mID)) {
6540                try {
6541                    String viewId = getResources().getResourceName(mID);
6542                    info.setViewIdResourceName(viewId);
6543                } catch (Resources.NotFoundException nfe) {
6544                    /* ignore */
6545                }
6546            }
6547        }
6548
6549        if (mLabelForId != View.NO_ID) {
6550            View rootView = getRootView();
6551            if (rootView == null) {
6552                rootView = this;
6553            }
6554            View labeled = rootView.findViewInsideOutShouldExist(this, mLabelForId);
6555            if (labeled != null) {
6556                info.setLabelFor(labeled);
6557            }
6558        }
6559
6560        if (mAccessibilityTraversalBeforeId != View.NO_ID) {
6561            View rootView = getRootView();
6562            if (rootView == null) {
6563                rootView = this;
6564            }
6565            View next = rootView.findViewInsideOutShouldExist(this,
6566                    mAccessibilityTraversalBeforeId);
6567            if (next != null && next.includeForAccessibility()) {
6568                info.setTraversalBefore(next);
6569            }
6570        }
6571
6572        if (mAccessibilityTraversalAfterId != View.NO_ID) {
6573            View rootView = getRootView();
6574            if (rootView == null) {
6575                rootView = this;
6576            }
6577            View next = rootView.findViewInsideOutShouldExist(this,
6578                    mAccessibilityTraversalAfterId);
6579            if (next != null && next.includeForAccessibility()) {
6580                info.setTraversalAfter(next);
6581            }
6582        }
6583
6584        info.setVisibleToUser(isVisibleToUser());
6585
6586        info.setPackageName(mContext.getPackageName());
6587        info.setClassName(getAccessibilityClassName());
6588        info.setContentDescription(getContentDescription());
6589
6590        info.setEnabled(isEnabled());
6591        info.setClickable(isClickable());
6592        info.setFocusable(isFocusable());
6593        info.setFocused(isFocused());
6594        info.setAccessibilityFocused(isAccessibilityFocused());
6595        info.setSelected(isSelected());
6596        info.setLongClickable(isLongClickable());
6597        info.setContextClickable(isContextClickable());
6598        info.setLiveRegion(getAccessibilityLiveRegion());
6599
6600        // TODO: These make sense only if we are in an AdapterView but all
6601        // views can be selected. Maybe from accessibility perspective
6602        // we should report as selectable view in an AdapterView.
6603        info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
6604        info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
6605
6606        if (isFocusable()) {
6607            if (isFocused()) {
6608                info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
6609            } else {
6610                info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
6611            }
6612        }
6613
6614        if (!isAccessibilityFocused()) {
6615            info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
6616        } else {
6617            info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
6618        }
6619
6620        if (isClickable() && isEnabled()) {
6621            info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
6622        }
6623
6624        if (isLongClickable() && isEnabled()) {
6625            info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
6626        }
6627
6628        if (isContextClickable() && isEnabled()) {
6629            info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
6630        }
6631
6632        CharSequence text = getIterableTextForAccessibility();
6633        if (text != null && text.length() > 0) {
6634            info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
6635
6636            info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
6637            info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
6638            info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
6639            info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
6640                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
6641                    | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
6642        }
6643
6644        info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN);
6645    }
6646
6647    private View findLabelForView(View view, int labeledId) {
6648        if (mMatchLabelForPredicate == null) {
6649            mMatchLabelForPredicate = new MatchLabelForPredicate();
6650        }
6651        mMatchLabelForPredicate.mLabeledId = labeledId;
6652        return findViewByPredicateInsideOut(view, mMatchLabelForPredicate);
6653    }
6654
6655    /**
6656     * Computes whether this view is visible to the user. Such a view is
6657     * attached, visible, all its predecessors are visible, it is not clipped
6658     * entirely by its predecessors, and has an alpha greater than zero.
6659     *
6660     * @return Whether the view is visible on the screen.
6661     *
6662     * @hide
6663     */
6664    protected boolean isVisibleToUser() {
6665        return isVisibleToUser(null);
6666    }
6667
6668    /**
6669     * Computes whether the given portion of this view is visible to the user.
6670     * Such a view is attached, visible, all its predecessors are visible,
6671     * has an alpha greater than zero, and the specified portion is not
6672     * clipped entirely by its predecessors.
6673     *
6674     * @param boundInView the portion of the view to test; coordinates should be relative; may be
6675     *                    <code>null</code>, and the entire view will be tested in this case.
6676     *                    When <code>true</code> is returned by the function, the actual visible
6677     *                    region will be stored in this parameter; that is, if boundInView is fully
6678     *                    contained within the view, no modification will be made, otherwise regions
6679     *                    outside of the visible area of the view will be clipped.
6680     *
6681     * @return Whether the specified portion of the view is visible on the screen.
6682     *
6683     * @hide
6684     */
6685    protected boolean isVisibleToUser(Rect boundInView) {
6686        if (mAttachInfo != null) {
6687            // Attached to invisible window means this view is not visible.
6688            if (mAttachInfo.mWindowVisibility != View.VISIBLE) {
6689                return false;
6690            }
6691            // An invisible predecessor or one with alpha zero means
6692            // that this view is not visible to the user.
6693            Object current = this;
6694            while (current instanceof View) {
6695                View view = (View) current;
6696                // We have attach info so this view is attached and there is no
6697                // need to check whether we reach to ViewRootImpl on the way up.
6698                if (view.getAlpha() <= 0 || view.getTransitionAlpha() <= 0 ||
6699                        view.getVisibility() != VISIBLE) {
6700                    return false;
6701                }
6702                current = view.mParent;
6703            }
6704            // Check if the view is entirely covered by its predecessors.
6705            Rect visibleRect = mAttachInfo.mTmpInvalRect;
6706            Point offset = mAttachInfo.mPoint;
6707            if (!getGlobalVisibleRect(visibleRect, offset)) {
6708                return false;
6709            }
6710            // Check if the visible portion intersects the rectangle of interest.
6711            if (boundInView != null) {
6712                visibleRect.offset(-offset.x, -offset.y);
6713                return boundInView.intersect(visibleRect);
6714            }
6715            return true;
6716        }
6717        return false;
6718    }
6719
6720    /**
6721     * Returns the delegate for implementing accessibility support via
6722     * composition. For more details see {@link AccessibilityDelegate}.
6723     *
6724     * @return The delegate, or null if none set.
6725     *
6726     * @hide
6727     */
6728    public AccessibilityDelegate getAccessibilityDelegate() {
6729        return mAccessibilityDelegate;
6730    }
6731
6732    /**
6733     * Sets a delegate for implementing accessibility support via composition
6734     * (as opposed to inheritance). For more details, see
6735     * {@link AccessibilityDelegate}.
6736     * <p>
6737     * <strong>Note:</strong> On platform versions prior to
6738     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
6739     * views in the {@code android.widget.*} package are called <i>before</i>
6740     * host methods. This prevents certain properties such as class name from
6741     * being modified by overriding
6742     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
6743     * as any changes will be overwritten by the host class.
6744     * <p>
6745     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
6746     * methods are called <i>after</i> host methods, which all properties to be
6747     * modified without being overwritten by the host class.
6748     *
6749     * @param delegate the object to which accessibility method calls should be
6750     *                 delegated
6751     * @see AccessibilityDelegate
6752     */
6753    public void setAccessibilityDelegate(@Nullable AccessibilityDelegate delegate) {
6754        mAccessibilityDelegate = delegate;
6755    }
6756
6757    /**
6758     * Gets the provider for managing a virtual view hierarchy rooted at this View
6759     * and reported to {@link android.accessibilityservice.AccessibilityService}s
6760     * that explore the window content.
6761     * <p>
6762     * If this method returns an instance, this instance is responsible for managing
6763     * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
6764     * View including the one representing the View itself. Similarly the returned
6765     * instance is responsible for performing accessibility actions on any virtual
6766     * view or the root view itself.
6767     * </p>
6768     * <p>
6769     * If an {@link AccessibilityDelegate} has been specified via calling
6770     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6771     * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
6772     * is responsible for handling this call.
6773     * </p>
6774     *
6775     * @return The provider.
6776     *
6777     * @see AccessibilityNodeProvider
6778     */
6779    public AccessibilityNodeProvider getAccessibilityNodeProvider() {
6780        if (mAccessibilityDelegate != null) {
6781            return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
6782        } else {
6783            return null;
6784        }
6785    }
6786
6787    /**
6788     * Gets the unique identifier of this view on the screen for accessibility purposes.
6789     * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
6790     *
6791     * @return The view accessibility id.
6792     *
6793     * @hide
6794     */
6795    public int getAccessibilityViewId() {
6796        if (mAccessibilityViewId == NO_ID) {
6797            mAccessibilityViewId = sNextAccessibilityViewId++;
6798        }
6799        return mAccessibilityViewId;
6800    }
6801
6802    /**
6803     * Gets the unique identifier of the window in which this View reseides.
6804     *
6805     * @return The window accessibility id.
6806     *
6807     * @hide
6808     */
6809    public int getAccessibilityWindowId() {
6810        return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId
6811                : AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
6812    }
6813
6814    /**
6815     * Returns the {@link View}'s content description.
6816     * <p>
6817     * <strong>Note:</strong> Do not override this method, as it will have no
6818     * effect on the content description presented to accessibility services.
6819     * You must call {@link #setContentDescription(CharSequence)} to modify the
6820     * content description.
6821     *
6822     * @return the content description
6823     * @see #setContentDescription(CharSequence)
6824     * @attr ref android.R.styleable#View_contentDescription
6825     */
6826    @ViewDebug.ExportedProperty(category = "accessibility")
6827    public CharSequence getContentDescription() {
6828        return mContentDescription;
6829    }
6830
6831    /**
6832     * Sets the {@link View}'s content description.
6833     * <p>
6834     * A content description briefly describes the view and is primarily used
6835     * for accessibility support to determine how a view should be presented to
6836     * the user. In the case of a view with no textual representation, such as
6837     * {@link android.widget.ImageButton}, a useful content description
6838     * explains what the view does. For example, an image button with a phone
6839     * icon that is used to place a call may use "Call" as its content
6840     * description. An image of a floppy disk that is used to save a file may
6841     * use "Save".
6842     *
6843     * @param contentDescription The content description.
6844     * @see #getContentDescription()
6845     * @attr ref android.R.styleable#View_contentDescription
6846     */
6847    @RemotableViewMethod
6848    public void setContentDescription(CharSequence contentDescription) {
6849        if (mContentDescription == null) {
6850            if (contentDescription == null) {
6851                return;
6852            }
6853        } else if (mContentDescription.equals(contentDescription)) {
6854            return;
6855        }
6856        mContentDescription = contentDescription;
6857        final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
6858        if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
6859            setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
6860            notifySubtreeAccessibilityStateChangedIfNeeded();
6861        } else {
6862            notifyViewAccessibilityStateChangedIfNeeded(
6863                    AccessibilityEvent.CONTENT_CHANGE_TYPE_CONTENT_DESCRIPTION);
6864        }
6865    }
6866
6867    /**
6868     * Sets the id of a view before which this one is visited in accessibility traversal.
6869     * A screen-reader must visit the content of this view before the content of the one
6870     * it precedes. For example, if view B is set to be before view A, then a screen-reader
6871     * will traverse the entire content of B before traversing the entire content of A,
6872     * regardles of what traversal strategy it is using.
6873     * <p>
6874     * Views that do not have specified before/after relationships are traversed in order
6875     * determined by the screen-reader.
6876     * </p>
6877     * <p>
6878     * Setting that this view is before a view that is not important for accessibility
6879     * or if this view is not important for accessibility will have no effect as the
6880     * screen-reader is not aware of unimportant views.
6881     * </p>
6882     *
6883     * @param beforeId The id of a view this one precedes in accessibility traversal.
6884     *
6885     * @attr ref android.R.styleable#View_accessibilityTraversalBefore
6886     *
6887     * @see #setImportantForAccessibility(int)
6888     */
6889    @RemotableViewMethod
6890    public void setAccessibilityTraversalBefore(int beforeId) {
6891        if (mAccessibilityTraversalBeforeId == beforeId) {
6892            return;
6893        }
6894        mAccessibilityTraversalBeforeId = beforeId;
6895        notifyViewAccessibilityStateChangedIfNeeded(
6896                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6897    }
6898
6899    /**
6900     * Gets the id of a view before which this one is visited in accessibility traversal.
6901     *
6902     * @return The id of a view this one precedes in accessibility traversal if
6903     *         specified, otherwise {@link #NO_ID}.
6904     *
6905     * @see #setAccessibilityTraversalBefore(int)
6906     */
6907    public int getAccessibilityTraversalBefore() {
6908        return mAccessibilityTraversalBeforeId;
6909    }
6910
6911    /**
6912     * Sets the id of a view after which this one is visited in accessibility traversal.
6913     * A screen-reader must visit the content of the other view before the content of this
6914     * one. For example, if view B is set to be after view A, then a screen-reader
6915     * will traverse the entire content of A before traversing the entire content of B,
6916     * regardles of what traversal strategy it is using.
6917     * <p>
6918     * Views that do not have specified before/after relationships are traversed in order
6919     * determined by the screen-reader.
6920     * </p>
6921     * <p>
6922     * Setting that this view is after a view that is not important for accessibility
6923     * or if this view is not important for accessibility will have no effect as the
6924     * screen-reader is not aware of unimportant views.
6925     * </p>
6926     *
6927     * @param afterId The id of a view this one succedees in accessibility traversal.
6928     *
6929     * @attr ref android.R.styleable#View_accessibilityTraversalAfter
6930     *
6931     * @see #setImportantForAccessibility(int)
6932     */
6933    @RemotableViewMethod
6934    public void setAccessibilityTraversalAfter(int afterId) {
6935        if (mAccessibilityTraversalAfterId == afterId) {
6936            return;
6937        }
6938        mAccessibilityTraversalAfterId = afterId;
6939        notifyViewAccessibilityStateChangedIfNeeded(
6940                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6941    }
6942
6943    /**
6944     * Gets the id of a view after which this one is visited in accessibility traversal.
6945     *
6946     * @return The id of a view this one succeedes in accessibility traversal if
6947     *         specified, otherwise {@link #NO_ID}.
6948     *
6949     * @see #setAccessibilityTraversalAfter(int)
6950     */
6951    public int getAccessibilityTraversalAfter() {
6952        return mAccessibilityTraversalAfterId;
6953    }
6954
6955    /**
6956     * Gets the id of a view for which this view serves as a label for
6957     * accessibility purposes.
6958     *
6959     * @return The labeled view id.
6960     */
6961    @ViewDebug.ExportedProperty(category = "accessibility")
6962    public int getLabelFor() {
6963        return mLabelForId;
6964    }
6965
6966    /**
6967     * Sets the id of a view for which this view serves as a label for
6968     * accessibility purposes.
6969     *
6970     * @param id The labeled view id.
6971     */
6972    @RemotableViewMethod
6973    public void setLabelFor(@IdRes int id) {
6974        if (mLabelForId == id) {
6975            return;
6976        }
6977        mLabelForId = id;
6978        if (mLabelForId != View.NO_ID
6979                && mID == View.NO_ID) {
6980            mID = generateViewId();
6981        }
6982        notifyViewAccessibilityStateChangedIfNeeded(
6983                AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
6984    }
6985
6986    /**
6987     * Invoked whenever this view loses focus, either by losing window focus or by losing
6988     * focus within its window. This method can be used to clear any state tied to the
6989     * focus. For instance, if a button is held pressed with the trackball and the window
6990     * loses focus, this method can be used to cancel the press.
6991     *
6992     * Subclasses of View overriding this method should always call super.onFocusLost().
6993     *
6994     * @see #onFocusChanged(boolean, int, android.graphics.Rect)
6995     * @see #onWindowFocusChanged(boolean)
6996     *
6997     * @hide pending API council approval
6998     */
6999    @CallSuper
7000    protected void onFocusLost() {
7001        resetPressedState();
7002    }
7003
7004    private void resetPressedState() {
7005        if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7006            return;
7007        }
7008
7009        if (isPressed()) {
7010            setPressed(false);
7011
7012            if (!mHasPerformedLongPress) {
7013                removeLongPressCallback();
7014            }
7015        }
7016    }
7017
7018    /**
7019     * Returns true if this view has focus
7020     *
7021     * @return True if this view has focus, false otherwise.
7022     */
7023    @ViewDebug.ExportedProperty(category = "focus")
7024    public boolean isFocused() {
7025        return (mPrivateFlags & PFLAG_FOCUSED) != 0;
7026    }
7027
7028    /**
7029     * Find the view in the hierarchy rooted at this view that currently has
7030     * focus.
7031     *
7032     * @return The view that currently has focus, or null if no focused view can
7033     *         be found.
7034     */
7035    public View findFocus() {
7036        return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
7037    }
7038
7039    /**
7040     * Indicates whether this view is one of the set of scrollable containers in
7041     * its window.
7042     *
7043     * @return whether this view is one of the set of scrollable containers in
7044     * its window
7045     *
7046     * @attr ref android.R.styleable#View_isScrollContainer
7047     */
7048    public boolean isScrollContainer() {
7049        return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
7050    }
7051
7052    /**
7053     * Change whether this view is one of the set of scrollable containers in
7054     * its window.  This will be used to determine whether the window can
7055     * resize or must pan when a soft input area is open -- scrollable
7056     * containers allow the window to use resize mode since the container
7057     * will appropriately shrink.
7058     *
7059     * @attr ref android.R.styleable#View_isScrollContainer
7060     */
7061    public void setScrollContainer(boolean isScrollContainer) {
7062        if (isScrollContainer) {
7063            if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
7064                mAttachInfo.mScrollContainers.add(this);
7065                mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
7066            }
7067            mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
7068        } else {
7069            if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
7070                mAttachInfo.mScrollContainers.remove(this);
7071            }
7072            mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
7073        }
7074    }
7075
7076    /**
7077     * Returns the quality of the drawing cache.
7078     *
7079     * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7080     *         {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7081     *
7082     * @see #setDrawingCacheQuality(int)
7083     * @see #setDrawingCacheEnabled(boolean)
7084     * @see #isDrawingCacheEnabled()
7085     *
7086     * @attr ref android.R.styleable#View_drawingCacheQuality
7087     */
7088    @DrawingCacheQuality
7089    public int getDrawingCacheQuality() {
7090        return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
7091    }
7092
7093    /**
7094     * Set the drawing cache quality of this view. This value is used only when the
7095     * drawing cache is enabled
7096     *
7097     * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
7098     *        {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
7099     *
7100     * @see #getDrawingCacheQuality()
7101     * @see #setDrawingCacheEnabled(boolean)
7102     * @see #isDrawingCacheEnabled()
7103     *
7104     * @attr ref android.R.styleable#View_drawingCacheQuality
7105     */
7106    public void setDrawingCacheQuality(@DrawingCacheQuality int quality) {
7107        setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
7108    }
7109
7110    /**
7111     * Returns whether the screen should remain on, corresponding to the current
7112     * value of {@link #KEEP_SCREEN_ON}.
7113     *
7114     * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
7115     *
7116     * @see #setKeepScreenOn(boolean)
7117     *
7118     * @attr ref android.R.styleable#View_keepScreenOn
7119     */
7120    public boolean getKeepScreenOn() {
7121        return (mViewFlags & KEEP_SCREEN_ON) != 0;
7122    }
7123
7124    /**
7125     * Controls whether the screen should remain on, modifying the
7126     * value of {@link #KEEP_SCREEN_ON}.
7127     *
7128     * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
7129     *
7130     * @see #getKeepScreenOn()
7131     *
7132     * @attr ref android.R.styleable#View_keepScreenOn
7133     */
7134    public void setKeepScreenOn(boolean keepScreenOn) {
7135        setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
7136    }
7137
7138    /**
7139     * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7140     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7141     *
7142     * @attr ref android.R.styleable#View_nextFocusLeft
7143     */
7144    public int getNextFocusLeftId() {
7145        return mNextFocusLeftId;
7146    }
7147
7148    /**
7149     * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
7150     * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
7151     * decide automatically.
7152     *
7153     * @attr ref android.R.styleable#View_nextFocusLeft
7154     */
7155    public void setNextFocusLeftId(int nextFocusLeftId) {
7156        mNextFocusLeftId = nextFocusLeftId;
7157    }
7158
7159    /**
7160     * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7161     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7162     *
7163     * @attr ref android.R.styleable#View_nextFocusRight
7164     */
7165    public int getNextFocusRightId() {
7166        return mNextFocusRightId;
7167    }
7168
7169    /**
7170     * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
7171     * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
7172     * decide automatically.
7173     *
7174     * @attr ref android.R.styleable#View_nextFocusRight
7175     */
7176    public void setNextFocusRightId(int nextFocusRightId) {
7177        mNextFocusRightId = nextFocusRightId;
7178    }
7179
7180    /**
7181     * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7182     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7183     *
7184     * @attr ref android.R.styleable#View_nextFocusUp
7185     */
7186    public int getNextFocusUpId() {
7187        return mNextFocusUpId;
7188    }
7189
7190    /**
7191     * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
7192     * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
7193     * decide automatically.
7194     *
7195     * @attr ref android.R.styleable#View_nextFocusUp
7196     */
7197    public void setNextFocusUpId(int nextFocusUpId) {
7198        mNextFocusUpId = nextFocusUpId;
7199    }
7200
7201    /**
7202     * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7203     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7204     *
7205     * @attr ref android.R.styleable#View_nextFocusDown
7206     */
7207    public int getNextFocusDownId() {
7208        return mNextFocusDownId;
7209    }
7210
7211    /**
7212     * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
7213     * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
7214     * decide automatically.
7215     *
7216     * @attr ref android.R.styleable#View_nextFocusDown
7217     */
7218    public void setNextFocusDownId(int nextFocusDownId) {
7219        mNextFocusDownId = nextFocusDownId;
7220    }
7221
7222    /**
7223     * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7224     * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
7225     *
7226     * @attr ref android.R.styleable#View_nextFocusForward
7227     */
7228    public int getNextFocusForwardId() {
7229        return mNextFocusForwardId;
7230    }
7231
7232    /**
7233     * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
7234     * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
7235     * decide automatically.
7236     *
7237     * @attr ref android.R.styleable#View_nextFocusForward
7238     */
7239    public void setNextFocusForwardId(int nextFocusForwardId) {
7240        mNextFocusForwardId = nextFocusForwardId;
7241    }
7242
7243    /**
7244     * Returns the visibility of this view and all of its ancestors
7245     *
7246     * @return True if this view and all of its ancestors are {@link #VISIBLE}
7247     */
7248    public boolean isShown() {
7249        View current = this;
7250        //noinspection ConstantConditions
7251        do {
7252            if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
7253                return false;
7254            }
7255            ViewParent parent = current.mParent;
7256            if (parent == null) {
7257                return false; // We are not attached to the view root
7258            }
7259            if (!(parent instanceof View)) {
7260                return true;
7261            }
7262            current = (View) parent;
7263        } while (current != null);
7264
7265        return false;
7266    }
7267
7268    /**
7269     * Called by the view hierarchy when the content insets for a window have
7270     * changed, to allow it to adjust its content to fit within those windows.
7271     * The content insets tell you the space that the status bar, input method,
7272     * and other system windows infringe on the application's window.
7273     *
7274     * <p>You do not normally need to deal with this function, since the default
7275     * window decoration given to applications takes care of applying it to the
7276     * content of the window.  If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
7277     * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
7278     * and your content can be placed under those system elements.  You can then
7279     * use this method within your view hierarchy if you have parts of your UI
7280     * which you would like to ensure are not being covered.
7281     *
7282     * <p>The default implementation of this method simply applies the content
7283     * insets to the view's padding, consuming that content (modifying the
7284     * insets to be 0), and returning true.  This behavior is off by default, but can
7285     * be enabled through {@link #setFitsSystemWindows(boolean)}.
7286     *
7287     * <p>This function's traversal down the hierarchy is depth-first.  The same content
7288     * insets object is propagated down the hierarchy, so any changes made to it will
7289     * be seen by all following views (including potentially ones above in
7290     * the hierarchy since this is a depth-first traversal).  The first view
7291     * that returns true will abort the entire traversal.
7292     *
7293     * <p>The default implementation works well for a situation where it is
7294     * used with a container that covers the entire window, allowing it to
7295     * apply the appropriate insets to its content on all edges.  If you need
7296     * a more complicated layout (such as two different views fitting system
7297     * windows, one on the top of the window, and one on the bottom),
7298     * you can override the method and handle the insets however you would like.
7299     * Note that the insets provided by the framework are always relative to the
7300     * far edges of the window, not accounting for the location of the called view
7301     * within that window.  (In fact when this method is called you do not yet know
7302     * where the layout will place the view, as it is done before layout happens.)
7303     *
7304     * <p>Note: unlike many View methods, there is no dispatch phase to this
7305     * call.  If you are overriding it in a ViewGroup and want to allow the
7306     * call to continue to your children, you must be sure to call the super
7307     * implementation.
7308     *
7309     * <p>Here is a sample layout that makes use of fitting system windows
7310     * to have controls for a video view placed inside of the window decorations
7311     * that it hides and shows.  This can be used with code like the second
7312     * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
7313     *
7314     * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
7315     *
7316     * @param insets Current content insets of the window.  Prior to
7317     * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
7318     * the insets or else you and Android will be unhappy.
7319     *
7320     * @return {@code true} if this view applied the insets and it should not
7321     * continue propagating further down the hierarchy, {@code false} otherwise.
7322     * @see #getFitsSystemWindows()
7323     * @see #setFitsSystemWindows(boolean)
7324     * @see #setSystemUiVisibility(int)
7325     *
7326     * @deprecated As of API 20 use {@link #dispatchApplyWindowInsets(WindowInsets)} to apply
7327     * insets to views. Views should override {@link #onApplyWindowInsets(WindowInsets)} or use
7328     * {@link #setOnApplyWindowInsetsListener(android.view.View.OnApplyWindowInsetsListener)}
7329     * to implement handling their own insets.
7330     */
7331    protected boolean fitSystemWindows(Rect insets) {
7332        if ((mPrivateFlags3 & PFLAG3_APPLYING_INSETS) == 0) {
7333            if (insets == null) {
7334                // Null insets by definition have already been consumed.
7335                // This call cannot apply insets since there are none to apply,
7336                // so return false.
7337                return false;
7338            }
7339            // If we're not in the process of dispatching the newer apply insets call,
7340            // that means we're not in the compatibility path. Dispatch into the newer
7341            // apply insets path and take things from there.
7342            try {
7343                mPrivateFlags3 |= PFLAG3_FITTING_SYSTEM_WINDOWS;
7344                return dispatchApplyWindowInsets(new WindowInsets(insets)).isConsumed();
7345            } finally {
7346                mPrivateFlags3 &= ~PFLAG3_FITTING_SYSTEM_WINDOWS;
7347            }
7348        } else {
7349            // We're being called from the newer apply insets path.
7350            // Perform the standard fallback behavior.
7351            return fitSystemWindowsInt(insets);
7352        }
7353    }
7354
7355    private boolean fitSystemWindowsInt(Rect insets) {
7356        if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
7357            mUserPaddingStart = UNDEFINED_PADDING;
7358            mUserPaddingEnd = UNDEFINED_PADDING;
7359            Rect localInsets = sThreadLocal.get();
7360            if (localInsets == null) {
7361                localInsets = new Rect();
7362                sThreadLocal.set(localInsets);
7363            }
7364            boolean res = computeFitSystemWindows(insets, localInsets);
7365            mUserPaddingLeftInitial = localInsets.left;
7366            mUserPaddingRightInitial = localInsets.right;
7367            internalSetPadding(localInsets.left, localInsets.top,
7368                    localInsets.right, localInsets.bottom);
7369            return res;
7370        }
7371        return false;
7372    }
7373
7374    /**
7375     * Called when the view should apply {@link WindowInsets} according to its internal policy.
7376     *
7377     * <p>This method should be overridden by views that wish to apply a policy different from or
7378     * in addition to the default behavior. Clients that wish to force a view subtree
7379     * to apply insets should call {@link #dispatchApplyWindowInsets(WindowInsets)}.</p>
7380     *
7381     * <p>Clients may supply an {@link OnApplyWindowInsetsListener} to a view. If one is set
7382     * it will be called during dispatch instead of this method. The listener may optionally
7383     * call this method from its own implementation if it wishes to apply the view's default
7384     * insets policy in addition to its own.</p>
7385     *
7386     * <p>Implementations of this method should either return the insets parameter unchanged
7387     * or a new {@link WindowInsets} cloned from the supplied insets with any insets consumed
7388     * that this view applied itself. This allows new inset types added in future platform
7389     * versions to pass through existing implementations unchanged without being erroneously
7390     * consumed.</p>
7391     *
7392     * <p>By default if a view's {@link #setFitsSystemWindows(boolean) fitsSystemWindows}
7393     * property is set then the view will consume the system window insets and apply them
7394     * as padding for the view.</p>
7395     *
7396     * @param insets Insets to apply
7397     * @return The supplied insets with any applied insets consumed
7398     */
7399    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
7400        if ((mPrivateFlags3 & PFLAG3_FITTING_SYSTEM_WINDOWS) == 0) {
7401            // We weren't called from within a direct call to fitSystemWindows,
7402            // call into it as a fallback in case we're in a class that overrides it
7403            // and has logic to perform.
7404            if (fitSystemWindows(insets.getSystemWindowInsets())) {
7405                return insets.consumeSystemWindowInsets();
7406            }
7407        } else {
7408            // We were called from within a direct call to fitSystemWindows.
7409            if (fitSystemWindowsInt(insets.getSystemWindowInsets())) {
7410                return insets.consumeSystemWindowInsets();
7411            }
7412        }
7413        return insets;
7414    }
7415
7416    /**
7417     * Set an {@link OnApplyWindowInsetsListener} to take over the policy for applying
7418     * window insets to this view. The listener's
7419     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
7420     * method will be called instead of the view's
7421     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
7422     *
7423     * @param listener Listener to set
7424     *
7425     * @see #onApplyWindowInsets(WindowInsets)
7426     */
7427    public void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
7428        getListenerInfo().mOnApplyWindowInsetsListener = listener;
7429    }
7430
7431    /**
7432     * Request to apply the given window insets to this view or another view in its subtree.
7433     *
7434     * <p>This method should be called by clients wishing to apply insets corresponding to areas
7435     * obscured by window decorations or overlays. This can include the status and navigation bars,
7436     * action bars, input methods and more. New inset categories may be added in the future.
7437     * The method returns the insets provided minus any that were applied by this view or its
7438     * children.</p>
7439     *
7440     * <p>Clients wishing to provide custom behavior should override the
7441     * {@link #onApplyWindowInsets(WindowInsets)} method or alternatively provide a
7442     * {@link OnApplyWindowInsetsListener} via the
7443     * {@link #setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) setOnApplyWindowInsetsListener}
7444     * method.</p>
7445     *
7446     * <p>This method replaces the older {@link #fitSystemWindows(Rect) fitSystemWindows} method.
7447     * </p>
7448     *
7449     * @param insets Insets to apply
7450     * @return The provided insets minus the insets that were consumed
7451     */
7452    public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
7453        try {
7454            mPrivateFlags3 |= PFLAG3_APPLYING_INSETS;
7455            if (mListenerInfo != null && mListenerInfo.mOnApplyWindowInsetsListener != null) {
7456                return mListenerInfo.mOnApplyWindowInsetsListener.onApplyWindowInsets(this, insets);
7457            } else {
7458                return onApplyWindowInsets(insets);
7459            }
7460        } finally {
7461            mPrivateFlags3 &= ~PFLAG3_APPLYING_INSETS;
7462        }
7463    }
7464
7465    /**
7466     * Compute the view's coordinate within the surface.
7467     *
7468     * <p>Computes the coordinates of this view in its surface. The argument
7469     * must be an array of two integers. After the method returns, the array
7470     * contains the x and y location in that order.</p>
7471     * @hide
7472     * @param location an array of two integers in which to hold the coordinates
7473     */
7474    public void getLocationInSurface(@Size(2) int[] location) {
7475        getLocationInWindow(location);
7476        if (mAttachInfo != null && mAttachInfo.mViewRootImpl != null) {
7477            location[0] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.left;
7478            location[1] += mAttachInfo.mViewRootImpl.mWindowAttributes.surfaceInsets.top;
7479        }
7480    }
7481
7482    /**
7483     * Provide original WindowInsets that are dispatched to the view hierarchy. The insets are
7484     * only available if the view is attached.
7485     *
7486     * @return WindowInsets from the top of the view hierarchy or null if View is detached
7487     */
7488    public WindowInsets getRootWindowInsets() {
7489        if (mAttachInfo != null) {
7490            return mAttachInfo.mViewRootImpl.getWindowInsets(false /* forceConstruct */);
7491        }
7492        return null;
7493    }
7494
7495    /**
7496     * @hide Compute the insets that should be consumed by this view and the ones
7497     * that should propagate to those under it.
7498     */
7499    protected boolean computeFitSystemWindows(Rect inoutInsets, Rect outLocalInsets) {
7500        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7501                || mAttachInfo == null
7502                || ((mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0
7503                        && !mAttachInfo.mOverscanRequested)) {
7504            outLocalInsets.set(inoutInsets);
7505            inoutInsets.set(0, 0, 0, 0);
7506            return true;
7507        } else {
7508            // The application wants to take care of fitting system window for
7509            // the content...  however we still need to take care of any overscan here.
7510            final Rect overscan = mAttachInfo.mOverscanInsets;
7511            outLocalInsets.set(overscan);
7512            inoutInsets.left -= overscan.left;
7513            inoutInsets.top -= overscan.top;
7514            inoutInsets.right -= overscan.right;
7515            inoutInsets.bottom -= overscan.bottom;
7516            return false;
7517        }
7518    }
7519
7520    /**
7521     * Compute insets that should be consumed by this view and the ones that should propagate
7522     * to those under it.
7523     *
7524     * @param in Insets currently being processed by this View, likely received as a parameter
7525     *           to {@link #onApplyWindowInsets(WindowInsets)}.
7526     * @param outLocalInsets A Rect that will receive the insets that should be consumed
7527     *                       by this view
7528     * @return Insets that should be passed along to views under this one
7529     */
7530    public WindowInsets computeSystemWindowInsets(WindowInsets in, Rect outLocalInsets) {
7531        if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
7532                || mAttachInfo == null
7533                || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
7534            outLocalInsets.set(in.getSystemWindowInsets());
7535            return in.consumeSystemWindowInsets();
7536        } else {
7537            outLocalInsets.set(0, 0, 0, 0);
7538            return in;
7539        }
7540    }
7541
7542    /**
7543     * Sets whether or not this view should account for system screen decorations
7544     * such as the status bar and inset its content; that is, controlling whether
7545     * the default implementation of {@link #fitSystemWindows(Rect)} will be
7546     * executed.  See that method for more details.
7547     *
7548     * <p>Note that if you are providing your own implementation of
7549     * {@link #fitSystemWindows(Rect)}, then there is no need to set this
7550     * flag to true -- your implementation will be overriding the default
7551     * implementation that checks this flag.
7552     *
7553     * @param fitSystemWindows If true, then the default implementation of
7554     * {@link #fitSystemWindows(Rect)} will be executed.
7555     *
7556     * @attr ref android.R.styleable#View_fitsSystemWindows
7557     * @see #getFitsSystemWindows()
7558     * @see #fitSystemWindows(Rect)
7559     * @see #setSystemUiVisibility(int)
7560     */
7561    public void setFitsSystemWindows(boolean fitSystemWindows) {
7562        setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
7563    }
7564
7565    /**
7566     * Check for state of {@link #setFitsSystemWindows(boolean)}. If this method
7567     * returns {@code true}, the default implementation of {@link #fitSystemWindows(Rect)}
7568     * will be executed.
7569     *
7570     * @return {@code true} if the default implementation of
7571     * {@link #fitSystemWindows(Rect)} will be executed.
7572     *
7573     * @attr ref android.R.styleable#View_fitsSystemWindows
7574     * @see #setFitsSystemWindows(boolean)
7575     * @see #fitSystemWindows(Rect)
7576     * @see #setSystemUiVisibility(int)
7577     */
7578    @ViewDebug.ExportedProperty
7579    public boolean getFitsSystemWindows() {
7580        return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
7581    }
7582
7583    /** @hide */
7584    public boolean fitsSystemWindows() {
7585        return getFitsSystemWindows();
7586    }
7587
7588    /**
7589     * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
7590     * @deprecated Use {@link #requestApplyInsets()} for newer platform versions.
7591     */
7592    public void requestFitSystemWindows() {
7593        if (mParent != null) {
7594            mParent.requestFitSystemWindows();
7595        }
7596    }
7597
7598    /**
7599     * Ask that a new dispatch of {@link #onApplyWindowInsets(WindowInsets)} be performed.
7600     */
7601    public void requestApplyInsets() {
7602        requestFitSystemWindows();
7603    }
7604
7605    /**
7606     * For use by PhoneWindow to make its own system window fitting optional.
7607     * @hide
7608     */
7609    public void makeOptionalFitsSystemWindows() {
7610        setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
7611    }
7612
7613    /**
7614     * Returns the outsets, which areas of the device that aren't a surface, but we would like to
7615     * treat them as such.
7616     * @hide
7617     */
7618    public void getOutsets(Rect outOutsetRect) {
7619        if (mAttachInfo != null) {
7620            outOutsetRect.set(mAttachInfo.mOutsets);
7621        } else {
7622            outOutsetRect.setEmpty();
7623        }
7624    }
7625
7626    /**
7627     * Returns the visibility status for this view.
7628     *
7629     * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7630     * @attr ref android.R.styleable#View_visibility
7631     */
7632    @ViewDebug.ExportedProperty(mapping = {
7633        @ViewDebug.IntToString(from = VISIBLE,   to = "VISIBLE"),
7634        @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
7635        @ViewDebug.IntToString(from = GONE,      to = "GONE")
7636    })
7637    @Visibility
7638    public int getVisibility() {
7639        return mViewFlags & VISIBILITY_MASK;
7640    }
7641
7642    /**
7643     * Set the enabled state of this view.
7644     *
7645     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
7646     * @attr ref android.R.styleable#View_visibility
7647     */
7648    @RemotableViewMethod
7649    public void setVisibility(@Visibility int visibility) {
7650        setFlags(visibility, VISIBILITY_MASK);
7651    }
7652
7653    /**
7654     * Returns the enabled status for this view. The interpretation of the
7655     * enabled state varies by subclass.
7656     *
7657     * @return True if this view is enabled, false otherwise.
7658     */
7659    @ViewDebug.ExportedProperty
7660    public boolean isEnabled() {
7661        return (mViewFlags & ENABLED_MASK) == ENABLED;
7662    }
7663
7664    /**
7665     * Set the enabled state of this view. The interpretation of the enabled
7666     * state varies by subclass.
7667     *
7668     * @param enabled True if this view is enabled, false otherwise.
7669     */
7670    @RemotableViewMethod
7671    public void setEnabled(boolean enabled) {
7672        if (enabled == isEnabled()) return;
7673
7674        setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
7675
7676        /*
7677         * The View most likely has to change its appearance, so refresh
7678         * the drawable state.
7679         */
7680        refreshDrawableState();
7681
7682        // Invalidate too, since the default behavior for views is to be
7683        // be drawn at 50% alpha rather than to change the drawable.
7684        invalidate(true);
7685
7686        if (!enabled) {
7687            cancelPendingInputEvents();
7688        }
7689    }
7690
7691    /**
7692     * Set whether this view can receive the focus.
7693     *
7694     * Setting this to false will also ensure that this view is not focusable
7695     * in touch mode.
7696     *
7697     * @param focusable If true, this view can receive the focus.
7698     *
7699     * @see #setFocusableInTouchMode(boolean)
7700     * @attr ref android.R.styleable#View_focusable
7701     */
7702    public void setFocusable(boolean focusable) {
7703        if (!focusable) {
7704            setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
7705        }
7706        setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
7707    }
7708
7709    /**
7710     * Set whether this view can receive focus while in touch mode.
7711     *
7712     * Setting this to true will also ensure that this view is focusable.
7713     *
7714     * @param focusableInTouchMode If true, this view can receive the focus while
7715     *   in touch mode.
7716     *
7717     * @see #setFocusable(boolean)
7718     * @attr ref android.R.styleable#View_focusableInTouchMode
7719     */
7720    public void setFocusableInTouchMode(boolean focusableInTouchMode) {
7721        // Focusable in touch mode should always be set before the focusable flag
7722        // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
7723        // which, in touch mode, will not successfully request focus on this view
7724        // because the focusable in touch mode flag is not set
7725        setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
7726        if (focusableInTouchMode) {
7727            setFlags(FOCUSABLE, FOCUSABLE_MASK);
7728        }
7729    }
7730
7731    /**
7732     * Set whether this view should have sound effects enabled for events such as
7733     * clicking and touching.
7734     *
7735     * <p>You may wish to disable sound effects for a view if you already play sounds,
7736     * for instance, a dial key that plays dtmf tones.
7737     *
7738     * @param soundEffectsEnabled whether sound effects are enabled for this view.
7739     * @see #isSoundEffectsEnabled()
7740     * @see #playSoundEffect(int)
7741     * @attr ref android.R.styleable#View_soundEffectsEnabled
7742     */
7743    public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
7744        setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
7745    }
7746
7747    /**
7748     * @return whether this view should have sound effects enabled for events such as
7749     *     clicking and touching.
7750     *
7751     * @see #setSoundEffectsEnabled(boolean)
7752     * @see #playSoundEffect(int)
7753     * @attr ref android.R.styleable#View_soundEffectsEnabled
7754     */
7755    @ViewDebug.ExportedProperty
7756    public boolean isSoundEffectsEnabled() {
7757        return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
7758    }
7759
7760    /**
7761     * Set whether this view should have haptic feedback for events such as
7762     * long presses.
7763     *
7764     * <p>You may wish to disable haptic feedback if your view already controls
7765     * its own haptic feedback.
7766     *
7767     * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
7768     * @see #isHapticFeedbackEnabled()
7769     * @see #performHapticFeedback(int)
7770     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7771     */
7772    public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
7773        setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
7774    }
7775
7776    /**
7777     * @return whether this view should have haptic feedback enabled for events
7778     * long presses.
7779     *
7780     * @see #setHapticFeedbackEnabled(boolean)
7781     * @see #performHapticFeedback(int)
7782     * @attr ref android.R.styleable#View_hapticFeedbackEnabled
7783     */
7784    @ViewDebug.ExportedProperty
7785    public boolean isHapticFeedbackEnabled() {
7786        return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
7787    }
7788
7789    /**
7790     * Returns the layout direction for this view.
7791     *
7792     * @return One of {@link #LAYOUT_DIRECTION_LTR},
7793     *   {@link #LAYOUT_DIRECTION_RTL},
7794     *   {@link #LAYOUT_DIRECTION_INHERIT} or
7795     *   {@link #LAYOUT_DIRECTION_LOCALE}.
7796     *
7797     * @attr ref android.R.styleable#View_layoutDirection
7798     *
7799     * @hide
7800     */
7801    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7802        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR,     to = "LTR"),
7803        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL,     to = "RTL"),
7804        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
7805        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE,  to = "LOCALE")
7806    })
7807    @LayoutDir
7808    public int getRawLayoutDirection() {
7809        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
7810    }
7811
7812    /**
7813     * Set the layout direction for this view. This will propagate a reset of layout direction
7814     * resolution to the view's children and resolve layout direction for this view.
7815     *
7816     * @param layoutDirection the layout direction to set. Should be one of:
7817     *
7818     * {@link #LAYOUT_DIRECTION_LTR},
7819     * {@link #LAYOUT_DIRECTION_RTL},
7820     * {@link #LAYOUT_DIRECTION_INHERIT},
7821     * {@link #LAYOUT_DIRECTION_LOCALE}.
7822     *
7823     * Resolution will be done if the value is set to LAYOUT_DIRECTION_INHERIT. The resolution
7824     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
7825     * will return the default {@link #LAYOUT_DIRECTION_LTR}.
7826     *
7827     * @attr ref android.R.styleable#View_layoutDirection
7828     */
7829    @RemotableViewMethod
7830    public void setLayoutDirection(@LayoutDir int layoutDirection) {
7831        if (getRawLayoutDirection() != layoutDirection) {
7832            // Reset the current layout direction and the resolved one
7833            mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
7834            resetRtlProperties();
7835            // Set the new layout direction (filtered)
7836            mPrivateFlags2 |=
7837                    ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
7838            // We need to resolve all RTL properties as they all depend on layout direction
7839            resolveRtlPropertiesIfNeeded();
7840            requestLayout();
7841            invalidate(true);
7842        }
7843    }
7844
7845    /**
7846     * Returns the resolved layout direction for this view.
7847     *
7848     * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
7849     * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
7850     *
7851     * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
7852     * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
7853     *
7854     * @attr ref android.R.styleable#View_layoutDirection
7855     */
7856    @ViewDebug.ExportedProperty(category = "layout", mapping = {
7857        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
7858        @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
7859    })
7860    @ResolvedLayoutDir
7861    public int getLayoutDirection() {
7862        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
7863        if (targetSdkVersion < JELLY_BEAN_MR1) {
7864            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
7865            return LAYOUT_DIRECTION_RESOLVED_DEFAULT;
7866        }
7867        return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ==
7868                PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ? LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
7869    }
7870
7871    /**
7872     * Indicates whether or not this view's layout is right-to-left. This is resolved from
7873     * layout attribute and/or the inherited value from the parent
7874     *
7875     * @return true if the layout is right-to-left.
7876     *
7877     * @hide
7878     */
7879    @ViewDebug.ExportedProperty(category = "layout")
7880    public boolean isLayoutRtl() {
7881        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
7882    }
7883
7884    /**
7885     * Indicates whether the view is currently tracking transient state that the
7886     * app should not need to concern itself with saving and restoring, but that
7887     * the framework should take special note to preserve when possible.
7888     *
7889     * <p>A view with transient state cannot be trivially rebound from an external
7890     * data source, such as an adapter binding item views in a list. This may be
7891     * because the view is performing an animation, tracking user selection
7892     * of content, or similar.</p>
7893     *
7894     * @return true if the view has transient state
7895     */
7896    @ViewDebug.ExportedProperty(category = "layout")
7897    public boolean hasTransientState() {
7898        return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
7899    }
7900
7901    /**
7902     * Set whether this view is currently tracking transient state that the
7903     * framework should attempt to preserve when possible. This flag is reference counted,
7904     * so every call to setHasTransientState(true) should be paired with a later call
7905     * to setHasTransientState(false).
7906     *
7907     * <p>A view with transient state cannot be trivially rebound from an external
7908     * data source, such as an adapter binding item views in a list. This may be
7909     * because the view is performing an animation, tracking user selection
7910     * of content, or similar.</p>
7911     *
7912     * @param hasTransientState true if this view has transient state
7913     */
7914    public void setHasTransientState(boolean hasTransientState) {
7915        mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
7916                mTransientStateCount - 1;
7917        if (mTransientStateCount < 0) {
7918            mTransientStateCount = 0;
7919            Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
7920                    "unmatched pair of setHasTransientState calls");
7921        } else if ((hasTransientState && mTransientStateCount == 1) ||
7922                (!hasTransientState && mTransientStateCount == 0)) {
7923            // update flag if we've just incremented up from 0 or decremented down to 0
7924            mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
7925                    (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
7926            if (mParent != null) {
7927                try {
7928                    mParent.childHasTransientStateChanged(this, hasTransientState);
7929                } catch (AbstractMethodError e) {
7930                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
7931                            " does not fully implement ViewParent", e);
7932                }
7933            }
7934        }
7935    }
7936
7937    /**
7938     * Returns true if this view is currently attached to a window.
7939     */
7940    public boolean isAttachedToWindow() {
7941        return mAttachInfo != null;
7942    }
7943
7944    /**
7945     * Returns true if this view has been through at least one layout since it
7946     * was last attached to or detached from a window.
7947     */
7948    public boolean isLaidOut() {
7949        return (mPrivateFlags3 & PFLAG3_IS_LAID_OUT) == PFLAG3_IS_LAID_OUT;
7950    }
7951
7952    /**
7953     * If this view doesn't do any drawing on its own, set this flag to
7954     * allow further optimizations. By default, this flag is not set on
7955     * View, but could be set on some View subclasses such as ViewGroup.
7956     *
7957     * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
7958     * you should clear this flag.
7959     *
7960     * @param willNotDraw whether or not this View draw on its own
7961     */
7962    public void setWillNotDraw(boolean willNotDraw) {
7963        setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
7964    }
7965
7966    /**
7967     * Returns whether or not this View draws on its own.
7968     *
7969     * @return true if this view has nothing to draw, false otherwise
7970     */
7971    @ViewDebug.ExportedProperty(category = "drawing")
7972    public boolean willNotDraw() {
7973        return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
7974    }
7975
7976    /**
7977     * When a View's drawing cache is enabled, drawing is redirected to an
7978     * offscreen bitmap. Some views, like an ImageView, must be able to
7979     * bypass this mechanism if they already draw a single bitmap, to avoid
7980     * unnecessary usage of the memory.
7981     *
7982     * @param willNotCacheDrawing true if this view does not cache its
7983     *        drawing, false otherwise
7984     */
7985    public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
7986        setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
7987    }
7988
7989    /**
7990     * Returns whether or not this View can cache its drawing or not.
7991     *
7992     * @return true if this view does not cache its drawing, false otherwise
7993     */
7994    @ViewDebug.ExportedProperty(category = "drawing")
7995    public boolean willNotCacheDrawing() {
7996        return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
7997    }
7998
7999    /**
8000     * Indicates whether this view reacts to click events or not.
8001     *
8002     * @return true if the view is clickable, false otherwise
8003     *
8004     * @see #setClickable(boolean)
8005     * @attr ref android.R.styleable#View_clickable
8006     */
8007    @ViewDebug.ExportedProperty
8008    public boolean isClickable() {
8009        return (mViewFlags & CLICKABLE) == CLICKABLE;
8010    }
8011
8012    /**
8013     * Enables or disables click events for this view. When a view
8014     * is clickable it will change its state to "pressed" on every click.
8015     * Subclasses should set the view clickable to visually react to
8016     * user's clicks.
8017     *
8018     * @param clickable true to make the view clickable, false otherwise
8019     *
8020     * @see #isClickable()
8021     * @attr ref android.R.styleable#View_clickable
8022     */
8023    public void setClickable(boolean clickable) {
8024        setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
8025    }
8026
8027    /**
8028     * Indicates whether this view reacts to long click events or not.
8029     *
8030     * @return true if the view is long clickable, false otherwise
8031     *
8032     * @see #setLongClickable(boolean)
8033     * @attr ref android.R.styleable#View_longClickable
8034     */
8035    public boolean isLongClickable() {
8036        return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
8037    }
8038
8039    /**
8040     * Enables or disables long click events for this view. When a view is long
8041     * clickable it reacts to the user holding down the button for a longer
8042     * duration than a tap. This event can either launch the listener or a
8043     * context menu.
8044     *
8045     * @param longClickable true to make the view long clickable, false otherwise
8046     * @see #isLongClickable()
8047     * @attr ref android.R.styleable#View_longClickable
8048     */
8049    public void setLongClickable(boolean longClickable) {
8050        setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
8051    }
8052
8053    /**
8054     * Indicates whether this view reacts to context clicks or not.
8055     *
8056     * @return true if the view is context clickable, false otherwise
8057     * @see #setContextClickable(boolean)
8058     * @attr ref android.R.styleable#View_contextClickable
8059     */
8060    public boolean isContextClickable() {
8061        return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
8062    }
8063
8064    /**
8065     * Enables or disables context clicking for this view. This event can launch the listener.
8066     *
8067     * @param contextClickable true to make the view react to a context click, false otherwise
8068     * @see #isContextClickable()
8069     * @attr ref android.R.styleable#View_contextClickable
8070     */
8071    public void setContextClickable(boolean contextClickable) {
8072        setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
8073    }
8074
8075    /**
8076     * Sets the pressed state for this view and provides a touch coordinate for
8077     * animation hinting.
8078     *
8079     * @param pressed Pass true to set the View's internal state to "pressed",
8080     *            or false to reverts the View's internal state from a
8081     *            previously set "pressed" state.
8082     * @param x The x coordinate of the touch that caused the press
8083     * @param y The y coordinate of the touch that caused the press
8084     */
8085    private void setPressed(boolean pressed, float x, float y) {
8086        if (pressed) {
8087            drawableHotspotChanged(x, y);
8088        }
8089
8090        setPressed(pressed);
8091    }
8092
8093    /**
8094     * Sets the pressed state for this view.
8095     *
8096     * @see #isClickable()
8097     * @see #setClickable(boolean)
8098     *
8099     * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
8100     *        the View's internal state from a previously set "pressed" state.
8101     */
8102    public void setPressed(boolean pressed) {
8103        final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
8104
8105        if (pressed) {
8106            mPrivateFlags |= PFLAG_PRESSED;
8107        } else {
8108            mPrivateFlags &= ~PFLAG_PRESSED;
8109        }
8110
8111        if (needsRefresh) {
8112            refreshDrawableState();
8113        }
8114        dispatchSetPressed(pressed);
8115    }
8116
8117    /**
8118     * Dispatch setPressed to all of this View's children.
8119     *
8120     * @see #setPressed(boolean)
8121     *
8122     * @param pressed The new pressed state
8123     */
8124    protected void dispatchSetPressed(boolean pressed) {
8125    }
8126
8127    /**
8128     * Indicates whether the view is currently in pressed state. Unless
8129     * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
8130     * the pressed state.
8131     *
8132     * @see #setPressed(boolean)
8133     * @see #isClickable()
8134     * @see #setClickable(boolean)
8135     *
8136     * @return true if the view is currently pressed, false otherwise
8137     */
8138    @ViewDebug.ExportedProperty
8139    public boolean isPressed() {
8140        return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
8141    }
8142
8143    /**
8144     * @hide
8145     * Indicates whether this view will participate in data collection through
8146     * {@link ViewStructure}.  If true, it will not provide any data
8147     * for itself or its children.  If false, the normal data collection will be allowed.
8148     *
8149     * @return Returns false if assist data collection is not blocked, else true.
8150     *
8151     * @see #setAssistBlocked(boolean)
8152     * @attr ref android.R.styleable#View_assistBlocked
8153     */
8154    public boolean isAssistBlocked() {
8155        return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
8156    }
8157
8158    /**
8159     * @hide
8160     * Controls whether assist data collection from this view and its children is enabled
8161     * (that is, whether {@link #onProvideStructure} and
8162     * {@link #onProvideVirtualStructure} will be called).  The default value is false,
8163     * allowing normal assist collection.  Setting this to false will disable assist collection.
8164     *
8165     * @param enabled Set to true to <em>disable</em> assist data collection, or false
8166     * (the default) to allow it.
8167     *
8168     * @see #isAssistBlocked()
8169     * @see #onProvideStructure
8170     * @see #onProvideVirtualStructure
8171     * @attr ref android.R.styleable#View_assistBlocked
8172     */
8173    public void setAssistBlocked(boolean enabled) {
8174        if (enabled) {
8175            mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
8176        } else {
8177            mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
8178        }
8179    }
8180
8181    /**
8182     * Indicates whether this view will save its state (that is,
8183     * whether its {@link #onSaveInstanceState} method will be called).
8184     *
8185     * @return Returns true if the view state saving is enabled, else false.
8186     *
8187     * @see #setSaveEnabled(boolean)
8188     * @attr ref android.R.styleable#View_saveEnabled
8189     */
8190    public boolean isSaveEnabled() {
8191        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
8192    }
8193
8194    /**
8195     * Controls whether the saving of this view's state is
8196     * enabled (that is, whether its {@link #onSaveInstanceState} method
8197     * will be called).  Note that even if freezing is enabled, the
8198     * view still must have an id assigned to it (via {@link #setId(int)})
8199     * for its state to be saved.  This flag can only disable the
8200     * saving of this view; any child views may still have their state saved.
8201     *
8202     * @param enabled Set to false to <em>disable</em> state saving, or true
8203     * (the default) to allow it.
8204     *
8205     * @see #isSaveEnabled()
8206     * @see #setId(int)
8207     * @see #onSaveInstanceState()
8208     * @attr ref android.R.styleable#View_saveEnabled
8209     */
8210    public void setSaveEnabled(boolean enabled) {
8211        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
8212    }
8213
8214    /**
8215     * Gets whether the framework should discard touches when the view's
8216     * window is obscured by another visible window.
8217     * Refer to the {@link View} security documentation for more details.
8218     *
8219     * @return True if touch filtering is enabled.
8220     *
8221     * @see #setFilterTouchesWhenObscured(boolean)
8222     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8223     */
8224    @ViewDebug.ExportedProperty
8225    public boolean getFilterTouchesWhenObscured() {
8226        return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
8227    }
8228
8229    /**
8230     * Sets whether the framework should discard touches when the view's
8231     * window is obscured by another visible window.
8232     * Refer to the {@link View} security documentation for more details.
8233     *
8234     * @param enabled True if touch filtering should be enabled.
8235     *
8236     * @see #getFilterTouchesWhenObscured
8237     * @attr ref android.R.styleable#View_filterTouchesWhenObscured
8238     */
8239    public void setFilterTouchesWhenObscured(boolean enabled) {
8240        setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
8241                FILTER_TOUCHES_WHEN_OBSCURED);
8242    }
8243
8244    /**
8245     * Indicates whether the entire hierarchy under this view will save its
8246     * state when a state saving traversal occurs from its parent.  The default
8247     * is true; if false, these views will not be saved unless
8248     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8249     *
8250     * @return Returns true if the view state saving from parent is enabled, else false.
8251     *
8252     * @see #setSaveFromParentEnabled(boolean)
8253     */
8254    public boolean isSaveFromParentEnabled() {
8255        return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
8256    }
8257
8258    /**
8259     * Controls whether the entire hierarchy under this view will save its
8260     * state when a state saving traversal occurs from its parent.  The default
8261     * is true; if false, these views will not be saved unless
8262     * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
8263     *
8264     * @param enabled Set to false to <em>disable</em> state saving, or true
8265     * (the default) to allow it.
8266     *
8267     * @see #isSaveFromParentEnabled()
8268     * @see #setId(int)
8269     * @see #onSaveInstanceState()
8270     */
8271    public void setSaveFromParentEnabled(boolean enabled) {
8272        setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
8273    }
8274
8275
8276    /**
8277     * Returns whether this View is able to take focus.
8278     *
8279     * @return True if this view can take focus, or false otherwise.
8280     * @attr ref android.R.styleable#View_focusable
8281     */
8282    @ViewDebug.ExportedProperty(category = "focus")
8283    public final boolean isFocusable() {
8284        return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
8285    }
8286
8287    /**
8288     * When a view is focusable, it may not want to take focus when in touch mode.
8289     * For example, a button would like focus when the user is navigating via a D-pad
8290     * so that the user can click on it, but once the user starts touching the screen,
8291     * the button shouldn't take focus
8292     * @return Whether the view is focusable in touch mode.
8293     * @attr ref android.R.styleable#View_focusableInTouchMode
8294     */
8295    @ViewDebug.ExportedProperty
8296    public final boolean isFocusableInTouchMode() {
8297        return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
8298    }
8299
8300    /**
8301     * Find the nearest view in the specified direction that can take focus.
8302     * This does not actually give focus to that view.
8303     *
8304     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8305     *
8306     * @return The nearest focusable in the specified direction, or null if none
8307     *         can be found.
8308     */
8309    public View focusSearch(@FocusRealDirection int direction) {
8310        if (mParent != null) {
8311            return mParent.focusSearch(this, direction);
8312        } else {
8313            return null;
8314        }
8315    }
8316
8317    /**
8318     * This method is the last chance for the focused view and its ancestors to
8319     * respond to an arrow key. This is called when the focused view did not
8320     * consume the key internally, nor could the view system find a new view in
8321     * the requested direction to give focus to.
8322     *
8323     * @param focused The currently focused view.
8324     * @param direction The direction focus wants to move. One of FOCUS_UP,
8325     *        FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
8326     * @return True if the this view consumed this unhandled move.
8327     */
8328    public boolean dispatchUnhandledMove(View focused, @FocusRealDirection int direction) {
8329        return false;
8330    }
8331
8332    /**
8333     * If a user manually specified the next view id for a particular direction,
8334     * use the root to look up the view.
8335     * @param root The root view of the hierarchy containing this view.
8336     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
8337     * or FOCUS_BACKWARD.
8338     * @return The user specified next view, or null if there is none.
8339     */
8340    View findUserSetNextFocus(View root, @FocusDirection int direction) {
8341        switch (direction) {
8342            case FOCUS_LEFT:
8343                if (mNextFocusLeftId == View.NO_ID) return null;
8344                return findViewInsideOutShouldExist(root, mNextFocusLeftId);
8345            case FOCUS_RIGHT:
8346                if (mNextFocusRightId == View.NO_ID) return null;
8347                return findViewInsideOutShouldExist(root, mNextFocusRightId);
8348            case FOCUS_UP:
8349                if (mNextFocusUpId == View.NO_ID) return null;
8350                return findViewInsideOutShouldExist(root, mNextFocusUpId);
8351            case FOCUS_DOWN:
8352                if (mNextFocusDownId == View.NO_ID) return null;
8353                return findViewInsideOutShouldExist(root, mNextFocusDownId);
8354            case FOCUS_FORWARD:
8355                if (mNextFocusForwardId == View.NO_ID) return null;
8356                return findViewInsideOutShouldExist(root, mNextFocusForwardId);
8357            case FOCUS_BACKWARD: {
8358                if (mID == View.NO_ID) return null;
8359                final int id = mID;
8360                return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
8361                    @Override
8362                    public boolean apply(View t) {
8363                        return t.mNextFocusForwardId == id;
8364                    }
8365                });
8366            }
8367        }
8368        return null;
8369    }
8370
8371    private View findViewInsideOutShouldExist(View root, int id) {
8372        if (mMatchIdPredicate == null) {
8373            mMatchIdPredicate = new MatchIdPredicate();
8374        }
8375        mMatchIdPredicate.mId = id;
8376        View result = root.findViewByPredicateInsideOut(this, mMatchIdPredicate);
8377        if (result == null) {
8378            Log.w(VIEW_LOG_TAG, "couldn't find view with id " + id);
8379        }
8380        return result;
8381    }
8382
8383    /**
8384     * Find and return all focusable views that are descendants of this view,
8385     * possibly including this view if it is focusable itself.
8386     *
8387     * @param direction The direction of the focus
8388     * @return A list of focusable views
8389     */
8390    public ArrayList<View> getFocusables(@FocusDirection int direction) {
8391        ArrayList<View> result = new ArrayList<View>(24);
8392        addFocusables(result, direction);
8393        return result;
8394    }
8395
8396    /**
8397     * Add any focusable views that are descendants of this view (possibly
8398     * including this view if it is focusable itself) to views.  If we are in touch mode,
8399     * only add views that are also focusable in touch mode.
8400     *
8401     * @param views Focusable views found so far
8402     * @param direction The direction of the focus
8403     */
8404    public void addFocusables(ArrayList<View> views, @FocusDirection int direction) {
8405        addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
8406    }
8407
8408    /**
8409     * Adds any focusable views that are descendants of this view (possibly
8410     * including this view if it is focusable itself) to views. This method
8411     * adds all focusable views regardless if we are in touch mode or
8412     * only views focusable in touch mode if we are in touch mode or
8413     * only views that can take accessibility focus if accessibility is enabled
8414     * depending on the focusable mode parameter.
8415     *
8416     * @param views Focusable views found so far or null if all we are interested is
8417     *        the number of focusables.
8418     * @param direction The direction of the focus.
8419     * @param focusableMode The type of focusables to be added.
8420     *
8421     * @see #FOCUSABLES_ALL
8422     * @see #FOCUSABLES_TOUCH_MODE
8423     */
8424    public void addFocusables(ArrayList<View> views, @FocusDirection int direction,
8425            @FocusableMode int focusableMode) {
8426        if (views == null) {
8427            return;
8428        }
8429        if (!isFocusable()) {
8430            return;
8431        }
8432        if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
8433                && isInTouchMode() && !isFocusableInTouchMode()) {
8434            return;
8435        }
8436        views.add(this);
8437    }
8438
8439    /**
8440     * Finds the Views that contain given text. The containment is case insensitive.
8441     * The search is performed by either the text that the View renders or the content
8442     * description that describes the view for accessibility purposes and the view does
8443     * not render or both. Clients can specify how the search is to be performed via
8444     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
8445     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
8446     *
8447     * @param outViews The output list of matching Views.
8448     * @param searched The text to match against.
8449     *
8450     * @see #FIND_VIEWS_WITH_TEXT
8451     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
8452     * @see #setContentDescription(CharSequence)
8453     */
8454    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched,
8455            @FindViewFlags int flags) {
8456        if (getAccessibilityNodeProvider() != null) {
8457            if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
8458                outViews.add(this);
8459            }
8460        } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
8461                && (searched != null && searched.length() > 0)
8462                && (mContentDescription != null && mContentDescription.length() > 0)) {
8463            String searchedLowerCase = searched.toString().toLowerCase();
8464            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
8465            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
8466                outViews.add(this);
8467            }
8468        }
8469    }
8470
8471    /**
8472     * Find and return all touchable views that are descendants of this view,
8473     * possibly including this view if it is touchable itself.
8474     *
8475     * @return A list of touchable views
8476     */
8477    public ArrayList<View> getTouchables() {
8478        ArrayList<View> result = new ArrayList<View>();
8479        addTouchables(result);
8480        return result;
8481    }
8482
8483    /**
8484     * Add any touchable views that are descendants of this view (possibly
8485     * including this view if it is touchable itself) to views.
8486     *
8487     * @param views Touchable views found so far
8488     */
8489    public void addTouchables(ArrayList<View> views) {
8490        final int viewFlags = mViewFlags;
8491
8492        if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
8493                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
8494                && (viewFlags & ENABLED_MASK) == ENABLED) {
8495            views.add(this);
8496        }
8497    }
8498
8499    /**
8500     * Returns whether this View is accessibility focused.
8501     *
8502     * @return True if this View is accessibility focused.
8503     */
8504    public boolean isAccessibilityFocused() {
8505        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
8506    }
8507
8508    /**
8509     * Call this to try to give accessibility focus to this view.
8510     *
8511     * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
8512     * returns false or the view is no visible or the view already has accessibility
8513     * focus.
8514     *
8515     * See also {@link #focusSearch(int)}, which is what you call to say that you
8516     * have focus, and you want your parent to look for the next one.
8517     *
8518     * @return Whether this view actually took accessibility focus.
8519     *
8520     * @hide
8521     */
8522    public boolean requestAccessibilityFocus() {
8523        AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
8524        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
8525            return false;
8526        }
8527        if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8528            return false;
8529        }
8530        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
8531            mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
8532            ViewRootImpl viewRootImpl = getViewRootImpl();
8533            if (viewRootImpl != null) {
8534                viewRootImpl.setAccessibilityFocus(this, null);
8535            }
8536            invalidate();
8537            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
8538            return true;
8539        }
8540        return false;
8541    }
8542
8543    /**
8544     * Call this to try to clear accessibility focus of this view.
8545     *
8546     * See also {@link #focusSearch(int)}, which is what you call to say that you
8547     * have focus, and you want your parent to look for the next one.
8548     *
8549     * @hide
8550     */
8551    public void clearAccessibilityFocus() {
8552        clearAccessibilityFocusNoCallbacks();
8553
8554        // Clear the global reference of accessibility focus if this view or
8555        // any of its descendants had accessibility focus. This will NOT send
8556        // an event or update internal state if focus is cleared from a
8557        // descendant view, which may leave views in inconsistent states.
8558        final ViewRootImpl viewRootImpl = getViewRootImpl();
8559        if (viewRootImpl != null) {
8560            final View focusHost = viewRootImpl.getAccessibilityFocusedHost();
8561            if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8562                viewRootImpl.setAccessibilityFocus(null, null);
8563            }
8564        }
8565    }
8566
8567    private void sendAccessibilityHoverEvent(int eventType) {
8568        // Since we are not delivering to a client accessibility events from not
8569        // important views (unless the clinet request that) we need to fire the
8570        // event from the deepest view exposed to the client. As a consequence if
8571        // the user crosses a not exposed view the client will see enter and exit
8572        // of the exposed predecessor followed by and enter and exit of that same
8573        // predecessor when entering and exiting the not exposed descendant. This
8574        // is fine since the client has a clear idea which view is hovered at the
8575        // price of a couple more events being sent. This is a simple and
8576        // working solution.
8577        View source = this;
8578        while (true) {
8579            if (source.includeForAccessibility()) {
8580                source.sendAccessibilityEvent(eventType);
8581                return;
8582            }
8583            ViewParent parent = source.getParent();
8584            if (parent instanceof View) {
8585                source = (View) parent;
8586            } else {
8587                return;
8588            }
8589        }
8590    }
8591
8592    /**
8593     * Clears accessibility focus without calling any callback methods
8594     * normally invoked in {@link #clearAccessibilityFocus()}. This method
8595     * is used for clearing accessibility focus when giving this focus to
8596     * another view.
8597     */
8598    void clearAccessibilityFocusNoCallbacks() {
8599        if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
8600            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
8601            invalidate();
8602            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
8603        }
8604    }
8605
8606    /**
8607     * Call this to try to give focus to a specific view or to one of its
8608     * descendants.
8609     *
8610     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8611     * false), or if it is focusable and it is not focusable in touch mode
8612     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8613     *
8614     * See also {@link #focusSearch(int)}, which is what you call to say that you
8615     * have focus, and you want your parent to look for the next one.
8616     *
8617     * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
8618     * {@link #FOCUS_DOWN} and <code>null</code>.
8619     *
8620     * @return Whether this view or one of its descendants actually took focus.
8621     */
8622    public final boolean requestFocus() {
8623        return requestFocus(View.FOCUS_DOWN);
8624    }
8625
8626    /**
8627     * Call this to try to give focus to a specific view or to one of its
8628     * descendants and give it a hint about what direction focus is heading.
8629     *
8630     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8631     * false), or if it is focusable and it is not focusable in touch mode
8632     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8633     *
8634     * See also {@link #focusSearch(int)}, which is what you call to say that you
8635     * have focus, and you want your parent to look for the next one.
8636     *
8637     * This is equivalent to calling {@link #requestFocus(int, Rect)} with
8638     * <code>null</code> set for the previously focused rectangle.
8639     *
8640     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8641     * @return Whether this view or one of its descendants actually took focus.
8642     */
8643    public final boolean requestFocus(int direction) {
8644        return requestFocus(direction, null);
8645    }
8646
8647    /**
8648     * Call this to try to give focus to a specific view or to one of its descendants
8649     * and give it hints about the direction and a specific rectangle that the focus
8650     * is coming from.  The rectangle can help give larger views a finer grained hint
8651     * about where focus is coming from, and therefore, where to show selection, or
8652     * forward focus change internally.
8653     *
8654     * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
8655     * false), or if it is focusable and it is not focusable in touch mode
8656     * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
8657     *
8658     * A View will not take focus if it is not visible.
8659     *
8660     * A View will not take focus if one of its parents has
8661     * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
8662     * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
8663     *
8664     * See also {@link #focusSearch(int)}, which is what you call to say that you
8665     * have focus, and you want your parent to look for the next one.
8666     *
8667     * You may wish to override this method if your custom {@link View} has an internal
8668     * {@link View} that it wishes to forward the request to.
8669     *
8670     * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
8671     * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
8672     *        to give a finer grained hint about where focus is coming from.  May be null
8673     *        if there is no hint.
8674     * @return Whether this view or one of its descendants actually took focus.
8675     */
8676    public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
8677        return requestFocusNoSearch(direction, previouslyFocusedRect);
8678    }
8679
8680    private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
8681        // need to be focusable
8682        if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
8683                (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
8684            return false;
8685        }
8686
8687        // need to be focusable in touch mode if in touch mode
8688        if (isInTouchMode() &&
8689            (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
8690               return false;
8691        }
8692
8693        // need to not have any parents blocking us
8694        if (hasAncestorThatBlocksDescendantFocus()) {
8695            return false;
8696        }
8697
8698        handleFocusGainInternal(direction, previouslyFocusedRect);
8699        return true;
8700    }
8701
8702    /**
8703     * Call this to try to give focus to a specific view or to one of its descendants. This is a
8704     * special variant of {@link #requestFocus() } that will allow views that are not focusable in
8705     * touch mode to request focus when they are touched.
8706     *
8707     * @return Whether this view or one of its descendants actually took focus.
8708     *
8709     * @see #isInTouchMode()
8710     *
8711     */
8712    public final boolean requestFocusFromTouch() {
8713        // Leave touch mode if we need to
8714        if (isInTouchMode()) {
8715            ViewRootImpl viewRoot = getViewRootImpl();
8716            if (viewRoot != null) {
8717                viewRoot.ensureTouchMode(false);
8718            }
8719        }
8720        return requestFocus(View.FOCUS_DOWN);
8721    }
8722
8723    /**
8724     * @return Whether any ancestor of this view blocks descendant focus.
8725     */
8726    private boolean hasAncestorThatBlocksDescendantFocus() {
8727        final boolean focusableInTouchMode = isFocusableInTouchMode();
8728        ViewParent ancestor = mParent;
8729        while (ancestor instanceof ViewGroup) {
8730            final ViewGroup vgAncestor = (ViewGroup) ancestor;
8731            if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS
8732                    || (!focusableInTouchMode && vgAncestor.shouldBlockFocusForTouchscreen())) {
8733                return true;
8734            } else {
8735                ancestor = vgAncestor.getParent();
8736            }
8737        }
8738        return false;
8739    }
8740
8741    /**
8742     * Gets the mode for determining whether this View is important for accessibility
8743     * which is if it fires accessibility events and if it is reported to
8744     * accessibility services that query the screen.
8745     *
8746     * @return The mode for determining whether a View is important for accessibility.
8747     *
8748     * @attr ref android.R.styleable#View_importantForAccessibility
8749     *
8750     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8751     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8752     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8753     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8754     */
8755    @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
8756            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
8757            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
8758            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no"),
8759            @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS,
8760                    to = "noHideDescendants")
8761        })
8762    public int getImportantForAccessibility() {
8763        return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8764                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8765    }
8766
8767    /**
8768     * Sets the live region mode for this view. This indicates to accessibility
8769     * services whether they should automatically notify the user about changes
8770     * to the view's content description or text, or to the content descriptions
8771     * or text of the view's children (where applicable).
8772     * <p>
8773     * For example, in a login screen with a TextView that displays an "incorrect
8774     * password" notification, that view should be marked as a live region with
8775     * mode {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8776     * <p>
8777     * To disable change notifications for this view, use
8778     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}. This is the default live region
8779     * mode for most views.
8780     * <p>
8781     * To indicate that the user should be notified of changes, use
8782     * {@link #ACCESSIBILITY_LIVE_REGION_POLITE}.
8783     * <p>
8784     * If the view's changes should interrupt ongoing speech and notify the user
8785     * immediately, use {@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}.
8786     *
8787     * @param mode The live region mode for this view, one of:
8788     *        <ul>
8789     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_NONE}
8790     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_POLITE}
8791     *        <li>{@link #ACCESSIBILITY_LIVE_REGION_ASSERTIVE}
8792     *        </ul>
8793     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8794     */
8795    public void setAccessibilityLiveRegion(int mode) {
8796        if (mode != getAccessibilityLiveRegion()) {
8797            mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8798            mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT)
8799                    & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK;
8800            notifyViewAccessibilityStateChangedIfNeeded(
8801                    AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8802        }
8803    }
8804
8805    /**
8806     * Gets the live region mode for this View.
8807     *
8808     * @return The live region mode for the view.
8809     *
8810     * @attr ref android.R.styleable#View_accessibilityLiveRegion
8811     *
8812     * @see #setAccessibilityLiveRegion(int)
8813     */
8814    public int getAccessibilityLiveRegion() {
8815        return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK)
8816                >> PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT;
8817    }
8818
8819    /**
8820     * Sets how to determine whether this view is important for accessibility
8821     * which is if it fires accessibility events and if it is reported to
8822     * accessibility services that query the screen.
8823     *
8824     * @param mode How to determine whether this view is important for accessibility.
8825     *
8826     * @attr ref android.R.styleable#View_importantForAccessibility
8827     *
8828     * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
8829     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
8830     * @see #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
8831     * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
8832     */
8833    public void setImportantForAccessibility(int mode) {
8834        final int oldMode = getImportantForAccessibility();
8835        if (mode != oldMode) {
8836            final boolean hideDescendants =
8837                    mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
8838
8839            // If this node or its descendants are no longer important, try to
8840            // clear accessibility focus.
8841            if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO || hideDescendants) {
8842                final View focusHost = findAccessibilityFocusHost(hideDescendants);
8843                if (focusHost != null) {
8844                    focusHost.clearAccessibilityFocus();
8845                }
8846            }
8847
8848            // If we're moving between AUTO and another state, we might not need
8849            // to send a subtree changed notification. We'll store the computed
8850            // importance, since we'll need to check it later to make sure.
8851            final boolean maySkipNotify = oldMode == IMPORTANT_FOR_ACCESSIBILITY_AUTO
8852                    || mode == IMPORTANT_FOR_ACCESSIBILITY_AUTO;
8853            final boolean oldIncludeForAccessibility = maySkipNotify && includeForAccessibility();
8854            mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8855            mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
8856                    & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
8857            if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) {
8858                notifySubtreeAccessibilityStateChangedIfNeeded();
8859            } else {
8860                notifyViewAccessibilityStateChangedIfNeeded(
8861                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
8862            }
8863        }
8864    }
8865
8866    /**
8867     * Returns the view within this view's hierarchy that is hosting
8868     * accessibility focus.
8869     *
8870     * @param searchDescendants whether to search for focus in descendant views
8871     * @return the view hosting accessibility focus, or {@code null}
8872     */
8873    private View findAccessibilityFocusHost(boolean searchDescendants) {
8874        if (isAccessibilityFocusedViewOrHost()) {
8875            return this;
8876        }
8877
8878        if (searchDescendants) {
8879            final ViewRootImpl viewRoot = getViewRootImpl();
8880            if (viewRoot != null) {
8881                final View focusHost = viewRoot.getAccessibilityFocusedHost();
8882                if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
8883                    return focusHost;
8884                }
8885            }
8886        }
8887
8888        return null;
8889    }
8890
8891    /**
8892     * Computes whether this view should be exposed for accessibility. In
8893     * general, views that are interactive or provide information are exposed
8894     * while views that serve only as containers are hidden.
8895     * <p>
8896     * If an ancestor of this view has importance
8897     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, this method
8898     * returns <code>false</code>.
8899     * <p>
8900     * Otherwise, the value is computed according to the view's
8901     * {@link #getImportantForAccessibility()} value:
8902     * <ol>
8903     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_NO} or
8904     * {@link #IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS}, return <code>false
8905     * </code>
8906     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_YES}, return <code>true</code>
8907     * <li>{@link #IMPORTANT_FOR_ACCESSIBILITY_AUTO}, return <code>true</code> if
8908     * view satisfies any of the following:
8909     * <ul>
8910     * <li>Is actionable, e.g. {@link #isClickable()},
8911     * {@link #isLongClickable()}, or {@link #isFocusable()}
8912     * <li>Has an {@link AccessibilityDelegate}
8913     * <li>Has an interaction listener, e.g. {@link OnTouchListener},
8914     * {@link OnKeyListener}, etc.
8915     * <li>Is an accessibility live region, e.g.
8916     * {@link #getAccessibilityLiveRegion()} is not
8917     * {@link #ACCESSIBILITY_LIVE_REGION_NONE}.
8918     * </ul>
8919     * </ol>
8920     *
8921     * @return Whether the view is exposed for accessibility.
8922     * @see #setImportantForAccessibility(int)
8923     * @see #getImportantForAccessibility()
8924     */
8925    public boolean isImportantForAccessibility() {
8926        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
8927                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
8928        if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
8929                || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8930            return false;
8931        }
8932
8933        // Check parent mode to ensure we're not hidden.
8934        ViewParent parent = mParent;
8935        while (parent instanceof View) {
8936            if (((View) parent).getImportantForAccessibility()
8937                    == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
8938                return false;
8939            }
8940            parent = parent.getParent();
8941        }
8942
8943        return mode == IMPORTANT_FOR_ACCESSIBILITY_YES || isActionableForAccessibility()
8944                || hasListenersForAccessibility() || getAccessibilityNodeProvider() != null
8945                || getAccessibilityLiveRegion() != ACCESSIBILITY_LIVE_REGION_NONE;
8946    }
8947
8948    /**
8949     * Gets the parent for accessibility purposes. Note that the parent for
8950     * accessibility is not necessary the immediate parent. It is the first
8951     * predecessor that is important for accessibility.
8952     *
8953     * @return The parent for accessibility purposes.
8954     */
8955    public ViewParent getParentForAccessibility() {
8956        if (mParent instanceof View) {
8957            View parentView = (View) mParent;
8958            if (parentView.includeForAccessibility()) {
8959                return mParent;
8960            } else {
8961                return mParent.getParentForAccessibility();
8962            }
8963        }
8964        return null;
8965    }
8966
8967    /**
8968     * Adds the children of this View relevant for accessibility to the given list
8969     * as output. Since some Views are not important for accessibility the added
8970     * child views are not necessarily direct children of this view, rather they are
8971     * the first level of descendants important for accessibility.
8972     *
8973     * @param outChildren The output list that will receive children for accessibility.
8974     */
8975    public void addChildrenForAccessibility(ArrayList<View> outChildren) {
8976
8977    }
8978
8979    /**
8980     * Whether to regard this view for accessibility. A view is regarded for
8981     * accessibility if it is important for accessibility or the querying
8982     * accessibility service has explicitly requested that view not
8983     * important for accessibility are regarded.
8984     *
8985     * @return Whether to regard the view for accessibility.
8986     *
8987     * @hide
8988     */
8989    public boolean includeForAccessibility() {
8990        if (mAttachInfo != null) {
8991            return (mAttachInfo.mAccessibilityFetchFlags
8992                    & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0
8993                    || isImportantForAccessibility();
8994        }
8995        return false;
8996    }
8997
8998    /**
8999     * Returns whether the View is considered actionable from
9000     * accessibility perspective. Such view are important for
9001     * accessibility.
9002     *
9003     * @return True if the view is actionable for accessibility.
9004     *
9005     * @hide
9006     */
9007    public boolean isActionableForAccessibility() {
9008        return (isClickable() || isLongClickable() || isFocusable());
9009    }
9010
9011    /**
9012     * Returns whether the View has registered callbacks which makes it
9013     * important for accessibility.
9014     *
9015     * @return True if the view is actionable for accessibility.
9016     */
9017    private boolean hasListenersForAccessibility() {
9018        ListenerInfo info = getListenerInfo();
9019        return mTouchDelegate != null || info.mOnKeyListener != null
9020                || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
9021                || info.mOnHoverListener != null || info.mOnDragListener != null;
9022    }
9023
9024    /**
9025     * Notifies that the accessibility state of this view changed. The change
9026     * is local to this view and does not represent structural changes such
9027     * as children and parent. For example, the view became focusable. The
9028     * notification is at at most once every
9029     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9030     * to avoid unnecessary load to the system. Also once a view has a pending
9031     * notification this method is a NOP until the notification has been sent.
9032     *
9033     * @hide
9034     */
9035    public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {
9036        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9037            return;
9038        }
9039        if (mSendViewStateChangedAccessibilityEvent == null) {
9040            mSendViewStateChangedAccessibilityEvent =
9041                    new SendViewStateChangedAccessibilityEvent();
9042        }
9043        mSendViewStateChangedAccessibilityEvent.runOrPost(changeType);
9044    }
9045
9046    /**
9047     * Notifies that the accessibility state of this view changed. The change
9048     * is *not* local to this view and does represent structural changes such
9049     * as children and parent. For example, the view size changed. The
9050     * notification is at at most once every
9051     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
9052     * to avoid unnecessary load to the system. Also once a view has a pending
9053     * notification this method is a NOP until the notification has been sent.
9054     *
9055     * @hide
9056     */
9057    public void notifySubtreeAccessibilityStateChangedIfNeeded() {
9058        if (!AccessibilityManager.getInstance(mContext).isEnabled() || mAttachInfo == null) {
9059            return;
9060        }
9061        if ((mPrivateFlags2 & PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED) == 0) {
9062            mPrivateFlags2 |= PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9063            if (mParent != null) {
9064                try {
9065                    mParent.notifySubtreeAccessibilityStateChanged(
9066                            this, this, AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
9067                } catch (AbstractMethodError e) {
9068                    Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
9069                            " does not fully implement ViewParent", e);
9070                }
9071            }
9072        }
9073    }
9074
9075    /**
9076     * Change the visibility of the View without triggering any other changes. This is
9077     * important for transitions, where visibility changes should not adjust focus or
9078     * trigger a new layout. This is only used when the visibility has already been changed
9079     * and we need a transient value during an animation. When the animation completes,
9080     * the original visibility value is always restored.
9081     *
9082     * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
9083     * @hide
9084     */
9085    public void setTransitionVisibility(@Visibility int visibility) {
9086        mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
9087    }
9088
9089    /**
9090     * Reset the flag indicating the accessibility state of the subtree rooted
9091     * at this view changed.
9092     */
9093    void resetSubtreeAccessibilityStateChanged() {
9094        mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
9095    }
9096
9097    /**
9098     * Report an accessibility action to this view's parents for delegated processing.
9099     *
9100     * <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
9101     * call this method to delegate an accessibility action to a supporting parent. If the parent
9102     * returns true from its
9103     * {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
9104     * method this method will return true to signify that the action was consumed.</p>
9105     *
9106     * <p>This method is useful for implementing nested scrolling child views. If
9107     * {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
9108     * a custom view implementation may invoke this method to allow a parent to consume the
9109     * scroll first. If this method returns true the custom view should skip its own scrolling
9110     * behavior.</p>
9111     *
9112     * @param action Accessibility action to delegate
9113     * @param arguments Optional action arguments
9114     * @return true if the action was consumed by a parent
9115     */
9116    public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
9117        for (ViewParent p = getParent(); p != null; p = p.getParent()) {
9118            if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
9119                return true;
9120            }
9121        }
9122        return false;
9123    }
9124
9125    /**
9126     * Performs the specified accessibility action on the view. For
9127     * possible accessibility actions look at {@link AccessibilityNodeInfo}.
9128     * <p>
9129     * If an {@link AccessibilityDelegate} has been specified via calling
9130     * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
9131     * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
9132     * is responsible for handling this call.
9133     * </p>
9134     *
9135     * <p>The default implementation will delegate
9136     * {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
9137     * {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
9138     * {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
9139     *
9140     * @param action The action to perform.
9141     * @param arguments Optional action arguments.
9142     * @return Whether the action was performed.
9143     */
9144    public boolean performAccessibilityAction(int action, Bundle arguments) {
9145      if (mAccessibilityDelegate != null) {
9146          return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
9147      } else {
9148          return performAccessibilityActionInternal(action, arguments);
9149      }
9150    }
9151
9152   /**
9153    * @see #performAccessibilityAction(int, Bundle)
9154    *
9155    * Note: Called from the default {@link AccessibilityDelegate}.
9156    *
9157    * @hide
9158    */
9159    public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
9160        if (isNestedScrollingEnabled()
9161                && (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
9162                || action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
9163                || action == R.id.accessibilityActionScrollUp
9164                || action == R.id.accessibilityActionScrollLeft
9165                || action == R.id.accessibilityActionScrollDown
9166                || action == R.id.accessibilityActionScrollRight)) {
9167            if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
9168                return true;
9169            }
9170        }
9171
9172        switch (action) {
9173            case AccessibilityNodeInfo.ACTION_CLICK: {
9174                if (isClickable()) {
9175                    performClick();
9176                    return true;
9177                }
9178            } break;
9179            case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
9180                if (isLongClickable()) {
9181                    performLongClick();
9182                    return true;
9183                }
9184            } break;
9185            case AccessibilityNodeInfo.ACTION_FOCUS: {
9186                if (!hasFocus()) {
9187                    // Get out of touch mode since accessibility
9188                    // wants to move focus around.
9189                    getViewRootImpl().ensureTouchMode(false);
9190                    return requestFocus();
9191                }
9192            } break;
9193            case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
9194                if (hasFocus()) {
9195                    clearFocus();
9196                    return !isFocused();
9197                }
9198            } break;
9199            case AccessibilityNodeInfo.ACTION_SELECT: {
9200                if (!isSelected()) {
9201                    setSelected(true);
9202                    return isSelected();
9203                }
9204            } break;
9205            case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
9206                if (isSelected()) {
9207                    setSelected(false);
9208                    return !isSelected();
9209                }
9210            } break;
9211            case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
9212                if (!isAccessibilityFocused()) {
9213                    return requestAccessibilityFocus();
9214                }
9215            } break;
9216            case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
9217                if (isAccessibilityFocused()) {
9218                    clearAccessibilityFocus();
9219                    return true;
9220                }
9221            } break;
9222            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
9223                if (arguments != null) {
9224                    final int granularity = arguments.getInt(
9225                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9226                    final boolean extendSelection = arguments.getBoolean(
9227                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9228                    return traverseAtGranularity(granularity, true, extendSelection);
9229                }
9230            } break;
9231            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
9232                if (arguments != null) {
9233                    final int granularity = arguments.getInt(
9234                            AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
9235                    final boolean extendSelection = arguments.getBoolean(
9236                            AccessibilityNodeInfo.ACTION_ARGUMENT_EXTEND_SELECTION_BOOLEAN);
9237                    return traverseAtGranularity(granularity, false, extendSelection);
9238                }
9239            } break;
9240            case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
9241                CharSequence text = getIterableTextForAccessibility();
9242                if (text == null) {
9243                    return false;
9244                }
9245                final int start = (arguments != null) ? arguments.getInt(
9246                        AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_START_INT, -1) : -1;
9247                final int end = (arguments != null) ? arguments.getInt(
9248                AccessibilityNodeInfo.ACTION_ARGUMENT_SELECTION_END_INT, -1) : -1;
9249                // Only cursor position can be specified (selection length == 0)
9250                if ((getAccessibilitySelectionStart() != start
9251                        || getAccessibilitySelectionEnd() != end)
9252                        && (start == end)) {
9253                    setAccessibilitySelection(start, end);
9254                    notifyViewAccessibilityStateChangedIfNeeded(
9255                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
9256                    return true;
9257                }
9258            } break;
9259            case R.id.accessibilityActionShowOnScreen: {
9260                if (mAttachInfo != null) {
9261                    final Rect r = mAttachInfo.mTmpInvalRect;
9262                    getDrawingRect(r);
9263                    return requestRectangleOnScreen(r, true);
9264                }
9265            } break;
9266            case R.id.accessibilityActionContextClick: {
9267                if (isContextClickable()) {
9268                    performContextClick();
9269                    return true;
9270                }
9271            } break;
9272        }
9273        return false;
9274    }
9275
9276    private boolean traverseAtGranularity(int granularity, boolean forward,
9277            boolean extendSelection) {
9278        CharSequence text = getIterableTextForAccessibility();
9279        if (text == null || text.length() == 0) {
9280            return false;
9281        }
9282        TextSegmentIterator iterator = getIteratorForGranularity(granularity);
9283        if (iterator == null) {
9284            return false;
9285        }
9286        int current = getAccessibilitySelectionEnd();
9287        if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9288            current = forward ? 0 : text.length();
9289        }
9290        final int[] range = forward ? iterator.following(current) : iterator.preceding(current);
9291        if (range == null) {
9292            return false;
9293        }
9294        final int segmentStart = range[0];
9295        final int segmentEnd = range[1];
9296        int selectionStart;
9297        int selectionEnd;
9298        if (extendSelection && isAccessibilitySelectionExtendable()) {
9299            selectionStart = getAccessibilitySelectionStart();
9300            if (selectionStart == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
9301                selectionStart = forward ? segmentStart : segmentEnd;
9302            }
9303            selectionEnd = forward ? segmentEnd : segmentStart;
9304        } else {
9305            selectionStart = selectionEnd= forward ? segmentEnd : segmentStart;
9306        }
9307        setAccessibilitySelection(selectionStart, selectionEnd);
9308        final int action = forward ? AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
9309                : AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY;
9310        sendViewTextTraversedAtGranularityEvent(action, granularity, segmentStart, segmentEnd);
9311        return true;
9312    }
9313
9314    /**
9315     * Gets the text reported for accessibility purposes.
9316     *
9317     * @return The accessibility text.
9318     *
9319     * @hide
9320     */
9321    public CharSequence getIterableTextForAccessibility() {
9322        return getContentDescription();
9323    }
9324
9325    /**
9326     * Gets whether accessibility selection can be extended.
9327     *
9328     * @return If selection is extensible.
9329     *
9330     * @hide
9331     */
9332    public boolean isAccessibilitySelectionExtendable() {
9333        return false;
9334    }
9335
9336    /**
9337     * @hide
9338     */
9339    public int getAccessibilitySelectionStart() {
9340        return mAccessibilityCursorPosition;
9341    }
9342
9343    /**
9344     * @hide
9345     */
9346    public int getAccessibilitySelectionEnd() {
9347        return getAccessibilitySelectionStart();
9348    }
9349
9350    /**
9351     * @hide
9352     */
9353    public void setAccessibilitySelection(int start, int end) {
9354        if (start ==  end && end == mAccessibilityCursorPosition) {
9355            return;
9356        }
9357        if (start >= 0 && start == end && end <= getIterableTextForAccessibility().length()) {
9358            mAccessibilityCursorPosition = start;
9359        } else {
9360            mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
9361        }
9362        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED);
9363    }
9364
9365    private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
9366            int fromIndex, int toIndex) {
9367        if (mParent == null) {
9368            return;
9369        }
9370        AccessibilityEvent event = AccessibilityEvent.obtain(
9371                AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
9372        onInitializeAccessibilityEvent(event);
9373        onPopulateAccessibilityEvent(event);
9374        event.setFromIndex(fromIndex);
9375        event.setToIndex(toIndex);
9376        event.setAction(action);
9377        event.setMovementGranularity(granularity);
9378        mParent.requestSendAccessibilityEvent(this, event);
9379    }
9380
9381    /**
9382     * @hide
9383     */
9384    public TextSegmentIterator getIteratorForGranularity(int granularity) {
9385        switch (granularity) {
9386            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
9387                CharSequence text = getIterableTextForAccessibility();
9388                if (text != null && text.length() > 0) {
9389                    CharacterTextSegmentIterator iterator =
9390                        CharacterTextSegmentIterator.getInstance(
9391                                mContext.getResources().getConfiguration().locale);
9392                    iterator.initialize(text.toString());
9393                    return iterator;
9394                }
9395            } break;
9396            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
9397                CharSequence text = getIterableTextForAccessibility();
9398                if (text != null && text.length() > 0) {
9399                    WordTextSegmentIterator iterator =
9400                        WordTextSegmentIterator.getInstance(
9401                                mContext.getResources().getConfiguration().locale);
9402                    iterator.initialize(text.toString());
9403                    return iterator;
9404                }
9405            } break;
9406            case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
9407                CharSequence text = getIterableTextForAccessibility();
9408                if (text != null && text.length() > 0) {
9409                    ParagraphTextSegmentIterator iterator =
9410                        ParagraphTextSegmentIterator.getInstance();
9411                    iterator.initialize(text.toString());
9412                    return iterator;
9413                }
9414            } break;
9415        }
9416        return null;
9417    }
9418
9419    /**
9420     * @hide
9421     */
9422    public void dispatchStartTemporaryDetach() {
9423        onStartTemporaryDetach();
9424    }
9425
9426    /**
9427     * This is called when a container is going to temporarily detach a child, with
9428     * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
9429     * It will either be followed by {@link #onFinishTemporaryDetach()} or
9430     * {@link #onDetachedFromWindow()} when the container is done.
9431     */
9432    public void onStartTemporaryDetach() {
9433        removeUnsetPressCallback();
9434        mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
9435    }
9436
9437    /**
9438     * @hide
9439     */
9440    public void dispatchFinishTemporaryDetach() {
9441        onFinishTemporaryDetach();
9442    }
9443
9444    /**
9445     * Called after {@link #onStartTemporaryDetach} when the container is done
9446     * changing the view.
9447     */
9448    public void onFinishTemporaryDetach() {
9449    }
9450
9451    /**
9452     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
9453     * for this view's window.  Returns null if the view is not currently attached
9454     * to the window.  Normally you will not need to use this directly, but
9455     * just use the standard high-level event callbacks like
9456     * {@link #onKeyDown(int, KeyEvent)}.
9457     */
9458    public KeyEvent.DispatcherState getKeyDispatcherState() {
9459        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
9460    }
9461
9462    /**
9463     * Dispatch a key event before it is processed by any input method
9464     * associated with the view hierarchy.  This can be used to intercept
9465     * key events in special situations before the IME consumes them; a
9466     * typical example would be handling the BACK key to update the application's
9467     * UI instead of allowing the IME to see it and close itself.
9468     *
9469     * @param event The key event to be dispatched.
9470     * @return True if the event was handled, false otherwise.
9471     */
9472    public boolean dispatchKeyEventPreIme(KeyEvent event) {
9473        return onKeyPreIme(event.getKeyCode(), event);
9474    }
9475
9476    /**
9477     * Dispatch a key event to the next view on the focus path. This path runs
9478     * from the top of the view tree down to the currently focused view. If this
9479     * view has focus, it will dispatch to itself. Otherwise it will dispatch
9480     * the next node down the focus path. This method also fires any key
9481     * listeners.
9482     *
9483     * @param event The key event to be dispatched.
9484     * @return True if the event was handled, false otherwise.
9485     */
9486    public boolean dispatchKeyEvent(KeyEvent event) {
9487        if (mInputEventConsistencyVerifier != null) {
9488            mInputEventConsistencyVerifier.onKeyEvent(event, 0);
9489        }
9490
9491        // Give any attached key listener a first crack at the event.
9492        //noinspection SimplifiableIfStatement
9493        ListenerInfo li = mListenerInfo;
9494        if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
9495                && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
9496            return true;
9497        }
9498
9499        if (event.dispatch(this, mAttachInfo != null
9500                ? mAttachInfo.mKeyDispatchState : null, this)) {
9501            return true;
9502        }
9503
9504        if (mInputEventConsistencyVerifier != null) {
9505            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9506        }
9507        return false;
9508    }
9509
9510    /**
9511     * Dispatches a key shortcut event.
9512     *
9513     * @param event The key event to be dispatched.
9514     * @return True if the event was handled by the view, false otherwise.
9515     */
9516    public boolean dispatchKeyShortcutEvent(KeyEvent event) {
9517        return onKeyShortcut(event.getKeyCode(), event);
9518    }
9519
9520    /**
9521     * Pass the touch screen motion event down to the target view, or this
9522     * view if it is the target.
9523     *
9524     * @param event The motion event to be dispatched.
9525     * @return True if the event was handled by the view, false otherwise.
9526     */
9527    public boolean dispatchTouchEvent(MotionEvent event) {
9528        // If the event should be handled by accessibility focus first.
9529        if (event.isTargetAccessibilityFocus()) {
9530            // We don't have focus or no virtual descendant has it, do not handle the event.
9531            if (!isAccessibilityFocusedViewOrHost()) {
9532                return false;
9533            }
9534            // We have focus and got the event, then use normal event dispatch.
9535            event.setTargetAccessibilityFocus(false);
9536        }
9537
9538        boolean result = false;
9539
9540        if (mInputEventConsistencyVerifier != null) {
9541            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
9542        }
9543
9544        final int actionMasked = event.getActionMasked();
9545        if (actionMasked == MotionEvent.ACTION_DOWN) {
9546            // Defensive cleanup for new gesture
9547            stopNestedScroll();
9548        }
9549
9550        if (onFilterTouchEventForSecurity(event)) {
9551            //noinspection SimplifiableIfStatement
9552            ListenerInfo li = mListenerInfo;
9553            if (li != null && li.mOnTouchListener != null
9554                    && (mViewFlags & ENABLED_MASK) == ENABLED
9555                    && li.mOnTouchListener.onTouch(this, event)) {
9556                result = true;
9557            }
9558
9559            if (!result && onTouchEvent(event)) {
9560                result = true;
9561            }
9562        }
9563
9564        if (!result && mInputEventConsistencyVerifier != null) {
9565            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9566        }
9567
9568        // Clean up after nested scrolls if this is the end of a gesture;
9569        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
9570        // of the gesture.
9571        if (actionMasked == MotionEvent.ACTION_UP ||
9572                actionMasked == MotionEvent.ACTION_CANCEL ||
9573                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
9574            stopNestedScroll();
9575        }
9576
9577        return result;
9578    }
9579
9580    boolean isAccessibilityFocusedViewOrHost() {
9581        return isAccessibilityFocused() || (getViewRootImpl() != null && getViewRootImpl()
9582                .getAccessibilityFocusedHost() == this);
9583    }
9584
9585    /**
9586     * Filter the touch event to apply security policies.
9587     *
9588     * @param event The motion event to be filtered.
9589     * @return True if the event should be dispatched, false if the event should be dropped.
9590     *
9591     * @see #getFilterTouchesWhenObscured
9592     */
9593    public boolean onFilterTouchEventForSecurity(MotionEvent event) {
9594        //noinspection RedundantIfStatement
9595        if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
9596                && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
9597            // Window is obscured, drop this touch.
9598            return false;
9599        }
9600        return true;
9601    }
9602
9603    /**
9604     * Pass a trackball motion event down to the focused view.
9605     *
9606     * @param event The motion event to be dispatched.
9607     * @return True if the event was handled by the view, false otherwise.
9608     */
9609    public boolean dispatchTrackballEvent(MotionEvent event) {
9610        if (mInputEventConsistencyVerifier != null) {
9611            mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
9612        }
9613
9614        return onTrackballEvent(event);
9615    }
9616
9617    /**
9618     * Dispatch a generic motion event.
9619     * <p>
9620     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
9621     * are delivered to the view under the pointer.  All other generic motion events are
9622     * delivered to the focused view.  Hover events are handled specially and are delivered
9623     * to {@link #onHoverEvent(MotionEvent)}.
9624     * </p>
9625     *
9626     * @param event The motion event to be dispatched.
9627     * @return True if the event was handled by the view, false otherwise.
9628     */
9629    public boolean dispatchGenericMotionEvent(MotionEvent event) {
9630        if (mInputEventConsistencyVerifier != null) {
9631            mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
9632        }
9633
9634        final int source = event.getSource();
9635        if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
9636            final int action = event.getAction();
9637            if (action == MotionEvent.ACTION_HOVER_ENTER
9638                    || action == MotionEvent.ACTION_HOVER_MOVE
9639                    || action == MotionEvent.ACTION_HOVER_EXIT) {
9640                if (dispatchHoverEvent(event)) {
9641                    return true;
9642                }
9643            } else if (dispatchGenericPointerEvent(event)) {
9644                return true;
9645            }
9646        } else if (dispatchGenericFocusedEvent(event)) {
9647            return true;
9648        }
9649
9650        if (dispatchGenericMotionEventInternal(event)) {
9651            return true;
9652        }
9653
9654        if (mInputEventConsistencyVerifier != null) {
9655            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9656        }
9657        return false;
9658    }
9659
9660    private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
9661        //noinspection SimplifiableIfStatement
9662        ListenerInfo li = mListenerInfo;
9663        if (li != null && li.mOnGenericMotionListener != null
9664                && (mViewFlags & ENABLED_MASK) == ENABLED
9665                && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
9666            return true;
9667        }
9668
9669        if (onGenericMotionEvent(event)) {
9670            return true;
9671        }
9672
9673        final int actionButton = event.getActionButton();
9674        switch (event.getActionMasked()) {
9675            case MotionEvent.ACTION_BUTTON_PRESS:
9676                if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
9677                        && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9678                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9679                    if (performContextClick()) {
9680                        mInContextButtonPress = true;
9681                        setPressed(true, event.getX(), event.getY());
9682                        removeTapCallback();
9683                        removeLongPressCallback();
9684                        return true;
9685                    }
9686                }
9687                break;
9688
9689            case MotionEvent.ACTION_BUTTON_RELEASE:
9690                if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
9691                        || actionButton == MotionEvent.BUTTON_SECONDARY)) {
9692                    mInContextButtonPress = false;
9693                    mIgnoreNextUpEvent = true;
9694                }
9695                break;
9696        }
9697
9698        if (mInputEventConsistencyVerifier != null) {
9699            mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
9700        }
9701        return false;
9702    }
9703
9704    /**
9705     * Dispatch a hover event.
9706     * <p>
9707     * Do not call this method directly.
9708     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9709     * </p>
9710     *
9711     * @param event The motion event to be dispatched.
9712     * @return True if the event was handled by the view, false otherwise.
9713     */
9714    protected boolean dispatchHoverEvent(MotionEvent event) {
9715        ListenerInfo li = mListenerInfo;
9716        //noinspection SimplifiableIfStatement
9717        if (li != null && li.mOnHoverListener != null
9718                && (mViewFlags & ENABLED_MASK) == ENABLED
9719                && li.mOnHoverListener.onHover(this, event)) {
9720            return true;
9721        }
9722
9723        return onHoverEvent(event);
9724    }
9725
9726    /**
9727     * Returns true if the view has a child to which it has recently sent
9728     * {@link MotionEvent#ACTION_HOVER_ENTER}.  If this view is hovered and
9729     * it does not have a hovered child, then it must be the innermost hovered view.
9730     * @hide
9731     */
9732    protected boolean hasHoveredChild() {
9733        return false;
9734    }
9735
9736    /**
9737     * Dispatch a generic motion event to the view under the first pointer.
9738     * <p>
9739     * Do not call this method directly.
9740     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9741     * </p>
9742     *
9743     * @param event The motion event to be dispatched.
9744     * @return True if the event was handled by the view, false otherwise.
9745     */
9746    protected boolean dispatchGenericPointerEvent(MotionEvent event) {
9747        return false;
9748    }
9749
9750    /**
9751     * Dispatch a generic motion event to the currently focused view.
9752     * <p>
9753     * Do not call this method directly.
9754     * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
9755     * </p>
9756     *
9757     * @param event The motion event to be dispatched.
9758     * @return True if the event was handled by the view, false otherwise.
9759     */
9760    protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
9761        return false;
9762    }
9763
9764    /**
9765     * Dispatch a pointer event.
9766     * <p>
9767     * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
9768     * other events to {@link #onGenericMotionEvent(MotionEvent)}.  This separation of concerns
9769     * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
9770     * and should not be expected to handle other pointing device features.
9771     * </p>
9772     *
9773     * @param event The motion event to be dispatched.
9774     * @return True if the event was handled by the view, false otherwise.
9775     * @hide
9776     */
9777    public final boolean dispatchPointerEvent(MotionEvent event) {
9778        if (event.isTouchEvent()) {
9779            return dispatchTouchEvent(event);
9780        } else {
9781            return dispatchGenericMotionEvent(event);
9782        }
9783    }
9784
9785    /**
9786     * Called when the window containing this view gains or loses window focus.
9787     * ViewGroups should override to route to their children.
9788     *
9789     * @param hasFocus True if the window containing this view now has focus,
9790     *        false otherwise.
9791     */
9792    public void dispatchWindowFocusChanged(boolean hasFocus) {
9793        onWindowFocusChanged(hasFocus);
9794    }
9795
9796    /**
9797     * Called when the window containing this view gains or loses focus.  Note
9798     * that this is separate from view focus: to receive key events, both
9799     * your view and its window must have focus.  If a window is displayed
9800     * on top of yours that takes input focus, then your own window will lose
9801     * focus but the view focus will remain unchanged.
9802     *
9803     * @param hasWindowFocus True if the window containing this view now has
9804     *        focus, false otherwise.
9805     */
9806    public void onWindowFocusChanged(boolean hasWindowFocus) {
9807        InputMethodManager imm = InputMethodManager.peekInstance();
9808        if (!hasWindowFocus) {
9809            if (isPressed()) {
9810                setPressed(false);
9811            }
9812            if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9813                imm.focusOut(this);
9814            }
9815            removeLongPressCallback();
9816            removeTapCallback();
9817            onFocusLost();
9818        } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
9819            imm.focusIn(this);
9820        }
9821        refreshDrawableState();
9822    }
9823
9824    /**
9825     * Returns true if this view is in a window that currently has window focus.
9826     * Note that this is not the same as the view itself having focus.
9827     *
9828     * @return True if this view is in a window that currently has window focus.
9829     */
9830    public boolean hasWindowFocus() {
9831        return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
9832    }
9833
9834    /**
9835     * Dispatch a view visibility change down the view hierarchy.
9836     * ViewGroups should override to route to their children.
9837     * @param changedView The view whose visibility changed. Could be 'this' or
9838     * an ancestor view.
9839     * @param visibility The new visibility of changedView: {@link #VISIBLE},
9840     * {@link #INVISIBLE} or {@link #GONE}.
9841     */
9842    protected void dispatchVisibilityChanged(@NonNull View changedView,
9843            @Visibility int visibility) {
9844        onVisibilityChanged(changedView, visibility);
9845    }
9846
9847    /**
9848     * Called when the visibility of the view or an ancestor of the view has
9849     * changed.
9850     *
9851     * @param changedView The view whose visibility changed. May be
9852     *                    {@code this} or an ancestor view.
9853     * @param visibility The new visibility, one of {@link #VISIBLE},
9854     *                   {@link #INVISIBLE} or {@link #GONE}.
9855     */
9856    protected void onVisibilityChanged(@NonNull View changedView, @Visibility int visibility) {
9857        final boolean visible = visibility == VISIBLE && getVisibility() == VISIBLE;
9858        if (visible && mAttachInfo != null) {
9859            initialAwakenScrollBars();
9860        }
9861
9862        final Drawable dr = mBackground;
9863        if (dr != null && visible != dr.isVisible()) {
9864            dr.setVisible(visible, false);
9865        }
9866        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
9867        if (fg != null && visible != fg.isVisible()) {
9868            fg.setVisible(visible, false);
9869        }
9870    }
9871
9872    /**
9873     * Dispatch a hint about whether this view is displayed. For instance, when
9874     * a View moves out of the screen, it might receives a display hint indicating
9875     * the view is not displayed. Applications should not <em>rely</em> on this hint
9876     * as there is no guarantee that they will receive one.
9877     *
9878     * @param hint A hint about whether or not this view is displayed:
9879     * {@link #VISIBLE} or {@link #INVISIBLE}.
9880     */
9881    public void dispatchDisplayHint(@Visibility int hint) {
9882        onDisplayHint(hint);
9883    }
9884
9885    /**
9886     * Gives this view a hint about whether is displayed or not. For instance, when
9887     * a View moves out of the screen, it might receives a display hint indicating
9888     * the view is not displayed. Applications should not <em>rely</em> on this hint
9889     * as there is no guarantee that they will receive one.
9890     *
9891     * @param hint A hint about whether or not this view is displayed:
9892     * {@link #VISIBLE} or {@link #INVISIBLE}.
9893     */
9894    protected void onDisplayHint(@Visibility int hint) {
9895    }
9896
9897    /**
9898     * Dispatch a window visibility change down the view hierarchy.
9899     * ViewGroups should override to route to their children.
9900     *
9901     * @param visibility The new visibility of the window.
9902     *
9903     * @see #onWindowVisibilityChanged(int)
9904     */
9905    public void dispatchWindowVisibilityChanged(@Visibility int visibility) {
9906        onWindowVisibilityChanged(visibility);
9907    }
9908
9909    /**
9910     * Called when the window containing has change its visibility
9911     * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}).  Note
9912     * that this tells you whether or not your window is being made visible
9913     * to the window manager; this does <em>not</em> tell you whether or not
9914     * your window is obscured by other windows on the screen, even if it
9915     * is itself visible.
9916     *
9917     * @param visibility The new visibility of the window.
9918     */
9919    protected void onWindowVisibilityChanged(@Visibility int visibility) {
9920        if (visibility == VISIBLE) {
9921            initialAwakenScrollBars();
9922        }
9923    }
9924
9925    /**
9926     * Returns the current visibility of the window this view is attached to
9927     * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
9928     *
9929     * @return Returns the current visibility of the view's window.
9930     */
9931    @Visibility
9932    public int getWindowVisibility() {
9933        return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
9934    }
9935
9936    /**
9937     * Retrieve the overall visible display size in which the window this view is
9938     * attached to has been positioned in.  This takes into account screen
9939     * decorations above the window, for both cases where the window itself
9940     * is being position inside of them or the window is being placed under
9941     * then and covered insets are used for the window to position its content
9942     * inside.  In effect, this tells you the available area where content can
9943     * be placed and remain visible to users.
9944     *
9945     * <p>This function requires an IPC back to the window manager to retrieve
9946     * the requested information, so should not be used in performance critical
9947     * code like drawing.
9948     *
9949     * @param outRect Filled in with the visible display frame.  If the view
9950     * is not attached to a window, this is simply the raw display size.
9951     */
9952    public void getWindowVisibleDisplayFrame(Rect outRect) {
9953        if (mAttachInfo != null) {
9954            try {
9955                mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
9956            } catch (RemoteException e) {
9957                return;
9958            }
9959            // XXX This is really broken, and probably all needs to be done
9960            // in the window manager, and we need to know more about whether
9961            // we want the area behind or in front of the IME.
9962            final Rect insets = mAttachInfo.mVisibleInsets;
9963            outRect.left += insets.left;
9964            outRect.top += insets.top;
9965            outRect.right -= insets.right;
9966            outRect.bottom -= insets.bottom;
9967            return;
9968        }
9969        // The view is not attached to a display so we don't have a context.
9970        // Make a best guess about the display size.
9971        Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
9972        d.getRectSize(outRect);
9973    }
9974
9975    /**
9976     * Dispatch a notification about a resource configuration change down
9977     * the view hierarchy.
9978     * ViewGroups should override to route to their children.
9979     *
9980     * @param newConfig The new resource configuration.
9981     *
9982     * @see #onConfigurationChanged(android.content.res.Configuration)
9983     */
9984    public void dispatchConfigurationChanged(Configuration newConfig) {
9985        onConfigurationChanged(newConfig);
9986    }
9987
9988    /**
9989     * Called when the current configuration of the resources being used
9990     * by the application have changed.  You can use this to decide when
9991     * to reload resources that can changed based on orientation and other
9992     * configuration characteristics.  You only need to use this if you are
9993     * not relying on the normal {@link android.app.Activity} mechanism of
9994     * recreating the activity instance upon a configuration change.
9995     *
9996     * @param newConfig The new resource configuration.
9997     */
9998    protected void onConfigurationChanged(Configuration newConfig) {
9999    }
10000
10001    /**
10002     * Private function to aggregate all per-view attributes in to the view
10003     * root.
10004     */
10005    void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10006        performCollectViewAttributes(attachInfo, visibility);
10007    }
10008
10009    void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
10010        if ((visibility & VISIBILITY_MASK) == VISIBLE) {
10011            if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
10012                attachInfo.mKeepScreenOn = true;
10013            }
10014            attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
10015            ListenerInfo li = mListenerInfo;
10016            if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
10017                attachInfo.mHasSystemUiListeners = true;
10018            }
10019        }
10020    }
10021
10022    void needGlobalAttributesUpdate(boolean force) {
10023        final AttachInfo ai = mAttachInfo;
10024        if (ai != null && !ai.mRecomputeGlobalAttributes) {
10025            if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
10026                    || ai.mHasSystemUiListeners) {
10027                ai.mRecomputeGlobalAttributes = true;
10028            }
10029        }
10030    }
10031
10032    /**
10033     * Returns whether the device is currently in touch mode.  Touch mode is entered
10034     * once the user begins interacting with the device by touch, and affects various
10035     * things like whether focus is always visible to the user.
10036     *
10037     * @return Whether the device is in touch mode.
10038     */
10039    @ViewDebug.ExportedProperty
10040    public boolean isInTouchMode() {
10041        if (mAttachInfo != null) {
10042            return mAttachInfo.mInTouchMode;
10043        } else {
10044            return ViewRootImpl.isInTouchMode();
10045        }
10046    }
10047
10048    /**
10049     * Returns the context the view is running in, through which it can
10050     * access the current theme, resources, etc.
10051     *
10052     * @return The view's Context.
10053     */
10054    @ViewDebug.CapturedViewProperty
10055    public final Context getContext() {
10056        return mContext;
10057    }
10058
10059    /**
10060     * Handle a key event before it is processed by any input method
10061     * associated with the view hierarchy.  This can be used to intercept
10062     * key events in special situations before the IME consumes them; a
10063     * typical example would be handling the BACK key to update the application's
10064     * UI instead of allowing the IME to see it and close itself.
10065     *
10066     * @param keyCode The value in event.getKeyCode().
10067     * @param event Description of the key event.
10068     * @return If you handled the event, return true. If you want to allow the
10069     *         event to be handled by the next receiver, return false.
10070     */
10071    public boolean onKeyPreIme(int keyCode, KeyEvent event) {
10072        return false;
10073    }
10074
10075    /**
10076     * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
10077     * KeyEvent.Callback.onKeyDown()}: perform press of the view
10078     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
10079     * is released, if the view is enabled and clickable.
10080     * <p>
10081     * Key presses in software keyboards will generally NOT trigger this
10082     * listener, although some may elect to do so in some situations. Do not
10083     * rely on this to catch software key presses.
10084     *
10085     * @param keyCode a key code that represents the button pressed, from
10086     *                {@link android.view.KeyEvent}
10087     * @param event the KeyEvent object that defines the button action
10088     */
10089    public boolean onKeyDown(int keyCode, KeyEvent event) {
10090        if (KeyEvent.isConfirmKey(keyCode)) {
10091            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10092                return true;
10093            }
10094
10095            // Long clickable items don't necessarily have to be clickable.
10096            if (((mViewFlags & CLICKABLE) == CLICKABLE
10097                    || (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10098                    && (event.getRepeatCount() == 0)) {
10099                // For the purposes of menu anchoring and drawable hotspots,
10100                // key events are considered to be at the center of the view.
10101                final float x = getWidth() / 2f;
10102                final float y = getHeight() / 2f;
10103                setPressed(true, x, y);
10104                checkForLongClick(0, x, y);
10105                return true;
10106            }
10107        }
10108
10109        return false;
10110    }
10111
10112    /**
10113     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
10114     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
10115     * the event).
10116     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10117     * although some may elect to do so in some situations. Do not rely on this to
10118     * catch software key presses.
10119     */
10120    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
10121        return false;
10122    }
10123
10124    /**
10125     * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
10126     * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
10127     * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
10128     * {@link KeyEvent#KEYCODE_ENTER} is released.
10129     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10130     * although some may elect to do so in some situations. Do not rely on this to
10131     * catch software key presses.
10132     *
10133     * @param keyCode A key code that represents the button pressed, from
10134     *                {@link android.view.KeyEvent}.
10135     * @param event   The KeyEvent object that defines the button action.
10136     */
10137    public boolean onKeyUp(int keyCode, KeyEvent event) {
10138        if (KeyEvent.isConfirmKey(keyCode)) {
10139            if ((mViewFlags & ENABLED_MASK) == DISABLED) {
10140                return true;
10141            }
10142            if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
10143                setPressed(false);
10144
10145                if (!mHasPerformedLongPress) {
10146                    // This is a tap, so remove the longpress check
10147                    removeLongPressCallback();
10148                    return performClick();
10149                }
10150            }
10151        }
10152        return false;
10153    }
10154
10155    /**
10156     * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
10157     * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
10158     * the event).
10159     * <p>Key presses in software keyboards will generally NOT trigger this listener,
10160     * although some may elect to do so in some situations. Do not rely on this to
10161     * catch software key presses.
10162     *
10163     * @param keyCode     A key code that represents the button pressed, from
10164     *                    {@link android.view.KeyEvent}.
10165     * @param repeatCount The number of times the action was made.
10166     * @param event       The KeyEvent object that defines the button action.
10167     */
10168    public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
10169        return false;
10170    }
10171
10172    /**
10173     * Called on the focused view when a key shortcut event is not handled.
10174     * Override this method to implement local key shortcuts for the View.
10175     * Key shortcuts can also be implemented by setting the
10176     * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
10177     *
10178     * @param keyCode The value in event.getKeyCode().
10179     * @param event Description of the key event.
10180     * @return If you handled the event, return true. If you want to allow the
10181     *         event to be handled by the next receiver, return false.
10182     */
10183    public boolean onKeyShortcut(int keyCode, KeyEvent event) {
10184        return false;
10185    }
10186
10187    /**
10188     * Check whether the called view is a text editor, in which case it
10189     * would make sense to automatically display a soft input window for
10190     * it.  Subclasses should override this if they implement
10191     * {@link #onCreateInputConnection(EditorInfo)} to return true if
10192     * a call on that method would return a non-null InputConnection, and
10193     * they are really a first-class editor that the user would normally
10194     * start typing on when the go into a window containing your view.
10195     *
10196     * <p>The default implementation always returns false.  This does
10197     * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
10198     * will not be called or the user can not otherwise perform edits on your
10199     * view; it is just a hint to the system that this is not the primary
10200     * purpose of this view.
10201     *
10202     * @return Returns true if this view is a text editor, else false.
10203     */
10204    public boolean onCheckIsTextEditor() {
10205        return false;
10206    }
10207
10208    /**
10209     * Create a new InputConnection for an InputMethod to interact
10210     * with the view.  The default implementation returns null, since it doesn't
10211     * support input methods.  You can override this to implement such support.
10212     * This is only needed for views that take focus and text input.
10213     *
10214     * <p>When implementing this, you probably also want to implement
10215     * {@link #onCheckIsTextEditor()} to indicate you will return a
10216     * non-null InputConnection.</p>
10217     *
10218     * <p>Also, take good care to fill in the {@link android.view.inputmethod.EditorInfo}
10219     * object correctly and in its entirety, so that the connected IME can rely
10220     * on its values. For example, {@link android.view.inputmethod.EditorInfo#initialSelStart}
10221     * and  {@link android.view.inputmethod.EditorInfo#initialSelEnd} members
10222     * must be filled in with the correct cursor position for IMEs to work correctly
10223     * with your application.</p>
10224     *
10225     * @param outAttrs Fill in with attribute information about the connection.
10226     */
10227    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
10228        return null;
10229    }
10230
10231    /**
10232     * Called by the {@link android.view.inputmethod.InputMethodManager}
10233     * when a view who is not the current
10234     * input connection target is trying to make a call on the manager.  The
10235     * default implementation returns false; you can override this to return
10236     * true for certain views if you are performing InputConnection proxying
10237     * to them.
10238     * @param view The View that is making the InputMethodManager call.
10239     * @return Return true to allow the call, false to reject.
10240     */
10241    public boolean checkInputConnectionProxy(View view) {
10242        return false;
10243    }
10244
10245    /**
10246     * Show the context menu for this view. It is not safe to hold on to the
10247     * menu after returning from this method.
10248     *
10249     * You should normally not overload this method. Overload
10250     * {@link #onCreateContextMenu(ContextMenu)} or define an
10251     * {@link OnCreateContextMenuListener} to add items to the context menu.
10252     *
10253     * @param menu The context menu to populate
10254     */
10255    public void createContextMenu(ContextMenu menu) {
10256        ContextMenuInfo menuInfo = getContextMenuInfo();
10257
10258        // Sets the current menu info so all items added to menu will have
10259        // my extra info set.
10260        ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
10261
10262        onCreateContextMenu(menu);
10263        ListenerInfo li = mListenerInfo;
10264        if (li != null && li.mOnCreateContextMenuListener != null) {
10265            li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
10266        }
10267
10268        // Clear the extra information so subsequent items that aren't mine don't
10269        // have my extra info.
10270        ((MenuBuilder)menu).setCurrentMenuInfo(null);
10271
10272        if (mParent != null) {
10273            mParent.createContextMenu(menu);
10274        }
10275    }
10276
10277    /**
10278     * Views should implement this if they have extra information to associate
10279     * with the context menu. The return result is supplied as a parameter to
10280     * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
10281     * callback.
10282     *
10283     * @return Extra information about the item for which the context menu
10284     *         should be shown. This information will vary across different
10285     *         subclasses of View.
10286     */
10287    protected ContextMenuInfo getContextMenuInfo() {
10288        return null;
10289    }
10290
10291    /**
10292     * Views should implement this if the view itself is going to add items to
10293     * the context menu.
10294     *
10295     * @param menu the context menu to populate
10296     */
10297    protected void onCreateContextMenu(ContextMenu menu) {
10298    }
10299
10300    /**
10301     * Implement this method to handle trackball motion events.  The
10302     * <em>relative</em> movement of the trackball since the last event
10303     * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
10304     * {@link MotionEvent#getY MotionEvent.getY()}.  These are normalized so
10305     * that a movement of 1 corresponds to the user pressing one DPAD key (so
10306     * they will often be fractional values, representing the more fine-grained
10307     * movement information available from a trackball).
10308     *
10309     * @param event The motion event.
10310     * @return True if the event was handled, false otherwise.
10311     */
10312    public boolean onTrackballEvent(MotionEvent event) {
10313        return false;
10314    }
10315
10316    /**
10317     * Implement this method to handle generic motion events.
10318     * <p>
10319     * Generic motion events describe joystick movements, mouse hovers, track pad
10320     * touches, scroll wheel movements and other input events.  The
10321     * {@link MotionEvent#getSource() source} of the motion event specifies
10322     * the class of input that was received.  Implementations of this method
10323     * must examine the bits in the source before processing the event.
10324     * The following code example shows how this is done.
10325     * </p><p>
10326     * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
10327     * are delivered to the view under the pointer.  All other generic motion events are
10328     * delivered to the focused view.
10329     * </p>
10330     * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
10331     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK)) {
10332     *         if (event.getAction() == MotionEvent.ACTION_MOVE) {
10333     *             // process the joystick movement...
10334     *             return true;
10335     *         }
10336     *     }
10337     *     if (event.isFromSource(InputDevice.SOURCE_CLASS_POINTER)) {
10338     *         switch (event.getAction()) {
10339     *             case MotionEvent.ACTION_HOVER_MOVE:
10340     *                 // process the mouse hover movement...
10341     *                 return true;
10342     *             case MotionEvent.ACTION_SCROLL:
10343     *                 // process the scroll wheel movement...
10344     *                 return true;
10345     *         }
10346     *     }
10347     *     return super.onGenericMotionEvent(event);
10348     * }</pre>
10349     *
10350     * @param event The generic motion event being processed.
10351     * @return True if the event was handled, false otherwise.
10352     */
10353    public boolean onGenericMotionEvent(MotionEvent event) {
10354        return false;
10355    }
10356
10357    /**
10358     * Implement this method to handle hover events.
10359     * <p>
10360     * This method is called whenever a pointer is hovering into, over, or out of the
10361     * bounds of a view and the view is not currently being touched.
10362     * Hover events are represented as pointer events with action
10363     * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
10364     * or {@link MotionEvent#ACTION_HOVER_EXIT}.
10365     * </p>
10366     * <ul>
10367     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
10368     * when the pointer enters the bounds of the view.</li>
10369     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
10370     * when the pointer has already entered the bounds of the view and has moved.</li>
10371     * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
10372     * when the pointer has exited the bounds of the view or when the pointer is
10373     * about to go down due to a button click, tap, or similar user action that
10374     * causes the view to be touched.</li>
10375     * </ul>
10376     * <p>
10377     * The view should implement this method to return true to indicate that it is
10378     * handling the hover event, such as by changing its drawable state.
10379     * </p><p>
10380     * The default implementation calls {@link #setHovered} to update the hovered state
10381     * of the view when a hover enter or hover exit event is received, if the view
10382     * is enabled and is clickable.  The default implementation also sends hover
10383     * accessibility events.
10384     * </p>
10385     *
10386     * @param event The motion event that describes the hover.
10387     * @return True if the view handled the hover event.
10388     *
10389     * @see #isHovered
10390     * @see #setHovered
10391     * @see #onHoverChanged
10392     */
10393    public boolean onHoverEvent(MotionEvent event) {
10394        // The root view may receive hover (or touch) events that are outside the bounds of
10395        // the window.  This code ensures that we only send accessibility events for
10396        // hovers that are actually within the bounds of the root view.
10397        final int action = event.getActionMasked();
10398        if (!mSendingHoverAccessibilityEvents) {
10399            if ((action == MotionEvent.ACTION_HOVER_ENTER
10400                    || action == MotionEvent.ACTION_HOVER_MOVE)
10401                    && !hasHoveredChild()
10402                    && pointInView(event.getX(), event.getY())) {
10403                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
10404                mSendingHoverAccessibilityEvents = true;
10405            }
10406        } else {
10407            if (action == MotionEvent.ACTION_HOVER_EXIT
10408                    || (action == MotionEvent.ACTION_MOVE
10409                            && !pointInView(event.getX(), event.getY()))) {
10410                mSendingHoverAccessibilityEvents = false;
10411                sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
10412            }
10413        }
10414
10415        if (isHoverable()) {
10416            switch (action) {
10417                case MotionEvent.ACTION_HOVER_ENTER:
10418                    setHovered(true);
10419                    break;
10420                case MotionEvent.ACTION_HOVER_EXIT:
10421                    setHovered(false);
10422                    break;
10423            }
10424
10425            // Dispatch the event to onGenericMotionEvent before returning true.
10426            // This is to provide compatibility with existing applications that
10427            // handled HOVER_MOVE events in onGenericMotionEvent and that would
10428            // break because of the new default handling for hoverable views
10429            // in onHoverEvent.
10430            // Note that onGenericMotionEvent will be called by default when
10431            // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
10432            dispatchGenericMotionEventInternal(event);
10433            // The event was already handled by calling setHovered(), so always
10434            // return true.
10435            return true;
10436        }
10437
10438        return false;
10439    }
10440
10441    /**
10442     * Returns true if the view should handle {@link #onHoverEvent}
10443     * by calling {@link #setHovered} to change its hovered state.
10444     *
10445     * @return True if the view is hoverable.
10446     */
10447    private boolean isHoverable() {
10448        final int viewFlags = mViewFlags;
10449        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10450            return false;
10451        }
10452
10453        return (viewFlags & CLICKABLE) == CLICKABLE
10454                || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
10455                || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
10456    }
10457
10458    /**
10459     * Returns true if the view is currently hovered.
10460     *
10461     * @return True if the view is currently hovered.
10462     *
10463     * @see #setHovered
10464     * @see #onHoverChanged
10465     */
10466    @ViewDebug.ExportedProperty
10467    public boolean isHovered() {
10468        return (mPrivateFlags & PFLAG_HOVERED) != 0;
10469    }
10470
10471    /**
10472     * Sets whether the view is currently hovered.
10473     * <p>
10474     * Calling this method also changes the drawable state of the view.  This
10475     * enables the view to react to hover by using different drawable resources
10476     * to change its appearance.
10477     * </p><p>
10478     * The {@link #onHoverChanged} method is called when the hovered state changes.
10479     * </p>
10480     *
10481     * @param hovered True if the view is hovered.
10482     *
10483     * @see #isHovered
10484     * @see #onHoverChanged
10485     */
10486    public void setHovered(boolean hovered) {
10487        if (hovered) {
10488            if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
10489                mPrivateFlags |= PFLAG_HOVERED;
10490                refreshDrawableState();
10491                onHoverChanged(true);
10492            }
10493        } else {
10494            if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
10495                mPrivateFlags &= ~PFLAG_HOVERED;
10496                refreshDrawableState();
10497                onHoverChanged(false);
10498            }
10499        }
10500    }
10501
10502    /**
10503     * Implement this method to handle hover state changes.
10504     * <p>
10505     * This method is called whenever the hover state changes as a result of a
10506     * call to {@link #setHovered}.
10507     * </p>
10508     *
10509     * @param hovered The current hover state, as returned by {@link #isHovered}.
10510     *
10511     * @see #isHovered
10512     * @see #setHovered
10513     */
10514    public void onHoverChanged(boolean hovered) {
10515    }
10516
10517    /**
10518     * Implement this method to handle touch screen motion events.
10519     * <p>
10520     * If this method is used to detect click actions, it is recommended that
10521     * the actions be performed by implementing and calling
10522     * {@link #performClick()}. This will ensure consistent system behavior,
10523     * including:
10524     * <ul>
10525     * <li>obeying click sound preferences
10526     * <li>dispatching OnClickListener calls
10527     * <li>handling {@link AccessibilityNodeInfo#ACTION_CLICK ACTION_CLICK} when
10528     * accessibility features are enabled
10529     * </ul>
10530     *
10531     * @param event The motion event.
10532     * @return True if the event was handled, false otherwise.
10533     */
10534    public boolean onTouchEvent(MotionEvent event) {
10535        final float x = event.getX();
10536        final float y = event.getY();
10537        final int viewFlags = mViewFlags;
10538        final int action = event.getAction();
10539
10540        if ((viewFlags & ENABLED_MASK) == DISABLED) {
10541            if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
10542                setPressed(false);
10543            }
10544            // A disabled view that is clickable still consumes the touch
10545            // events, it just doesn't respond to them.
10546            return (((viewFlags & CLICKABLE) == CLICKABLE
10547                    || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
10548                    || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
10549        }
10550
10551        if (mTouchDelegate != null) {
10552            if (mTouchDelegate.onTouchEvent(event)) {
10553                return true;
10554            }
10555        }
10556
10557        if (((viewFlags & CLICKABLE) == CLICKABLE ||
10558                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
10559                (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
10560            switch (action) {
10561                case MotionEvent.ACTION_UP:
10562                    boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
10563                    if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
10564                        // take focus if we don't have it already and we should in
10565                        // touch mode.
10566                        boolean focusTaken = false;
10567                        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
10568                            focusTaken = requestFocus();
10569                        }
10570
10571                        if (prepressed) {
10572                            // The button is being released before we actually
10573                            // showed it as pressed.  Make it show the pressed
10574                            // state now (before scheduling the click) to ensure
10575                            // the user sees it.
10576                            setPressed(true, x, y);
10577                       }
10578
10579                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
10580                            // This is a tap, so remove the longpress check
10581                            removeLongPressCallback();
10582
10583                            // Only perform take click actions if we were in the pressed state
10584                            if (!focusTaken) {
10585                                // Use a Runnable and post this rather than calling
10586                                // performClick directly. This lets other visual state
10587                                // of the view update before click actions start.
10588                                if (mPerformClick == null) {
10589                                    mPerformClick = new PerformClick();
10590                                }
10591                                if (!post(mPerformClick)) {
10592                                    performClick();
10593                                }
10594                            }
10595                        }
10596
10597                        if (mUnsetPressedState == null) {
10598                            mUnsetPressedState = new UnsetPressedState();
10599                        }
10600
10601                        if (prepressed) {
10602                            postDelayed(mUnsetPressedState,
10603                                    ViewConfiguration.getPressedStateDuration());
10604                        } else if (!post(mUnsetPressedState)) {
10605                            // If the post failed, unpress right now
10606                            mUnsetPressedState.run();
10607                        }
10608
10609                        removeTapCallback();
10610                    }
10611                    mIgnoreNextUpEvent = false;
10612                    break;
10613
10614                case MotionEvent.ACTION_DOWN:
10615                    mHasPerformedLongPress = false;
10616
10617                    if (performButtonActionOnTouchDown(event)) {
10618                        break;
10619                    }
10620
10621                    // Walk up the hierarchy to determine if we're inside a scrolling container.
10622                    boolean isInScrollingContainer = isInScrollingContainer();
10623
10624                    // For views inside a scrolling container, delay the pressed feedback for
10625                    // a short period in case this is a scroll.
10626                    if (isInScrollingContainer) {
10627                        mPrivateFlags |= PFLAG_PREPRESSED;
10628                        if (mPendingCheckForTap == null) {
10629                            mPendingCheckForTap = new CheckForTap();
10630                        }
10631                        mPendingCheckForTap.x = event.getX();
10632                        mPendingCheckForTap.y = event.getY();
10633                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
10634                    } else {
10635                        // Not inside a scrolling container, so show the feedback right away
10636                        setPressed(true, x, y);
10637                        checkForLongClick(0, x, y);
10638                    }
10639                    break;
10640
10641                case MotionEvent.ACTION_CANCEL:
10642                    setPressed(false);
10643                    removeTapCallback();
10644                    removeLongPressCallback();
10645                    mInContextButtonPress = false;
10646                    mHasPerformedLongPress = false;
10647                    mIgnoreNextUpEvent = false;
10648                    break;
10649
10650                case MotionEvent.ACTION_MOVE:
10651                    drawableHotspotChanged(x, y);
10652
10653                    // Be lenient about moving outside of buttons
10654                    if (!pointInView(x, y, mTouchSlop)) {
10655                        // Outside button
10656                        removeTapCallback();
10657                        if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
10658                            // Remove any future long press/tap checks
10659                            removeLongPressCallback();
10660
10661                            setPressed(false);
10662                        }
10663                    }
10664                    break;
10665            }
10666
10667            return true;
10668        }
10669
10670        return false;
10671    }
10672
10673    /**
10674     * @hide
10675     */
10676    public boolean isInScrollingContainer() {
10677        ViewParent p = getParent();
10678        while (p != null && p instanceof ViewGroup) {
10679            if (((ViewGroup) p).shouldDelayChildPressedState()) {
10680                return true;
10681            }
10682            p = p.getParent();
10683        }
10684        return false;
10685    }
10686
10687    /**
10688     * Remove the longpress detection timer.
10689     */
10690    private void removeLongPressCallback() {
10691        if (mPendingCheckForLongPress != null) {
10692          removeCallbacks(mPendingCheckForLongPress);
10693        }
10694    }
10695
10696    /**
10697     * Remove the pending click action
10698     */
10699    private void removePerformClickCallback() {
10700        if (mPerformClick != null) {
10701            removeCallbacks(mPerformClick);
10702        }
10703    }
10704
10705    /**
10706     * Remove the prepress detection timer.
10707     */
10708    private void removeUnsetPressCallback() {
10709        if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
10710            setPressed(false);
10711            removeCallbacks(mUnsetPressedState);
10712        }
10713    }
10714
10715    /**
10716     * Remove the tap detection timer.
10717     */
10718    private void removeTapCallback() {
10719        if (mPendingCheckForTap != null) {
10720            mPrivateFlags &= ~PFLAG_PREPRESSED;
10721            removeCallbacks(mPendingCheckForTap);
10722        }
10723    }
10724
10725    /**
10726     * Cancels a pending long press.  Your subclass can use this if you
10727     * want the context menu to come up if the user presses and holds
10728     * at the same place, but you don't want it to come up if they press
10729     * and then move around enough to cause scrolling.
10730     */
10731    public void cancelLongPress() {
10732        removeLongPressCallback();
10733
10734        /*
10735         * The prepressed state handled by the tap callback is a display
10736         * construct, but the tap callback will post a long press callback
10737         * less its own timeout. Remove it here.
10738         */
10739        removeTapCallback();
10740    }
10741
10742    /**
10743     * Remove the pending callback for sending a
10744     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
10745     */
10746    private void removeSendViewScrolledAccessibilityEventCallback() {
10747        if (mSendViewScrolledAccessibilityEvent != null) {
10748            removeCallbacks(mSendViewScrolledAccessibilityEvent);
10749            mSendViewScrolledAccessibilityEvent.mIsPending = false;
10750        }
10751    }
10752
10753    /**
10754     * Sets the TouchDelegate for this View.
10755     */
10756    public void setTouchDelegate(TouchDelegate delegate) {
10757        mTouchDelegate = delegate;
10758    }
10759
10760    /**
10761     * Gets the TouchDelegate for this View.
10762     */
10763    public TouchDelegate getTouchDelegate() {
10764        return mTouchDelegate;
10765    }
10766
10767    /**
10768     * Request unbuffered dispatch of the given stream of MotionEvents to this View.
10769     *
10770     * Until this View receives a corresponding {@link MotionEvent#ACTION_UP}, ask that the input
10771     * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
10772     * available. This method should only be called for touch events.
10773     *
10774     * <p class="note">This api is not intended for most applications. Buffered dispatch
10775     * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
10776     * streams will not improve your input latency. Side effects include: increased latency,
10777     * jittery scrolls and inability to take advantage of system resampling. Talk to your input
10778     * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
10779     * you.</p>
10780     */
10781    public final void requestUnbufferedDispatch(MotionEvent event) {
10782        final int action = event.getAction();
10783        if (mAttachInfo == null
10784                || action != MotionEvent.ACTION_DOWN && action != MotionEvent.ACTION_MOVE
10785                || !event.isTouchEvent()) {
10786            return;
10787        }
10788        mAttachInfo.mUnbufferedDispatchRequested = true;
10789    }
10790
10791    /**
10792     * Set flags controlling behavior of this view.
10793     *
10794     * @param flags Constant indicating the value which should be set
10795     * @param mask Constant indicating the bit range that should be changed
10796     */
10797    void setFlags(int flags, int mask) {
10798        final boolean accessibilityEnabled =
10799                AccessibilityManager.getInstance(mContext).isEnabled();
10800        final boolean oldIncludeForAccessibility = accessibilityEnabled && includeForAccessibility();
10801
10802        int old = mViewFlags;
10803        mViewFlags = (mViewFlags & ~mask) | (flags & mask);
10804
10805        int changed = mViewFlags ^ old;
10806        if (changed == 0) {
10807            return;
10808        }
10809        int privateFlags = mPrivateFlags;
10810
10811        /* Check if the FOCUSABLE bit has changed */
10812        if (((changed & FOCUSABLE_MASK) != 0) &&
10813                ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
10814            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
10815                    && ((privateFlags & PFLAG_FOCUSED) != 0)) {
10816                /* Give up focus if we are no longer focusable */
10817                clearFocus();
10818            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
10819                    && ((privateFlags & PFLAG_FOCUSED) == 0)) {
10820                /*
10821                 * Tell the view system that we are now available to take focus
10822                 * if no one else already has it.
10823                 */
10824                if (mParent != null) mParent.focusableViewAvailable(this);
10825            }
10826        }
10827
10828        final int newVisibility = flags & VISIBILITY_MASK;
10829        if (newVisibility == VISIBLE) {
10830            if ((changed & VISIBILITY_MASK) != 0) {
10831                /*
10832                 * If this view is becoming visible, invalidate it in case it changed while
10833                 * it was not visible. Marking it drawn ensures that the invalidation will
10834                 * go through.
10835                 */
10836                mPrivateFlags |= PFLAG_DRAWN;
10837                invalidate(true);
10838
10839                needGlobalAttributesUpdate(true);
10840
10841                // a view becoming visible is worth notifying the parent
10842                // about in case nothing has focus.  even if this specific view
10843                // isn't focusable, it may contain something that is, so let
10844                // the root view try to give this focus if nothing else does.
10845                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
10846                    mParent.focusableViewAvailable(this);
10847                }
10848            }
10849        }
10850
10851        /* Check if the GONE bit has changed */
10852        if ((changed & GONE) != 0) {
10853            needGlobalAttributesUpdate(false);
10854            requestLayout();
10855
10856            if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
10857                if (hasFocus()) clearFocus();
10858                clearAccessibilityFocus();
10859                destroyDrawingCache();
10860                if (mParent instanceof View) {
10861                    // GONE views noop invalidation, so invalidate the parent
10862                    ((View) mParent).invalidate(true);
10863                }
10864                // Mark the view drawn to ensure that it gets invalidated properly the next
10865                // time it is visible and gets invalidated
10866                mPrivateFlags |= PFLAG_DRAWN;
10867            }
10868            if (mAttachInfo != null) {
10869                mAttachInfo.mViewVisibilityChanged = true;
10870            }
10871        }
10872
10873        /* Check if the VISIBLE bit has changed */
10874        if ((changed & INVISIBLE) != 0) {
10875            needGlobalAttributesUpdate(false);
10876            /*
10877             * If this view is becoming invisible, set the DRAWN flag so that
10878             * the next invalidate() will not be skipped.
10879             */
10880            mPrivateFlags |= PFLAG_DRAWN;
10881
10882            if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE)) {
10883                // root view becoming invisible shouldn't clear focus and accessibility focus
10884                if (getRootView() != this) {
10885                    if (hasFocus()) clearFocus();
10886                    clearAccessibilityFocus();
10887                }
10888            }
10889            if (mAttachInfo != null) {
10890                mAttachInfo.mViewVisibilityChanged = true;
10891            }
10892        }
10893
10894        if ((changed & VISIBILITY_MASK) != 0) {
10895            // If the view is invisible, cleanup its display list to free up resources
10896            if (newVisibility != VISIBLE && mAttachInfo != null) {
10897                cleanupDraw();
10898            }
10899
10900            if (mParent instanceof ViewGroup) {
10901                ((ViewGroup) mParent).onChildVisibilityChanged(this,
10902                        (changed & VISIBILITY_MASK), newVisibility);
10903                ((View) mParent).invalidate(true);
10904            } else if (mParent != null) {
10905                mParent.invalidateChild(this, null);
10906            }
10907
10908            if (mAttachInfo != null) {
10909                dispatchVisibilityChanged(this, newVisibility);
10910                notifySubtreeAccessibilityStateChangedIfNeeded();
10911            }
10912        }
10913
10914        if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
10915            destroyDrawingCache();
10916        }
10917
10918        if ((changed & DRAWING_CACHE_ENABLED) != 0) {
10919            destroyDrawingCache();
10920            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10921            invalidateParentCaches();
10922        }
10923
10924        if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
10925            destroyDrawingCache();
10926            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10927        }
10928
10929        if ((changed & DRAW_MASK) != 0) {
10930            if ((mViewFlags & WILL_NOT_DRAW) != 0) {
10931                if (mBackground != null
10932                        || (mForegroundInfo != null && mForegroundInfo.mDrawable != null)) {
10933                    mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10934                } else {
10935                    mPrivateFlags |= PFLAG_SKIP_DRAW;
10936                }
10937            } else {
10938                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
10939            }
10940            requestLayout();
10941            invalidate(true);
10942        }
10943
10944        if ((changed & KEEP_SCREEN_ON) != 0) {
10945            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
10946                mParent.recomputeViewAttributes(this);
10947            }
10948        }
10949
10950        if (accessibilityEnabled) {
10951            if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
10952                    || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
10953                    || (changed & CONTEXT_CLICKABLE) != 0) {
10954                if (oldIncludeForAccessibility != includeForAccessibility()) {
10955                    notifySubtreeAccessibilityStateChangedIfNeeded();
10956                } else {
10957                    notifyViewAccessibilityStateChangedIfNeeded(
10958                            AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10959                }
10960            } else if ((changed & ENABLED_MASK) != 0) {
10961                notifyViewAccessibilityStateChangedIfNeeded(
10962                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
10963            }
10964        }
10965    }
10966
10967    /**
10968     * Change the view's z order in the tree, so it's on top of other sibling
10969     * views. This ordering change may affect layout, if the parent container
10970     * uses an order-dependent layout scheme (e.g., LinearLayout). Prior
10971     * to {@link android.os.Build.VERSION_CODES#KITKAT} this
10972     * method should be followed by calls to {@link #requestLayout()} and
10973     * {@link View#invalidate()} on the view's parent to force the parent to redraw
10974     * with the new child ordering.
10975     *
10976     * @see ViewGroup#bringChildToFront(View)
10977     */
10978    public void bringToFront() {
10979        if (mParent != null) {
10980            mParent.bringChildToFront(this);
10981        }
10982    }
10983
10984    /**
10985     * This is called in response to an internal scroll in this view (i.e., the
10986     * view scrolled its own contents). This is typically as a result of
10987     * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
10988     * called.
10989     *
10990     * @param l Current horizontal scroll origin.
10991     * @param t Current vertical scroll origin.
10992     * @param oldl Previous horizontal scroll origin.
10993     * @param oldt Previous vertical scroll origin.
10994     */
10995    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
10996        notifySubtreeAccessibilityStateChangedIfNeeded();
10997
10998        if (AccessibilityManager.getInstance(mContext).isEnabled()) {
10999            postSendViewScrolledAccessibilityEventCallback();
11000        }
11001
11002        mBackgroundSizeChanged = true;
11003        if (mForegroundInfo != null) {
11004            mForegroundInfo.mBoundsChanged = true;
11005        }
11006
11007        final AttachInfo ai = mAttachInfo;
11008        if (ai != null) {
11009            ai.mViewScrollChanged = true;
11010        }
11011
11012        if (mListenerInfo != null && mListenerInfo.mOnScrollChangeListener != null) {
11013            mListenerInfo.mOnScrollChangeListener.onScrollChange(this, l, t, oldl, oldt);
11014        }
11015    }
11016
11017    /**
11018     * Interface definition for a callback to be invoked when the scroll
11019     * X or Y positions of a view change.
11020     * <p>
11021     * <b>Note:</b> Some views handle scrolling independently from View and may
11022     * have their own separate listeners for scroll-type events. For example,
11023     * {@link android.widget.ListView ListView} allows clients to register an
11024     * {@link android.widget.ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener) AbsListView.OnScrollListener}
11025     * to listen for changes in list scroll position.
11026     *
11027     * @see #setOnScrollChangeListener(View.OnScrollChangeListener)
11028     */
11029    public interface OnScrollChangeListener {
11030        /**
11031         * Called when the scroll position of a view changes.
11032         *
11033         * @param v The view whose scroll position has changed.
11034         * @param scrollX Current horizontal scroll origin.
11035         * @param scrollY Current vertical scroll origin.
11036         * @param oldScrollX Previous horizontal scroll origin.
11037         * @param oldScrollY Previous vertical scroll origin.
11038         */
11039        void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
11040    }
11041
11042    /**
11043     * Interface definition for a callback to be invoked when the layout bounds of a view
11044     * changes due to layout processing.
11045     */
11046    public interface OnLayoutChangeListener {
11047        /**
11048         * Called when the layout bounds of a view changes due to layout processing.
11049         *
11050         * @param v The view whose bounds have changed.
11051         * @param left The new value of the view's left property.
11052         * @param top The new value of the view's top property.
11053         * @param right The new value of the view's right property.
11054         * @param bottom The new value of the view's bottom property.
11055         * @param oldLeft The previous value of the view's left property.
11056         * @param oldTop The previous value of the view's top property.
11057         * @param oldRight The previous value of the view's right property.
11058         * @param oldBottom The previous value of the view's bottom property.
11059         */
11060        void onLayoutChange(View v, int left, int top, int right, int bottom,
11061            int oldLeft, int oldTop, int oldRight, int oldBottom);
11062    }
11063
11064    /**
11065     * This is called during layout when the size of this view has changed. If
11066     * you were just added to the view hierarchy, you're called with the old
11067     * values of 0.
11068     *
11069     * @param w Current width of this view.
11070     * @param h Current height of this view.
11071     * @param oldw Old width of this view.
11072     * @param oldh Old height of this view.
11073     */
11074    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
11075    }
11076
11077    /**
11078     * Called by draw to draw the child views. This may be overridden
11079     * by derived classes to gain control just before its children are drawn
11080     * (but after its own view has been drawn).
11081     * @param canvas the canvas on which to draw the view
11082     */
11083    protected void dispatchDraw(Canvas canvas) {
11084
11085    }
11086
11087    /**
11088     * Gets the parent of this view. Note that the parent is a
11089     * ViewParent and not necessarily a View.
11090     *
11091     * @return Parent of this view.
11092     */
11093    public final ViewParent getParent() {
11094        return mParent;
11095    }
11096
11097    /**
11098     * Set the horizontal scrolled position of your view. This will cause a call to
11099     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11100     * invalidated.
11101     * @param value the x position to scroll to
11102     */
11103    public void setScrollX(int value) {
11104        scrollTo(value, mScrollY);
11105    }
11106
11107    /**
11108     * Set the vertical scrolled position of your view. This will cause a call to
11109     * {@link #onScrollChanged(int, int, int, int)} and the view will be
11110     * invalidated.
11111     * @param value the y position to scroll to
11112     */
11113    public void setScrollY(int value) {
11114        scrollTo(mScrollX, value);
11115    }
11116
11117    /**
11118     * Return the scrolled left position of this view. This is the left edge of
11119     * the displayed part of your view. You do not need to draw any pixels
11120     * farther left, since those are outside of the frame of your view on
11121     * screen.
11122     *
11123     * @return The left edge of the displayed part of your view, in pixels.
11124     */
11125    public final int getScrollX() {
11126        return mScrollX;
11127    }
11128
11129    /**
11130     * Return the scrolled top position of this view. This is the top edge of
11131     * the displayed part of your view. You do not need to draw any pixels above
11132     * it, since those are outside of the frame of your view on screen.
11133     *
11134     * @return The top edge of the displayed part of your view, in pixels.
11135     */
11136    public final int getScrollY() {
11137        return mScrollY;
11138    }
11139
11140    /**
11141     * Return the width of the your view.
11142     *
11143     * @return The width of your view, in pixels.
11144     */
11145    @ViewDebug.ExportedProperty(category = "layout")
11146    public final int getWidth() {
11147        return mRight - mLeft;
11148    }
11149
11150    /**
11151     * Return the height of your view.
11152     *
11153     * @return The height of your view, in pixels.
11154     */
11155    @ViewDebug.ExportedProperty(category = "layout")
11156    public final int getHeight() {
11157        return mBottom - mTop;
11158    }
11159
11160    /**
11161     * Return the visible drawing bounds of your view. Fills in the output
11162     * rectangle with the values from getScrollX(), getScrollY(),
11163     * getWidth(), and getHeight(). These bounds do not account for any
11164     * transformation properties currently set on the view, such as
11165     * {@link #setScaleX(float)} or {@link #setRotation(float)}.
11166     *
11167     * @param outRect The (scrolled) drawing bounds of the view.
11168     */
11169    public void getDrawingRect(Rect outRect) {
11170        outRect.left = mScrollX;
11171        outRect.top = mScrollY;
11172        outRect.right = mScrollX + (mRight - mLeft);
11173        outRect.bottom = mScrollY + (mBottom - mTop);
11174    }
11175
11176    /**
11177     * Like {@link #getMeasuredWidthAndState()}, but only returns the
11178     * raw width component (that is the result is masked by
11179     * {@link #MEASURED_SIZE_MASK}).
11180     *
11181     * @return The raw measured width of this view.
11182     */
11183    public final int getMeasuredWidth() {
11184        return mMeasuredWidth & MEASURED_SIZE_MASK;
11185    }
11186
11187    /**
11188     * Return the full width measurement information for this view as computed
11189     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11190     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11191     * This should be used during measurement and layout calculations only. Use
11192     * {@link #getWidth()} to see how wide a view is after layout.
11193     *
11194     * @return The measured width of this view as a bit mask.
11195     */
11196    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11197            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11198                    name = "MEASURED_STATE_TOO_SMALL"),
11199    })
11200    public final int getMeasuredWidthAndState() {
11201        return mMeasuredWidth;
11202    }
11203
11204    /**
11205     * Like {@link #getMeasuredHeightAndState()}, but only returns the
11206     * raw width component (that is the result is masked by
11207     * {@link #MEASURED_SIZE_MASK}).
11208     *
11209     * @return The raw measured height of this view.
11210     */
11211    public final int getMeasuredHeight() {
11212        return mMeasuredHeight & MEASURED_SIZE_MASK;
11213    }
11214
11215    /**
11216     * Return the full height measurement information for this view as computed
11217     * by the most recent call to {@link #measure(int, int)}.  This result is a bit mask
11218     * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
11219     * This should be used during measurement and layout calculations only. Use
11220     * {@link #getHeight()} to see how wide a view is after layout.
11221     *
11222     * @return The measured width of this view as a bit mask.
11223     */
11224    @ViewDebug.ExportedProperty(category = "measurement", flagMapping = {
11225            @ViewDebug.FlagToString(mask = MEASURED_STATE_MASK, equals = MEASURED_STATE_TOO_SMALL,
11226                    name = "MEASURED_STATE_TOO_SMALL"),
11227    })
11228    public final int getMeasuredHeightAndState() {
11229        return mMeasuredHeight;
11230    }
11231
11232    /**
11233     * Return only the state bits of {@link #getMeasuredWidthAndState()}
11234     * and {@link #getMeasuredHeightAndState()}, combined into one integer.
11235     * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
11236     * and the height component is at the shifted bits
11237     * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
11238     */
11239    public final int getMeasuredState() {
11240        return (mMeasuredWidth&MEASURED_STATE_MASK)
11241                | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
11242                        & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
11243    }
11244
11245    /**
11246     * The transform matrix of this view, which is calculated based on the current
11247     * rotation, scale, and pivot properties.
11248     *
11249     * @see #getRotation()
11250     * @see #getScaleX()
11251     * @see #getScaleY()
11252     * @see #getPivotX()
11253     * @see #getPivotY()
11254     * @return The current transform matrix for the view
11255     */
11256    public Matrix getMatrix() {
11257        ensureTransformationInfo();
11258        final Matrix matrix = mTransformationInfo.mMatrix;
11259        mRenderNode.getMatrix(matrix);
11260        return matrix;
11261    }
11262
11263    /**
11264     * Returns true if the transform matrix is the identity matrix.
11265     * Recomputes the matrix if necessary.
11266     *
11267     * @return True if the transform matrix is the identity matrix, false otherwise.
11268     */
11269    final boolean hasIdentityMatrix() {
11270        return mRenderNode.hasIdentityMatrix();
11271    }
11272
11273    void ensureTransformationInfo() {
11274        if (mTransformationInfo == null) {
11275            mTransformationInfo = new TransformationInfo();
11276        }
11277    }
11278
11279   /**
11280     * Utility method to retrieve the inverse of the current mMatrix property.
11281     * We cache the matrix to avoid recalculating it when transform properties
11282     * have not changed.
11283     *
11284     * @return The inverse of the current matrix of this view.
11285     * @hide
11286     */
11287    public final Matrix getInverseMatrix() {
11288        ensureTransformationInfo();
11289        if (mTransformationInfo.mInverseMatrix == null) {
11290            mTransformationInfo.mInverseMatrix = new Matrix();
11291        }
11292        final Matrix matrix = mTransformationInfo.mInverseMatrix;
11293        mRenderNode.getInverseMatrix(matrix);
11294        return matrix;
11295    }
11296
11297    /**
11298     * Gets the distance along the Z axis from the camera to this view.
11299     *
11300     * @see #setCameraDistance(float)
11301     *
11302     * @return The distance along the Z axis.
11303     */
11304    public float getCameraDistance() {
11305        final float dpi = mResources.getDisplayMetrics().densityDpi;
11306        return -(mRenderNode.getCameraDistance() * dpi);
11307    }
11308
11309    /**
11310     * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
11311     * views are drawn) from the camera to this view. The camera's distance
11312     * affects 3D transformations, for instance rotations around the X and Y
11313     * axis. If the rotationX or rotationY properties are changed and this view is
11314     * large (more than half the size of the screen), it is recommended to always
11315     * use a camera distance that's greater than the height (X axis rotation) or
11316     * the width (Y axis rotation) of this view.</p>
11317     *
11318     * <p>The distance of the camera from the view plane can have an affect on the
11319     * perspective distortion of the view when it is rotated around the x or y axis.
11320     * For example, a large distance will result in a large viewing angle, and there
11321     * will not be much perspective distortion of the view as it rotates. A short
11322     * distance may cause much more perspective distortion upon rotation, and can
11323     * also result in some drawing artifacts if the rotated view ends up partially
11324     * behind the camera (which is why the recommendation is to use a distance at
11325     * least as far as the size of the view, if the view is to be rotated.)</p>
11326     *
11327     * <p>The distance is expressed in "depth pixels." The default distance depends
11328     * on the screen density. For instance, on a medium density display, the
11329     * default distance is 1280. On a high density display, the default distance
11330     * is 1920.</p>
11331     *
11332     * <p>If you want to specify a distance that leads to visually consistent
11333     * results across various densities, use the following formula:</p>
11334     * <pre>
11335     * float scale = context.getResources().getDisplayMetrics().density;
11336     * view.setCameraDistance(distance * scale);
11337     * </pre>
11338     *
11339     * <p>The density scale factor of a high density display is 1.5,
11340     * and 1920 = 1280 * 1.5.</p>
11341     *
11342     * @param distance The distance in "depth pixels", if negative the opposite
11343     *        value is used
11344     *
11345     * @see #setRotationX(float)
11346     * @see #setRotationY(float)
11347     */
11348    public void setCameraDistance(float distance) {
11349        final float dpi = mResources.getDisplayMetrics().densityDpi;
11350
11351        invalidateViewProperty(true, false);
11352        mRenderNode.setCameraDistance(-Math.abs(distance) / dpi);
11353        invalidateViewProperty(false, false);
11354
11355        invalidateParentIfNeededAndWasQuickRejected();
11356    }
11357
11358    /**
11359     * The degrees that the view is rotated around the pivot point.
11360     *
11361     * @see #setRotation(float)
11362     * @see #getPivotX()
11363     * @see #getPivotY()
11364     *
11365     * @return The degrees of rotation.
11366     */
11367    @ViewDebug.ExportedProperty(category = "drawing")
11368    public float getRotation() {
11369        return mRenderNode.getRotation();
11370    }
11371
11372    /**
11373     * Sets the degrees that the view is rotated around the pivot point. Increasing values
11374     * result in clockwise rotation.
11375     *
11376     * @param rotation The degrees of rotation.
11377     *
11378     * @see #getRotation()
11379     * @see #getPivotX()
11380     * @see #getPivotY()
11381     * @see #setRotationX(float)
11382     * @see #setRotationY(float)
11383     *
11384     * @attr ref android.R.styleable#View_rotation
11385     */
11386    public void setRotation(float rotation) {
11387        if (rotation != getRotation()) {
11388            // Double-invalidation is necessary to capture view's old and new areas
11389            invalidateViewProperty(true, false);
11390            mRenderNode.setRotation(rotation);
11391            invalidateViewProperty(false, true);
11392
11393            invalidateParentIfNeededAndWasQuickRejected();
11394            notifySubtreeAccessibilityStateChangedIfNeeded();
11395        }
11396    }
11397
11398    /**
11399     * The degrees that the view is rotated around the vertical axis through the pivot point.
11400     *
11401     * @see #getPivotX()
11402     * @see #getPivotY()
11403     * @see #setRotationY(float)
11404     *
11405     * @return The degrees of Y rotation.
11406     */
11407    @ViewDebug.ExportedProperty(category = "drawing")
11408    public float getRotationY() {
11409        return mRenderNode.getRotationY();
11410    }
11411
11412    /**
11413     * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
11414     * Increasing values result in counter-clockwise rotation from the viewpoint of looking
11415     * down the y axis.
11416     *
11417     * When rotating large views, it is recommended to adjust the camera distance
11418     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11419     *
11420     * @param rotationY The degrees of Y rotation.
11421     *
11422     * @see #getRotationY()
11423     * @see #getPivotX()
11424     * @see #getPivotY()
11425     * @see #setRotation(float)
11426     * @see #setRotationX(float)
11427     * @see #setCameraDistance(float)
11428     *
11429     * @attr ref android.R.styleable#View_rotationY
11430     */
11431    public void setRotationY(float rotationY) {
11432        if (rotationY != getRotationY()) {
11433            invalidateViewProperty(true, false);
11434            mRenderNode.setRotationY(rotationY);
11435            invalidateViewProperty(false, true);
11436
11437            invalidateParentIfNeededAndWasQuickRejected();
11438            notifySubtreeAccessibilityStateChangedIfNeeded();
11439        }
11440    }
11441
11442    /**
11443     * The degrees that the view is rotated around the horizontal axis through the pivot point.
11444     *
11445     * @see #getPivotX()
11446     * @see #getPivotY()
11447     * @see #setRotationX(float)
11448     *
11449     * @return The degrees of X rotation.
11450     */
11451    @ViewDebug.ExportedProperty(category = "drawing")
11452    public float getRotationX() {
11453        return mRenderNode.getRotationX();
11454    }
11455
11456    /**
11457     * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
11458     * Increasing values result in clockwise rotation from the viewpoint of looking down the
11459     * x axis.
11460     *
11461     * When rotating large views, it is recommended to adjust the camera distance
11462     * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
11463     *
11464     * @param rotationX The degrees of X rotation.
11465     *
11466     * @see #getRotationX()
11467     * @see #getPivotX()
11468     * @see #getPivotY()
11469     * @see #setRotation(float)
11470     * @see #setRotationY(float)
11471     * @see #setCameraDistance(float)
11472     *
11473     * @attr ref android.R.styleable#View_rotationX
11474     */
11475    public void setRotationX(float rotationX) {
11476        if (rotationX != getRotationX()) {
11477            invalidateViewProperty(true, false);
11478            mRenderNode.setRotationX(rotationX);
11479            invalidateViewProperty(false, true);
11480
11481            invalidateParentIfNeededAndWasQuickRejected();
11482            notifySubtreeAccessibilityStateChangedIfNeeded();
11483        }
11484    }
11485
11486    /**
11487     * The amount that the view is scaled in x around the pivot point, as a proportion of
11488     * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
11489     *
11490     * <p>By default, this is 1.0f.
11491     *
11492     * @see #getPivotX()
11493     * @see #getPivotY()
11494     * @return The scaling factor.
11495     */
11496    @ViewDebug.ExportedProperty(category = "drawing")
11497    public float getScaleX() {
11498        return mRenderNode.getScaleX();
11499    }
11500
11501    /**
11502     * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
11503     * the view's unscaled width. A value of 1 means that no scaling is applied.
11504     *
11505     * @param scaleX The scaling factor.
11506     * @see #getPivotX()
11507     * @see #getPivotY()
11508     *
11509     * @attr ref android.R.styleable#View_scaleX
11510     */
11511    public void setScaleX(float scaleX) {
11512        if (scaleX != getScaleX()) {
11513            invalidateViewProperty(true, false);
11514            mRenderNode.setScaleX(scaleX);
11515            invalidateViewProperty(false, true);
11516
11517            invalidateParentIfNeededAndWasQuickRejected();
11518            notifySubtreeAccessibilityStateChangedIfNeeded();
11519        }
11520    }
11521
11522    /**
11523     * The amount that the view is scaled in y around the pivot point, as a proportion of
11524     * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
11525     *
11526     * <p>By default, this is 1.0f.
11527     *
11528     * @see #getPivotX()
11529     * @see #getPivotY()
11530     * @return The scaling factor.
11531     */
11532    @ViewDebug.ExportedProperty(category = "drawing")
11533    public float getScaleY() {
11534        return mRenderNode.getScaleY();
11535    }
11536
11537    /**
11538     * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
11539     * the view's unscaled width. A value of 1 means that no scaling is applied.
11540     *
11541     * @param scaleY The scaling factor.
11542     * @see #getPivotX()
11543     * @see #getPivotY()
11544     *
11545     * @attr ref android.R.styleable#View_scaleY
11546     */
11547    public void setScaleY(float scaleY) {
11548        if (scaleY != getScaleY()) {
11549            invalidateViewProperty(true, false);
11550            mRenderNode.setScaleY(scaleY);
11551            invalidateViewProperty(false, true);
11552
11553            invalidateParentIfNeededAndWasQuickRejected();
11554            notifySubtreeAccessibilityStateChangedIfNeeded();
11555        }
11556    }
11557
11558    /**
11559     * The x location of the point around which the view is {@link #setRotation(float) rotated}
11560     * and {@link #setScaleX(float) scaled}.
11561     *
11562     * @see #getRotation()
11563     * @see #getScaleX()
11564     * @see #getScaleY()
11565     * @see #getPivotY()
11566     * @return The x location of the pivot point.
11567     *
11568     * @attr ref android.R.styleable#View_transformPivotX
11569     */
11570    @ViewDebug.ExportedProperty(category = "drawing")
11571    public float getPivotX() {
11572        return mRenderNode.getPivotX();
11573    }
11574
11575    /**
11576     * Sets the x location of the point around which the view is
11577     * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
11578     * By default, the pivot point is centered on the object.
11579     * Setting this property disables this behavior and causes the view to use only the
11580     * explicitly set pivotX and pivotY values.
11581     *
11582     * @param pivotX The x location of the pivot point.
11583     * @see #getRotation()
11584     * @see #getScaleX()
11585     * @see #getScaleY()
11586     * @see #getPivotY()
11587     *
11588     * @attr ref android.R.styleable#View_transformPivotX
11589     */
11590    public void setPivotX(float pivotX) {
11591        if (!mRenderNode.isPivotExplicitlySet() || pivotX != getPivotX()) {
11592            invalidateViewProperty(true, false);
11593            mRenderNode.setPivotX(pivotX);
11594            invalidateViewProperty(false, true);
11595
11596            invalidateParentIfNeededAndWasQuickRejected();
11597        }
11598    }
11599
11600    /**
11601     * The y location of the point around which the view is {@link #setRotation(float) rotated}
11602     * and {@link #setScaleY(float) scaled}.
11603     *
11604     * @see #getRotation()
11605     * @see #getScaleX()
11606     * @see #getScaleY()
11607     * @see #getPivotY()
11608     * @return The y location of the pivot point.
11609     *
11610     * @attr ref android.R.styleable#View_transformPivotY
11611     */
11612    @ViewDebug.ExportedProperty(category = "drawing")
11613    public float getPivotY() {
11614        return mRenderNode.getPivotY();
11615    }
11616
11617    /**
11618     * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
11619     * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
11620     * Setting this property disables this behavior and causes the view to use only the
11621     * explicitly set pivotX and pivotY values.
11622     *
11623     * @param pivotY The y location of the pivot point.
11624     * @see #getRotation()
11625     * @see #getScaleX()
11626     * @see #getScaleY()
11627     * @see #getPivotY()
11628     *
11629     * @attr ref android.R.styleable#View_transformPivotY
11630     */
11631    public void setPivotY(float pivotY) {
11632        if (!mRenderNode.isPivotExplicitlySet() || pivotY != getPivotY()) {
11633            invalidateViewProperty(true, false);
11634            mRenderNode.setPivotY(pivotY);
11635            invalidateViewProperty(false, true);
11636
11637            invalidateParentIfNeededAndWasQuickRejected();
11638        }
11639    }
11640
11641    /**
11642     * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
11643     * completely transparent and 1 means the view is completely opaque.
11644     *
11645     * <p>By default this is 1.0f.
11646     * @return The opacity of the view.
11647     */
11648    @ViewDebug.ExportedProperty(category = "drawing")
11649    public float getAlpha() {
11650        return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
11651    }
11652
11653    /**
11654     * Returns whether this View has content which overlaps.
11655     *
11656     * <p>This function, intended to be overridden by specific View types, is an optimization when
11657     * alpha is set on a view. If rendering overlaps in a view with alpha < 1, that view is drawn to
11658     * an offscreen buffer and then composited into place, which can be expensive. If the view has
11659     * no overlapping rendering, the view can draw each primitive with the appropriate alpha value
11660     * directly. An example of overlapping rendering is a TextView with a background image, such as
11661     * a Button. An example of non-overlapping rendering is a TextView with no background, or an
11662     * ImageView with only the foreground image. The default implementation returns true; subclasses
11663     * should override if they have cases which can be optimized.</p>
11664     *
11665     * <p>The current implementation of the saveLayer and saveLayerAlpha methods in {@link Canvas}
11666     * necessitates that a View return true if it uses the methods internally without passing the
11667     * {@link Canvas#CLIP_TO_LAYER_SAVE_FLAG}.</p>
11668     *
11669     * @return true if the content in this view might overlap, false otherwise.
11670     */
11671    @ViewDebug.ExportedProperty(category = "drawing")
11672    public boolean hasOverlappingRendering() {
11673        return true;
11674    }
11675
11676    /**
11677     * Sets the opacity of the view to a value from 0 to 1, where 0 means the view is
11678     * completely transparent and 1 means the view is completely opaque.
11679     *
11680     * <p class="note"><strong>Note:</strong> setting alpha to a translucent value (0 < alpha < 1)
11681     * can have significant performance implications, especially for large views. It is best to use
11682     * the alpha property sparingly and transiently, as in the case of fading animations.</p>
11683     *
11684     * <p>For a view with a frequently changing alpha, such as during a fading animation, it is
11685     * strongly recommended for performance reasons to either override
11686     * {@link #hasOverlappingRendering()} to return <code>false</code> if appropriate, or setting a
11687     * {@link #setLayerType(int, android.graphics.Paint) layer type} on the view for the duration
11688     * of the animation. On versions {@link android.os.Build.VERSION_CODES#M} and below,
11689     * the default path for rendering an unlayered View with alpha could add multiple milliseconds
11690     * of rendering cost, even for simple or small views. Starting with
11691     * {@link android.os.Build.VERSION_CODES#M}, {@link #LAYER_TYPE_HARDWARE} is automatically
11692     * applied to the view at the rendering level.</p>
11693     *
11694     * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
11695     * responsible for applying the opacity itself.</p>
11696     *
11697     * <p>On versions {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and below, note that if
11698     * the view is backed by a {@link #setLayerType(int, android.graphics.Paint) layer} and is
11699     * associated with a {@link #setLayerPaint(android.graphics.Paint) layer paint}, setting an
11700     * alpha value less than 1.0 will supersede the alpha of the layer paint.</p>
11701     *
11702     * <p>Starting with {@link android.os.Build.VERSION_CODES#M}, setting a translucent alpha
11703     * value will clip a View to its bounds, unless the View returns <code>false</code> from
11704     * {@link #hasOverlappingRendering}.</p>
11705     *
11706     * @param alpha The opacity of the view.
11707     *
11708     * @see #hasOverlappingRendering()
11709     * @see #setLayerType(int, android.graphics.Paint)
11710     *
11711     * @attr ref android.R.styleable#View_alpha
11712     */
11713    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {
11714        ensureTransformationInfo();
11715        if (mTransformationInfo.mAlpha != alpha) {
11716            mTransformationInfo.mAlpha = alpha;
11717            if (onSetAlpha((int) (alpha * 255))) {
11718                mPrivateFlags |= PFLAG_ALPHA_SET;
11719                // subclass is handling alpha - don't optimize rendering cache invalidation
11720                invalidateParentCaches();
11721                invalidate(true);
11722            } else {
11723                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11724                invalidateViewProperty(true, false);
11725                mRenderNode.setAlpha(getFinalAlpha());
11726                notifyViewAccessibilityStateChangedIfNeeded(
11727                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
11728            }
11729        }
11730    }
11731
11732    /**
11733     * Faster version of setAlpha() which performs the same steps except there are
11734     * no calls to invalidate(). The caller of this function should perform proper invalidation
11735     * on the parent and this object. The return value indicates whether the subclass handles
11736     * alpha (the return value for onSetAlpha()).
11737     *
11738     * @param alpha The new value for the alpha property
11739     * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
11740     *         the new value for the alpha property is different from the old value
11741     */
11742    boolean setAlphaNoInvalidation(float alpha) {
11743        ensureTransformationInfo();
11744        if (mTransformationInfo.mAlpha != alpha) {
11745            mTransformationInfo.mAlpha = alpha;
11746            boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
11747            if (subclassHandlesAlpha) {
11748                mPrivateFlags |= PFLAG_ALPHA_SET;
11749                return true;
11750            } else {
11751                mPrivateFlags &= ~PFLAG_ALPHA_SET;
11752                mRenderNode.setAlpha(getFinalAlpha());
11753            }
11754        }
11755        return false;
11756    }
11757
11758    /**
11759     * This property is hidden and intended only for use by the Fade transition, which
11760     * animates it to produce a visual translucency that does not side-effect (or get
11761     * affected by) the real alpha property. This value is composited with the other
11762     * alpha value (and the AlphaAnimation value, when that is present) to produce
11763     * a final visual translucency result, which is what is passed into the DisplayList.
11764     *
11765     * @hide
11766     */
11767    public void setTransitionAlpha(float alpha) {
11768        ensureTransformationInfo();
11769        if (mTransformationInfo.mTransitionAlpha != alpha) {
11770            mTransformationInfo.mTransitionAlpha = alpha;
11771            mPrivateFlags &= ~PFLAG_ALPHA_SET;
11772            invalidateViewProperty(true, false);
11773            mRenderNode.setAlpha(getFinalAlpha());
11774        }
11775    }
11776
11777    /**
11778     * Calculates the visual alpha of this view, which is a combination of the actual
11779     * alpha value and the transitionAlpha value (if set).
11780     */
11781    private float getFinalAlpha() {
11782        if (mTransformationInfo != null) {
11783            return mTransformationInfo.mAlpha * mTransformationInfo.mTransitionAlpha;
11784        }
11785        return 1;
11786    }
11787
11788    /**
11789     * This property is hidden and intended only for use by the Fade transition, which
11790     * animates it to produce a visual translucency that does not side-effect (or get
11791     * affected by) the real alpha property. This value is composited with the other
11792     * alpha value (and the AlphaAnimation value, when that is present) to produce
11793     * a final visual translucency result, which is what is passed into the DisplayList.
11794     *
11795     * @hide
11796     */
11797    @ViewDebug.ExportedProperty(category = "drawing")
11798    public float getTransitionAlpha() {
11799        return mTransformationInfo != null ? mTransformationInfo.mTransitionAlpha : 1;
11800    }
11801
11802    /**
11803     * Top position of this view relative to its parent.
11804     *
11805     * @return The top of this view, in pixels.
11806     */
11807    @ViewDebug.CapturedViewProperty
11808    public final int getTop() {
11809        return mTop;
11810    }
11811
11812    /**
11813     * Sets the top position of this view relative to its parent. This method is meant to be called
11814     * by the layout system and should not generally be called otherwise, because the property
11815     * may be changed at any time by the layout.
11816     *
11817     * @param top The top of this view, in pixels.
11818     */
11819    public final void setTop(int top) {
11820        if (top != mTop) {
11821            final boolean matrixIsIdentity = hasIdentityMatrix();
11822            if (matrixIsIdentity) {
11823                if (mAttachInfo != null) {
11824                    int minTop;
11825                    int yLoc;
11826                    if (top < mTop) {
11827                        minTop = top;
11828                        yLoc = top - mTop;
11829                    } else {
11830                        minTop = mTop;
11831                        yLoc = 0;
11832                    }
11833                    invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
11834                }
11835            } else {
11836                // Double-invalidation is necessary to capture view's old and new areas
11837                invalidate(true);
11838            }
11839
11840            int width = mRight - mLeft;
11841            int oldHeight = mBottom - mTop;
11842
11843            mTop = top;
11844            mRenderNode.setTop(mTop);
11845
11846            sizeChange(width, mBottom - mTop, width, oldHeight);
11847
11848            if (!matrixIsIdentity) {
11849                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11850                invalidate(true);
11851            }
11852            mBackgroundSizeChanged = true;
11853            if (mForegroundInfo != null) {
11854                mForegroundInfo.mBoundsChanged = true;
11855            }
11856            invalidateParentIfNeeded();
11857            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11858                // View was rejected last time it was drawn by its parent; this may have changed
11859                invalidateParentIfNeeded();
11860            }
11861        }
11862    }
11863
11864    /**
11865     * Bottom position of this view relative to its parent.
11866     *
11867     * @return The bottom of this view, in pixels.
11868     */
11869    @ViewDebug.CapturedViewProperty
11870    public final int getBottom() {
11871        return mBottom;
11872    }
11873
11874    /**
11875     * True if this view has changed since the last time being drawn.
11876     *
11877     * @return The dirty state of this view.
11878     */
11879    public boolean isDirty() {
11880        return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
11881    }
11882
11883    /**
11884     * Sets the bottom position of this view relative to its parent. This method is meant to be
11885     * called by the layout system and should not generally be called otherwise, because the
11886     * property may be changed at any time by the layout.
11887     *
11888     * @param bottom The bottom of this view, in pixels.
11889     */
11890    public final void setBottom(int bottom) {
11891        if (bottom != mBottom) {
11892            final boolean matrixIsIdentity = hasIdentityMatrix();
11893            if (matrixIsIdentity) {
11894                if (mAttachInfo != null) {
11895                    int maxBottom;
11896                    if (bottom < mBottom) {
11897                        maxBottom = mBottom;
11898                    } else {
11899                        maxBottom = bottom;
11900                    }
11901                    invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
11902                }
11903            } else {
11904                // Double-invalidation is necessary to capture view's old and new areas
11905                invalidate(true);
11906            }
11907
11908            int width = mRight - mLeft;
11909            int oldHeight = mBottom - mTop;
11910
11911            mBottom = bottom;
11912            mRenderNode.setBottom(mBottom);
11913
11914            sizeChange(width, mBottom - mTop, width, oldHeight);
11915
11916            if (!matrixIsIdentity) {
11917                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11918                invalidate(true);
11919            }
11920            mBackgroundSizeChanged = true;
11921            if (mForegroundInfo != null) {
11922                mForegroundInfo.mBoundsChanged = true;
11923            }
11924            invalidateParentIfNeeded();
11925            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11926                // View was rejected last time it was drawn by its parent; this may have changed
11927                invalidateParentIfNeeded();
11928            }
11929        }
11930    }
11931
11932    /**
11933     * Left position of this view relative to its parent.
11934     *
11935     * @return The left edge of this view, in pixels.
11936     */
11937    @ViewDebug.CapturedViewProperty
11938    public final int getLeft() {
11939        return mLeft;
11940    }
11941
11942    /**
11943     * Sets the left position of this view relative to its parent. This method is meant to be called
11944     * by the layout system and should not generally be called otherwise, because the property
11945     * may be changed at any time by the layout.
11946     *
11947     * @param left The left of this view, in pixels.
11948     */
11949    public final void setLeft(int left) {
11950        if (left != mLeft) {
11951            final boolean matrixIsIdentity = hasIdentityMatrix();
11952            if (matrixIsIdentity) {
11953                if (mAttachInfo != null) {
11954                    int minLeft;
11955                    int xLoc;
11956                    if (left < mLeft) {
11957                        minLeft = left;
11958                        xLoc = left - mLeft;
11959                    } else {
11960                        minLeft = mLeft;
11961                        xLoc = 0;
11962                    }
11963                    invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
11964                }
11965            } else {
11966                // Double-invalidation is necessary to capture view's old and new areas
11967                invalidate(true);
11968            }
11969
11970            int oldWidth = mRight - mLeft;
11971            int height = mBottom - mTop;
11972
11973            mLeft = left;
11974            mRenderNode.setLeft(left);
11975
11976            sizeChange(mRight - mLeft, height, oldWidth, height);
11977
11978            if (!matrixIsIdentity) {
11979                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
11980                invalidate(true);
11981            }
11982            mBackgroundSizeChanged = true;
11983            if (mForegroundInfo != null) {
11984                mForegroundInfo.mBoundsChanged = true;
11985            }
11986            invalidateParentIfNeeded();
11987            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
11988                // View was rejected last time it was drawn by its parent; this may have changed
11989                invalidateParentIfNeeded();
11990            }
11991        }
11992    }
11993
11994    /**
11995     * Right position of this view relative to its parent.
11996     *
11997     * @return The right edge of this view, in pixels.
11998     */
11999    @ViewDebug.CapturedViewProperty
12000    public final int getRight() {
12001        return mRight;
12002    }
12003
12004    /**
12005     * Sets the right position of this view relative to its parent. This method is meant to be called
12006     * by the layout system and should not generally be called otherwise, because the property
12007     * may be changed at any time by the layout.
12008     *
12009     * @param right The right of this view, in pixels.
12010     */
12011    public final void setRight(int right) {
12012        if (right != mRight) {
12013            final boolean matrixIsIdentity = hasIdentityMatrix();
12014            if (matrixIsIdentity) {
12015                if (mAttachInfo != null) {
12016                    int maxRight;
12017                    if (right < mRight) {
12018                        maxRight = mRight;
12019                    } else {
12020                        maxRight = right;
12021                    }
12022                    invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
12023                }
12024            } else {
12025                // Double-invalidation is necessary to capture view's old and new areas
12026                invalidate(true);
12027            }
12028
12029            int oldWidth = mRight - mLeft;
12030            int height = mBottom - mTop;
12031
12032            mRight = right;
12033            mRenderNode.setRight(mRight);
12034
12035            sizeChange(mRight - mLeft, height, oldWidth, height);
12036
12037            if (!matrixIsIdentity) {
12038                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
12039                invalidate(true);
12040            }
12041            mBackgroundSizeChanged = true;
12042            if (mForegroundInfo != null) {
12043                mForegroundInfo.mBoundsChanged = true;
12044            }
12045            invalidateParentIfNeeded();
12046            if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
12047                // View was rejected last time it was drawn by its parent; this may have changed
12048                invalidateParentIfNeeded();
12049            }
12050        }
12051    }
12052
12053    /**
12054     * The visual x position of this view, in pixels. This is equivalent to the
12055     * {@link #setTranslationX(float) translationX} property plus the current
12056     * {@link #getLeft() left} property.
12057     *
12058     * @return The visual x position of this view, in pixels.
12059     */
12060    @ViewDebug.ExportedProperty(category = "drawing")
12061    public float getX() {
12062        return mLeft + getTranslationX();
12063    }
12064
12065    /**
12066     * Sets the visual x position of this view, in pixels. This is equivalent to setting the
12067     * {@link #setTranslationX(float) translationX} property to be the difference between
12068     * the x value passed in and the current {@link #getLeft() left} property.
12069     *
12070     * @param x The visual x position of this view, in pixels.
12071     */
12072    public void setX(float x) {
12073        setTranslationX(x - mLeft);
12074    }
12075
12076    /**
12077     * The visual y position of this view, in pixels. This is equivalent to the
12078     * {@link #setTranslationY(float) translationY} property plus the current
12079     * {@link #getTop() top} property.
12080     *
12081     * @return The visual y position of this view, in pixels.
12082     */
12083    @ViewDebug.ExportedProperty(category = "drawing")
12084    public float getY() {
12085        return mTop + getTranslationY();
12086    }
12087
12088    /**
12089     * Sets the visual y position of this view, in pixels. This is equivalent to setting the
12090     * {@link #setTranslationY(float) translationY} property to be the difference between
12091     * the y value passed in and the current {@link #getTop() top} property.
12092     *
12093     * @param y The visual y position of this view, in pixels.
12094     */
12095    public void setY(float y) {
12096        setTranslationY(y - mTop);
12097    }
12098
12099    /**
12100     * The visual z position of this view, in pixels. This is equivalent to the
12101     * {@link #setTranslationZ(float) translationZ} property plus the current
12102     * {@link #getElevation() elevation} property.
12103     *
12104     * @return The visual z position of this view, in pixels.
12105     */
12106    @ViewDebug.ExportedProperty(category = "drawing")
12107    public float getZ() {
12108        return getElevation() + getTranslationZ();
12109    }
12110
12111    /**
12112     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
12113     * {@link #setTranslationZ(float) translationZ} property to be the difference between
12114     * the x value passed in and the current {@link #getElevation() elevation} property.
12115     *
12116     * @param z The visual z position of this view, in pixels.
12117     */
12118    public void setZ(float z) {
12119        setTranslationZ(z - getElevation());
12120    }
12121
12122    /**
12123     * The base elevation of this view relative to its parent, in pixels.
12124     *
12125     * @return The base depth position of the view, in pixels.
12126     */
12127    @ViewDebug.ExportedProperty(category = "drawing")
12128    public float getElevation() {
12129        return mRenderNode.getElevation();
12130    }
12131
12132    /**
12133     * Sets the base elevation of this view, in pixels.
12134     *
12135     * @attr ref android.R.styleable#View_elevation
12136     */
12137    public void setElevation(float elevation) {
12138        if (elevation != getElevation()) {
12139            invalidateViewProperty(true, false);
12140            mRenderNode.setElevation(elevation);
12141            invalidateViewProperty(false, true);
12142
12143            invalidateParentIfNeededAndWasQuickRejected();
12144        }
12145    }
12146
12147    /**
12148     * The horizontal location of this view relative to its {@link #getLeft() left} position.
12149     * This position is post-layout, in addition to wherever the object's
12150     * layout placed it.
12151     *
12152     * @return The horizontal position of this view relative to its left position, in pixels.
12153     */
12154    @ViewDebug.ExportedProperty(category = "drawing")
12155    public float getTranslationX() {
12156        return mRenderNode.getTranslationX();
12157    }
12158
12159    /**
12160     * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
12161     * This effectively positions the object post-layout, in addition to wherever the object's
12162     * layout placed it.
12163     *
12164     * @param translationX The horizontal position of this view relative to its left position,
12165     * in pixels.
12166     *
12167     * @attr ref android.R.styleable#View_translationX
12168     */
12169    public void setTranslationX(float translationX) {
12170        if (translationX != getTranslationX()) {
12171            invalidateViewProperty(true, false);
12172            mRenderNode.setTranslationX(translationX);
12173            invalidateViewProperty(false, true);
12174
12175            invalidateParentIfNeededAndWasQuickRejected();
12176            notifySubtreeAccessibilityStateChangedIfNeeded();
12177        }
12178    }
12179
12180    /**
12181     * The vertical location of this view relative to its {@link #getTop() top} position.
12182     * This position is post-layout, in addition to wherever the object's
12183     * layout placed it.
12184     *
12185     * @return The vertical position of this view relative to its top position,
12186     * in pixels.
12187     */
12188    @ViewDebug.ExportedProperty(category = "drawing")
12189    public float getTranslationY() {
12190        return mRenderNode.getTranslationY();
12191    }
12192
12193    /**
12194     * Sets the vertical location of this view relative to its {@link #getTop() top} position.
12195     * This effectively positions the object post-layout, in addition to wherever the object's
12196     * layout placed it.
12197     *
12198     * @param translationY The vertical position of this view relative to its top position,
12199     * in pixels.
12200     *
12201     * @attr ref android.R.styleable#View_translationY
12202     */
12203    public void setTranslationY(float translationY) {
12204        if (translationY != getTranslationY()) {
12205            invalidateViewProperty(true, false);
12206            mRenderNode.setTranslationY(translationY);
12207            invalidateViewProperty(false, true);
12208
12209            invalidateParentIfNeededAndWasQuickRejected();
12210            notifySubtreeAccessibilityStateChangedIfNeeded();
12211        }
12212    }
12213
12214    /**
12215     * The depth location of this view relative to its {@link #getElevation() elevation}.
12216     *
12217     * @return The depth of this view relative to its elevation.
12218     */
12219    @ViewDebug.ExportedProperty(category = "drawing")
12220    public float getTranslationZ() {
12221        return mRenderNode.getTranslationZ();
12222    }
12223
12224    /**
12225     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
12226     *
12227     * @attr ref android.R.styleable#View_translationZ
12228     */
12229    public void setTranslationZ(float translationZ) {
12230        if (translationZ != getTranslationZ()) {
12231            invalidateViewProperty(true, false);
12232            mRenderNode.setTranslationZ(translationZ);
12233            invalidateViewProperty(false, true);
12234
12235            invalidateParentIfNeededAndWasQuickRejected();
12236        }
12237    }
12238
12239    /** @hide */
12240    public void setAnimationMatrix(Matrix matrix) {
12241        invalidateViewProperty(true, false);
12242        mRenderNode.setAnimationMatrix(matrix);
12243        invalidateViewProperty(false, true);
12244
12245        invalidateParentIfNeededAndWasQuickRejected();
12246    }
12247
12248    /**
12249     * Returns the current StateListAnimator if exists.
12250     *
12251     * @return StateListAnimator or null if it does not exists
12252     * @see    #setStateListAnimator(android.animation.StateListAnimator)
12253     */
12254    public StateListAnimator getStateListAnimator() {
12255        return mStateListAnimator;
12256    }
12257
12258    /**
12259     * Attaches the provided StateListAnimator to this View.
12260     * <p>
12261     * Any previously attached StateListAnimator will be detached.
12262     *
12263     * @param stateListAnimator The StateListAnimator to update the view
12264     * @see {@link android.animation.StateListAnimator}
12265     */
12266    public void setStateListAnimator(StateListAnimator stateListAnimator) {
12267        if (mStateListAnimator == stateListAnimator) {
12268            return;
12269        }
12270        if (mStateListAnimator != null) {
12271            mStateListAnimator.setTarget(null);
12272        }
12273        mStateListAnimator = stateListAnimator;
12274        if (stateListAnimator != null) {
12275            stateListAnimator.setTarget(this);
12276            if (isAttachedToWindow()) {
12277                stateListAnimator.setState(getDrawableState());
12278            }
12279        }
12280    }
12281
12282    /**
12283     * Returns whether the Outline should be used to clip the contents of the View.
12284     * <p>
12285     * Note that this flag will only be respected if the View's Outline returns true from
12286     * {@link Outline#canClip()}.
12287     *
12288     * @see #setOutlineProvider(ViewOutlineProvider)
12289     * @see #setClipToOutline(boolean)
12290     */
12291    public final boolean getClipToOutline() {
12292        return mRenderNode.getClipToOutline();
12293    }
12294
12295    /**
12296     * Sets whether the View's Outline should be used to clip the contents of the View.
12297     * <p>
12298     * Only a single non-rectangular clip can be applied on a View at any time.
12299     * Circular clips from a {@link ViewAnimationUtils#createCircularReveal(View, int, int, float, float)
12300     * circular reveal} animation take priority over Outline clipping, and
12301     * child Outline clipping takes priority over Outline clipping done by a
12302     * parent.
12303     * <p>
12304     * Note that this flag will only be respected if the View's Outline returns true from
12305     * {@link Outline#canClip()}.
12306     *
12307     * @see #setOutlineProvider(ViewOutlineProvider)
12308     * @see #getClipToOutline()
12309     */
12310    public void setClipToOutline(boolean clipToOutline) {
12311        damageInParent();
12312        if (getClipToOutline() != clipToOutline) {
12313            mRenderNode.setClipToOutline(clipToOutline);
12314        }
12315    }
12316
12317    // correspond to the enum values of View_outlineProvider
12318    private static final int PROVIDER_BACKGROUND = 0;
12319    private static final int PROVIDER_NONE = 1;
12320    private static final int PROVIDER_BOUNDS = 2;
12321    private static final int PROVIDER_PADDED_BOUNDS = 3;
12322    private void setOutlineProviderFromAttribute(int providerInt) {
12323        switch (providerInt) {
12324            case PROVIDER_BACKGROUND:
12325                setOutlineProvider(ViewOutlineProvider.BACKGROUND);
12326                break;
12327            case PROVIDER_NONE:
12328                setOutlineProvider(null);
12329                break;
12330            case PROVIDER_BOUNDS:
12331                setOutlineProvider(ViewOutlineProvider.BOUNDS);
12332                break;
12333            case PROVIDER_PADDED_BOUNDS:
12334                setOutlineProvider(ViewOutlineProvider.PADDED_BOUNDS);
12335                break;
12336        }
12337    }
12338
12339    /**
12340     * Sets the {@link ViewOutlineProvider} of the view, which generates the Outline that defines
12341     * the shape of the shadow it casts, and enables outline clipping.
12342     * <p>
12343     * The default ViewOutlineProvider, {@link ViewOutlineProvider#BACKGROUND}, queries the Outline
12344     * from the View's background drawable, via {@link Drawable#getOutline(Outline)}. Changing the
12345     * outline provider with this method allows this behavior to be overridden.
12346     * <p>
12347     * If the ViewOutlineProvider is null, if querying it for an outline returns false,
12348     * or if the produced Outline is {@link Outline#isEmpty()}, shadows will not be cast.
12349     * <p>
12350     * Only outlines that return true from {@link Outline#canClip()} may be used for clipping.
12351     *
12352     * @see #setClipToOutline(boolean)
12353     * @see #getClipToOutline()
12354     * @see #getOutlineProvider()
12355     */
12356    public void setOutlineProvider(ViewOutlineProvider provider) {
12357        mOutlineProvider = provider;
12358        invalidateOutline();
12359    }
12360
12361    /**
12362     * Returns the current {@link ViewOutlineProvider} of the view, which generates the Outline
12363     * that defines the shape of the shadow it casts, and enables outline clipping.
12364     *
12365     * @see #setOutlineProvider(ViewOutlineProvider)
12366     */
12367    public ViewOutlineProvider getOutlineProvider() {
12368        return mOutlineProvider;
12369    }
12370
12371    /**
12372     * Called to rebuild this View's Outline from its {@link ViewOutlineProvider outline provider}
12373     *
12374     * @see #setOutlineProvider(ViewOutlineProvider)
12375     */
12376    public void invalidateOutline() {
12377        rebuildOutline();
12378
12379        notifySubtreeAccessibilityStateChangedIfNeeded();
12380        invalidateViewProperty(false, false);
12381    }
12382
12383    /**
12384     * Internal version of {@link #invalidateOutline()} which invalidates the
12385     * outline without invalidating the view itself. This is intended to be called from
12386     * within methods in the View class itself which are the result of the view being
12387     * invalidated already. For example, when we are drawing the background of a View,
12388     * we invalidate the outline in case it changed in the meantime, but we do not
12389     * need to invalidate the view because we're already drawing the background as part
12390     * of drawing the view in response to an earlier invalidation of the view.
12391     */
12392    private void rebuildOutline() {
12393        // Unattached views ignore this signal, and outline is recomputed in onAttachedToWindow()
12394        if (mAttachInfo == null) return;
12395
12396        if (mOutlineProvider == null) {
12397            // no provider, remove outline
12398            mRenderNode.setOutline(null);
12399        } else {
12400            final Outline outline = mAttachInfo.mTmpOutline;
12401            outline.setEmpty();
12402            outline.setAlpha(1.0f);
12403
12404            mOutlineProvider.getOutline(this, outline);
12405            mRenderNode.setOutline(outline);
12406        }
12407    }
12408
12409    /**
12410     * HierarchyViewer only
12411     *
12412     * @hide
12413     */
12414    @ViewDebug.ExportedProperty(category = "drawing")
12415    public boolean hasShadow() {
12416        return mRenderNode.hasShadow();
12417    }
12418
12419
12420    /** @hide */
12421    public void setRevealClip(boolean shouldClip, float x, float y, float radius) {
12422        mRenderNode.setRevealClip(shouldClip, x, y, radius);
12423        invalidateViewProperty(false, false);
12424    }
12425
12426    /**
12427     * Hit rectangle in parent's coordinates
12428     *
12429     * @param outRect The hit rectangle of the view.
12430     */
12431    public void getHitRect(Rect outRect) {
12432        if (hasIdentityMatrix() || mAttachInfo == null) {
12433            outRect.set(mLeft, mTop, mRight, mBottom);
12434        } else {
12435            final RectF tmpRect = mAttachInfo.mTmpTransformRect;
12436            tmpRect.set(0, 0, getWidth(), getHeight());
12437            getMatrix().mapRect(tmpRect); // TODO: mRenderNode.mapRect(tmpRect)
12438            outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
12439                    (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
12440        }
12441    }
12442
12443    /**
12444     * Determines whether the given point, in local coordinates is inside the view.
12445     */
12446    /*package*/ final boolean pointInView(float localX, float localY) {
12447        return localX >= 0 && localX < (mRight - mLeft)
12448                && localY >= 0 && localY < (mBottom - mTop);
12449    }
12450
12451    /**
12452     * Utility method to determine whether the given point, in local coordinates,
12453     * is inside the view, where the area of the view is expanded by the slop factor.
12454     * This method is called while processing touch-move events to determine if the event
12455     * is still within the view.
12456     *
12457     * @hide
12458     */
12459    public boolean pointInView(float localX, float localY, float slop) {
12460        return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
12461                localY < ((mBottom - mTop) + slop);
12462    }
12463
12464    /**
12465     * When a view has focus and the user navigates away from it, the next view is searched for
12466     * starting from the rectangle filled in by this method.
12467     *
12468     * By default, the rectangle is the {@link #getDrawingRect(android.graphics.Rect)})
12469     * of the view.  However, if your view maintains some idea of internal selection,
12470     * such as a cursor, or a selected row or column, you should override this method and
12471     * fill in a more specific rectangle.
12472     *
12473     * @param r The rectangle to fill in, in this view's coordinates.
12474     */
12475    public void getFocusedRect(Rect r) {
12476        getDrawingRect(r);
12477    }
12478
12479    /**
12480     * If some part of this view is not clipped by any of its parents, then
12481     * return that area in r in global (root) coordinates. To convert r to local
12482     * coordinates (without taking possible View rotations into account), offset
12483     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
12484     * If the view is completely clipped or translated out, return false.
12485     *
12486     * @param r If true is returned, r holds the global coordinates of the
12487     *        visible portion of this view.
12488     * @param globalOffset If true is returned, globalOffset holds the dx,dy
12489     *        between this view and its root. globalOffet may be null.
12490     * @return true if r is non-empty (i.e. part of the view is visible at the
12491     *         root level.
12492     */
12493    public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
12494        int width = mRight - mLeft;
12495        int height = mBottom - mTop;
12496        if (width > 0 && height > 0) {
12497            r.set(0, 0, width, height);
12498            if (globalOffset != null) {
12499                globalOffset.set(-mScrollX, -mScrollY);
12500            }
12501            return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
12502        }
12503        return false;
12504    }
12505
12506    public final boolean getGlobalVisibleRect(Rect r) {
12507        return getGlobalVisibleRect(r, null);
12508    }
12509
12510    public final boolean getLocalVisibleRect(Rect r) {
12511        final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
12512        if (getGlobalVisibleRect(r, offset)) {
12513            r.offset(-offset.x, -offset.y); // make r local
12514            return true;
12515        }
12516        return false;
12517    }
12518
12519    /**
12520     * Offset this view's vertical location by the specified number of pixels.
12521     *
12522     * @param offset the number of pixels to offset the view by
12523     */
12524    public void offsetTopAndBottom(int offset) {
12525        if (offset != 0) {
12526            final boolean matrixIsIdentity = hasIdentityMatrix();
12527            if (matrixIsIdentity) {
12528                if (isHardwareAccelerated()) {
12529                    invalidateViewProperty(false, false);
12530                } else {
12531                    final ViewParent p = mParent;
12532                    if (p != null && mAttachInfo != null) {
12533                        final Rect r = mAttachInfo.mTmpInvalRect;
12534                        int minTop;
12535                        int maxBottom;
12536                        int yLoc;
12537                        if (offset < 0) {
12538                            minTop = mTop + offset;
12539                            maxBottom = mBottom;
12540                            yLoc = offset;
12541                        } else {
12542                            minTop = mTop;
12543                            maxBottom = mBottom + offset;
12544                            yLoc = 0;
12545                        }
12546                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
12547                        p.invalidateChild(this, r);
12548                    }
12549                }
12550            } else {
12551                invalidateViewProperty(false, false);
12552            }
12553
12554            mTop += offset;
12555            mBottom += offset;
12556            mRenderNode.offsetTopAndBottom(offset);
12557            if (isHardwareAccelerated()) {
12558                invalidateViewProperty(false, false);
12559                invalidateParentIfNeededAndWasQuickRejected();
12560            } else {
12561                if (!matrixIsIdentity) {
12562                    invalidateViewProperty(false, true);
12563                }
12564                invalidateParentIfNeeded();
12565            }
12566            notifySubtreeAccessibilityStateChangedIfNeeded();
12567        }
12568    }
12569
12570    /**
12571     * Offset this view's horizontal location by the specified amount of pixels.
12572     *
12573     * @param offset the number of pixels to offset the view by
12574     */
12575    public void offsetLeftAndRight(int offset) {
12576        if (offset != 0) {
12577            final boolean matrixIsIdentity = hasIdentityMatrix();
12578            if (matrixIsIdentity) {
12579                if (isHardwareAccelerated()) {
12580                    invalidateViewProperty(false, false);
12581                } else {
12582                    final ViewParent p = mParent;
12583                    if (p != null && mAttachInfo != null) {
12584                        final Rect r = mAttachInfo.mTmpInvalRect;
12585                        int minLeft;
12586                        int maxRight;
12587                        if (offset < 0) {
12588                            minLeft = mLeft + offset;
12589                            maxRight = mRight;
12590                        } else {
12591                            minLeft = mLeft;
12592                            maxRight = mRight + offset;
12593                        }
12594                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
12595                        p.invalidateChild(this, r);
12596                    }
12597                }
12598            } else {
12599                invalidateViewProperty(false, false);
12600            }
12601
12602            mLeft += offset;
12603            mRight += offset;
12604            mRenderNode.offsetLeftAndRight(offset);
12605            if (isHardwareAccelerated()) {
12606                invalidateViewProperty(false, false);
12607                invalidateParentIfNeededAndWasQuickRejected();
12608            } else {
12609                if (!matrixIsIdentity) {
12610                    invalidateViewProperty(false, true);
12611                }
12612                invalidateParentIfNeeded();
12613            }
12614            notifySubtreeAccessibilityStateChangedIfNeeded();
12615        }
12616    }
12617
12618    /**
12619     * Get the LayoutParams associated with this view. All views should have
12620     * layout parameters. These supply parameters to the <i>parent</i> of this
12621     * view specifying how it should be arranged. There are many subclasses of
12622     * ViewGroup.LayoutParams, and these correspond to the different subclasses
12623     * of ViewGroup that are responsible for arranging their children.
12624     *
12625     * This method may return null if this View is not attached to a parent
12626     * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
12627     * was not invoked successfully. When a View is attached to a parent
12628     * ViewGroup, this method must not return null.
12629     *
12630     * @return The LayoutParams associated with this view, or null if no
12631     *         parameters have been set yet
12632     */
12633    @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
12634    public ViewGroup.LayoutParams getLayoutParams() {
12635        return mLayoutParams;
12636    }
12637
12638    /**
12639     * Set the layout parameters associated with this view. These supply
12640     * parameters to the <i>parent</i> of this view specifying how it should be
12641     * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
12642     * correspond to the different subclasses of ViewGroup that are responsible
12643     * for arranging their children.
12644     *
12645     * @param params The layout parameters for this view, cannot be null
12646     */
12647    public void setLayoutParams(ViewGroup.LayoutParams params) {
12648        if (params == null) {
12649            throw new NullPointerException("Layout parameters cannot be null");
12650        }
12651        mLayoutParams = params;
12652        resolveLayoutParams();
12653        if (mParent instanceof ViewGroup) {
12654            ((ViewGroup) mParent).onSetLayoutParams(this, params);
12655        }
12656        requestLayout();
12657    }
12658
12659    /**
12660     * Resolve the layout parameters depending on the resolved layout direction
12661     *
12662     * @hide
12663     */
12664    public void resolveLayoutParams() {
12665        if (mLayoutParams != null) {
12666            mLayoutParams.resolveLayoutDirection(getLayoutDirection());
12667        }
12668    }
12669
12670    /**
12671     * Set the scrolled position of your view. This will cause a call to
12672     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12673     * invalidated.
12674     * @param x the x position to scroll to
12675     * @param y the y position to scroll to
12676     */
12677    public void scrollTo(int x, int y) {
12678        if (mScrollX != x || mScrollY != y) {
12679            int oldX = mScrollX;
12680            int oldY = mScrollY;
12681            mScrollX = x;
12682            mScrollY = y;
12683            invalidateParentCaches();
12684            onScrollChanged(mScrollX, mScrollY, oldX, oldY);
12685            if (!awakenScrollBars()) {
12686                postInvalidateOnAnimation();
12687            }
12688        }
12689    }
12690
12691    /**
12692     * Move the scrolled position of your view. This will cause a call to
12693     * {@link #onScrollChanged(int, int, int, int)} and the view will be
12694     * invalidated.
12695     * @param x the amount of pixels to scroll by horizontally
12696     * @param y the amount of pixels to scroll by vertically
12697     */
12698    public void scrollBy(int x, int y) {
12699        scrollTo(mScrollX + x, mScrollY + y);
12700    }
12701
12702    /**
12703     * <p>Trigger the scrollbars to draw. When invoked this method starts an
12704     * animation to fade the scrollbars out after a default delay. If a subclass
12705     * provides animated scrolling, the start delay should equal the duration
12706     * of the scrolling animation.</p>
12707     *
12708     * <p>The animation starts only if at least one of the scrollbars is
12709     * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
12710     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12711     * this method returns true, and false otherwise. If the animation is
12712     * started, this method calls {@link #invalidate()}; in that case the
12713     * caller should not call {@link #invalidate()}.</p>
12714     *
12715     * <p>This method should be invoked every time a subclass directly updates
12716     * the scroll parameters.</p>
12717     *
12718     * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
12719     * and {@link #scrollTo(int, int)}.</p>
12720     *
12721     * @return true if the animation is played, false otherwise
12722     *
12723     * @see #awakenScrollBars(int)
12724     * @see #scrollBy(int, int)
12725     * @see #scrollTo(int, int)
12726     * @see #isHorizontalScrollBarEnabled()
12727     * @see #isVerticalScrollBarEnabled()
12728     * @see #setHorizontalScrollBarEnabled(boolean)
12729     * @see #setVerticalScrollBarEnabled(boolean)
12730     */
12731    protected boolean awakenScrollBars() {
12732        return mScrollCache != null &&
12733                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
12734    }
12735
12736    /**
12737     * Trigger the scrollbars to draw.
12738     * This method differs from awakenScrollBars() only in its default duration.
12739     * initialAwakenScrollBars() will show the scroll bars for longer than
12740     * usual to give the user more of a chance to notice them.
12741     *
12742     * @return true if the animation is played, false otherwise.
12743     */
12744    private boolean initialAwakenScrollBars() {
12745        return mScrollCache != null &&
12746                awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
12747    }
12748
12749    /**
12750     * <p>
12751     * Trigger the scrollbars to draw. When invoked this method starts an
12752     * animation to fade the scrollbars out after a fixed delay. If a subclass
12753     * provides animated scrolling, the start delay should equal the duration of
12754     * the scrolling animation.
12755     * </p>
12756     *
12757     * <p>
12758     * The animation starts only if at least one of the scrollbars is enabled,
12759     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12760     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12761     * this method returns true, and false otherwise. If the animation is
12762     * started, this method calls {@link #invalidate()}; in that case the caller
12763     * should not call {@link #invalidate()}.
12764     * </p>
12765     *
12766     * <p>
12767     * This method should be invoked every time a subclass directly updates the
12768     * scroll parameters.
12769     * </p>
12770     *
12771     * @param startDelay the delay, in milliseconds, after which the animation
12772     *        should start; when the delay is 0, the animation starts
12773     *        immediately
12774     * @return true if the animation is played, false otherwise
12775     *
12776     * @see #scrollBy(int, int)
12777     * @see #scrollTo(int, int)
12778     * @see #isHorizontalScrollBarEnabled()
12779     * @see #isVerticalScrollBarEnabled()
12780     * @see #setHorizontalScrollBarEnabled(boolean)
12781     * @see #setVerticalScrollBarEnabled(boolean)
12782     */
12783    protected boolean awakenScrollBars(int startDelay) {
12784        return awakenScrollBars(startDelay, true);
12785    }
12786
12787    /**
12788     * <p>
12789     * Trigger the scrollbars to draw. When invoked this method starts an
12790     * animation to fade the scrollbars out after a fixed delay. If a subclass
12791     * provides animated scrolling, the start delay should equal the duration of
12792     * the scrolling animation.
12793     * </p>
12794     *
12795     * <p>
12796     * The animation starts only if at least one of the scrollbars is enabled,
12797     * as specified by {@link #isHorizontalScrollBarEnabled()} and
12798     * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
12799     * this method returns true, and false otherwise. If the animation is
12800     * started, this method calls {@link #invalidate()} if the invalidate parameter
12801     * is set to true; in that case the caller
12802     * should not call {@link #invalidate()}.
12803     * </p>
12804     *
12805     * <p>
12806     * This method should be invoked every time a subclass directly updates the
12807     * scroll parameters.
12808     * </p>
12809     *
12810     * @param startDelay the delay, in milliseconds, after which the animation
12811     *        should start; when the delay is 0, the animation starts
12812     *        immediately
12813     *
12814     * @param invalidate Whether this method should call invalidate
12815     *
12816     * @return true if the animation is played, false otherwise
12817     *
12818     * @see #scrollBy(int, int)
12819     * @see #scrollTo(int, int)
12820     * @see #isHorizontalScrollBarEnabled()
12821     * @see #isVerticalScrollBarEnabled()
12822     * @see #setHorizontalScrollBarEnabled(boolean)
12823     * @see #setVerticalScrollBarEnabled(boolean)
12824     */
12825    protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
12826        final ScrollabilityCache scrollCache = mScrollCache;
12827
12828        if (scrollCache == null || !scrollCache.fadeScrollBars) {
12829            return false;
12830        }
12831
12832        if (scrollCache.scrollBar == null) {
12833            scrollCache.scrollBar = new ScrollBarDrawable();
12834            scrollCache.scrollBar.setCallback(this);
12835            scrollCache.scrollBar.setState(getDrawableState());
12836        }
12837
12838        if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
12839
12840            if (invalidate) {
12841                // Invalidate to show the scrollbars
12842                postInvalidateOnAnimation();
12843            }
12844
12845            if (scrollCache.state == ScrollabilityCache.OFF) {
12846                // FIXME: this is copied from WindowManagerService.
12847                // We should get this value from the system when it
12848                // is possible to do so.
12849                final int KEY_REPEAT_FIRST_DELAY = 750;
12850                startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
12851            }
12852
12853            // Tell mScrollCache when we should start fading. This may
12854            // extend the fade start time if one was already scheduled
12855            long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
12856            scrollCache.fadeStartTime = fadeStartTime;
12857            scrollCache.state = ScrollabilityCache.ON;
12858
12859            // Schedule our fader to run, unscheduling any old ones first
12860            if (mAttachInfo != null) {
12861                mAttachInfo.mHandler.removeCallbacks(scrollCache);
12862                mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
12863            }
12864
12865            return true;
12866        }
12867
12868        return false;
12869    }
12870
12871    /**
12872     * Do not invalidate views which are not visible and which are not running an animation. They
12873     * will not get drawn and they should not set dirty flags as if they will be drawn
12874     */
12875    private boolean skipInvalidate() {
12876        return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
12877                (!(mParent instanceof ViewGroup) ||
12878                        !((ViewGroup) mParent).isViewTransitioning(this));
12879    }
12880
12881    /**
12882     * Mark the area defined by dirty as needing to be drawn. If the view is
12883     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12884     * point in the future.
12885     * <p>
12886     * This must be called from a UI thread. To call from a non-UI thread, call
12887     * {@link #postInvalidate()}.
12888     * <p>
12889     * <b>WARNING:</b> In API 19 and below, this method may be destructive to
12890     * {@code dirty}.
12891     *
12892     * @param dirty the rectangle representing the bounds of the dirty region
12893     */
12894    public void invalidate(Rect dirty) {
12895        final int scrollX = mScrollX;
12896        final int scrollY = mScrollY;
12897        invalidateInternal(dirty.left - scrollX, dirty.top - scrollY,
12898                dirty.right - scrollX, dirty.bottom - scrollY, true, false);
12899    }
12900
12901    /**
12902     * Mark the area defined by the rect (l,t,r,b) as needing to be drawn. The
12903     * coordinates of the dirty rect are relative to the view. If the view is
12904     * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some
12905     * point in the future.
12906     * <p>
12907     * This must be called from a UI thread. To call from a non-UI thread, call
12908     * {@link #postInvalidate()}.
12909     *
12910     * @param l the left position of the dirty region
12911     * @param t the top position of the dirty region
12912     * @param r the right position of the dirty region
12913     * @param b the bottom position of the dirty region
12914     */
12915    public void invalidate(int l, int t, int r, int b) {
12916        final int scrollX = mScrollX;
12917        final int scrollY = mScrollY;
12918        invalidateInternal(l - scrollX, t - scrollY, r - scrollX, b - scrollY, true, false);
12919    }
12920
12921    /**
12922     * Invalidate the whole view. If the view is visible,
12923     * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
12924     * the future.
12925     * <p>
12926     * This must be called from a UI thread. To call from a non-UI thread, call
12927     * {@link #postInvalidate()}.
12928     */
12929    public void invalidate() {
12930        invalidate(true);
12931    }
12932
12933    /**
12934     * This is where the invalidate() work actually happens. A full invalidate()
12935     * causes the drawing cache to be invalidated, but this function can be
12936     * called with invalidateCache set to false to skip that invalidation step
12937     * for cases that do not need it (for example, a component that remains at
12938     * the same dimensions with the same content).
12939     *
12940     * @param invalidateCache Whether the drawing cache for this view should be
12941     *            invalidated as well. This is usually true for a full
12942     *            invalidate, but may be set to false if the View's contents or
12943     *            dimensions have not changed.
12944     */
12945    void invalidate(boolean invalidateCache) {
12946        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);
12947    }
12948
12949    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,
12950            boolean fullInvalidate) {
12951        if (mGhostView != null) {
12952            mGhostView.invalidate(true);
12953            return;
12954        }
12955
12956        if (skipInvalidate()) {
12957            return;
12958        }
12959
12960        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)
12961                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)
12962                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED
12963                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {
12964            if (fullInvalidate) {
12965                mLastIsOpaque = isOpaque();
12966                mPrivateFlags &= ~PFLAG_DRAWN;
12967            }
12968
12969            mPrivateFlags |= PFLAG_DIRTY;
12970
12971            if (invalidateCache) {
12972                mPrivateFlags |= PFLAG_INVALIDATED;
12973                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
12974            }
12975
12976            // Propagate the damage rectangle to the parent view.
12977            final AttachInfo ai = mAttachInfo;
12978            final ViewParent p = mParent;
12979            if (p != null && ai != null && l < r && t < b) {
12980                final Rect damage = ai.mTmpInvalRect;
12981                damage.set(l, t, r, b);
12982                p.invalidateChild(this, damage);
12983            }
12984
12985            // Damage the entire projection receiver, if necessary.
12986            if (mBackground != null && mBackground.isProjected()) {
12987                final View receiver = getProjectionReceiver();
12988                if (receiver != null) {
12989                    receiver.damageInParent();
12990                }
12991            }
12992
12993            // Damage the entire IsolatedZVolume receiving this view's shadow.
12994            if (isHardwareAccelerated() && getZ() != 0) {
12995                damageShadowReceiver();
12996            }
12997        }
12998    }
12999
13000    /**
13001     * @return this view's projection receiver, or {@code null} if none exists
13002     */
13003    private View getProjectionReceiver() {
13004        ViewParent p = getParent();
13005        while (p != null && p instanceof View) {
13006            final View v = (View) p;
13007            if (v.isProjectionReceiver()) {
13008                return v;
13009            }
13010            p = p.getParent();
13011        }
13012
13013        return null;
13014    }
13015
13016    /**
13017     * @return whether the view is a projection receiver
13018     */
13019    private boolean isProjectionReceiver() {
13020        return mBackground != null;
13021    }
13022
13023    /**
13024     * Damage area of the screen that can be covered by this View's shadow.
13025     *
13026     * This method will guarantee that any changes to shadows cast by a View
13027     * are damaged on the screen for future redraw.
13028     */
13029    private void damageShadowReceiver() {
13030        final AttachInfo ai = mAttachInfo;
13031        if (ai != null) {
13032            ViewParent p = getParent();
13033            if (p != null && p instanceof ViewGroup) {
13034                final ViewGroup vg = (ViewGroup) p;
13035                vg.damageInParent();
13036            }
13037        }
13038    }
13039
13040    /**
13041     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
13042     * set any flags or handle all of the cases handled by the default invalidation methods.
13043     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
13044     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
13045     * walk up the hierarchy, transforming the dirty rect as necessary.
13046     *
13047     * The method also handles normal invalidation logic if display list properties are not
13048     * being used in this view. The invalidateParent and forceRedraw flags are used by that
13049     * backup approach, to handle these cases used in the various property-setting methods.
13050     *
13051     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
13052     * are not being used in this view
13053     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
13054     * list properties are not being used in this view
13055     */
13056    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
13057        if (!isHardwareAccelerated()
13058                || !mRenderNode.isValid()
13059                || (mPrivateFlags & PFLAG_DRAW_ANIMATION) != 0) {
13060            if (invalidateParent) {
13061                invalidateParentCaches();
13062            }
13063            if (forceRedraw) {
13064                mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
13065            }
13066            invalidate(false);
13067        } else {
13068            damageInParent();
13069        }
13070        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
13071            damageShadowReceiver();
13072        }
13073    }
13074
13075    /**
13076     * Tells the parent view to damage this view's bounds.
13077     *
13078     * @hide
13079     */
13080    protected void damageInParent() {
13081        final AttachInfo ai = mAttachInfo;
13082        final ViewParent p = mParent;
13083        if (p != null && ai != null) {
13084            final Rect r = ai.mTmpInvalRect;
13085            r.set(0, 0, mRight - mLeft, mBottom - mTop);
13086            if (mParent instanceof ViewGroup) {
13087                ((ViewGroup) mParent).damageChild(this, r);
13088            } else {
13089                mParent.invalidateChild(this, r);
13090            }
13091        }
13092    }
13093
13094    /**
13095     * Utility method to transform a given Rect by the current matrix of this view.
13096     */
13097    void transformRect(final Rect rect) {
13098        if (!getMatrix().isIdentity()) {
13099            RectF boundingRect = mAttachInfo.mTmpTransformRect;
13100            boundingRect.set(rect);
13101            getMatrix().mapRect(boundingRect);
13102            rect.set((int) Math.floor(boundingRect.left),
13103                    (int) Math.floor(boundingRect.top),
13104                    (int) Math.ceil(boundingRect.right),
13105                    (int) Math.ceil(boundingRect.bottom));
13106        }
13107    }
13108
13109    /**
13110     * Used to indicate that the parent of this view should clear its caches. This functionality
13111     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13112     * which is necessary when various parent-managed properties of the view change, such as
13113     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
13114     * clears the parent caches and does not causes an invalidate event.
13115     *
13116     * @hide
13117     */
13118    protected void invalidateParentCaches() {
13119        if (mParent instanceof View) {
13120            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
13121        }
13122    }
13123
13124    /**
13125     * Used to indicate that the parent of this view should be invalidated. This functionality
13126     * is used to force the parent to rebuild its display list (when hardware-accelerated),
13127     * which is necessary when various parent-managed properties of the view change, such as
13128     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
13129     * an invalidation event to the parent.
13130     *
13131     * @hide
13132     */
13133    protected void invalidateParentIfNeeded() {
13134        if (isHardwareAccelerated() && mParent instanceof View) {
13135            ((View) mParent).invalidate(true);
13136        }
13137    }
13138
13139    /**
13140     * @hide
13141     */
13142    protected void invalidateParentIfNeededAndWasQuickRejected() {
13143        if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) != 0) {
13144            // View was rejected last time it was drawn by its parent; this may have changed
13145            invalidateParentIfNeeded();
13146        }
13147    }
13148
13149    /**
13150     * Indicates whether this View is opaque. An opaque View guarantees that it will
13151     * draw all the pixels overlapping its bounds using a fully opaque color.
13152     *
13153     * Subclasses of View should override this method whenever possible to indicate
13154     * whether an instance is opaque. Opaque Views are treated in a special way by
13155     * the View hierarchy, possibly allowing it to perform optimizations during
13156     * invalidate/draw passes.
13157     *
13158     * @return True if this View is guaranteed to be fully opaque, false otherwise.
13159     */
13160    @ViewDebug.ExportedProperty(category = "drawing")
13161    public boolean isOpaque() {
13162        return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
13163                getFinalAlpha() >= 1.0f;
13164    }
13165
13166    /**
13167     * @hide
13168     */
13169    protected void computeOpaqueFlags() {
13170        // Opaque if:
13171        //   - Has a background
13172        //   - Background is opaque
13173        //   - Doesn't have scrollbars or scrollbars overlay
13174
13175        if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
13176            mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
13177        } else {
13178            mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
13179        }
13180
13181        final int flags = mViewFlags;
13182        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
13183                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY ||
13184                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_OUTSIDE_OVERLAY) {
13185            mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
13186        } else {
13187            mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
13188        }
13189    }
13190
13191    /**
13192     * @hide
13193     */
13194    protected boolean hasOpaqueScrollbars() {
13195        return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
13196    }
13197
13198    /**
13199     * @return A handler associated with the thread running the View. This
13200     * handler can be used to pump events in the UI events queue.
13201     */
13202    public Handler getHandler() {
13203        final AttachInfo attachInfo = mAttachInfo;
13204        if (attachInfo != null) {
13205            return attachInfo.mHandler;
13206        }
13207        return null;
13208    }
13209
13210    /**
13211     * Returns the queue of runnable for this view.
13212     *
13213     * @return the queue of runnables for this view
13214     */
13215    private HandlerActionQueue getRunQueue() {
13216        if (mRunQueue == null) {
13217            mRunQueue = new HandlerActionQueue();
13218        }
13219        return mRunQueue;
13220    }
13221
13222    /**
13223     * Gets the view root associated with the View.
13224     * @return The view root, or null if none.
13225     * @hide
13226     */
13227    public ViewRootImpl getViewRootImpl() {
13228        if (mAttachInfo != null) {
13229            return mAttachInfo.mViewRootImpl;
13230        }
13231        return null;
13232    }
13233
13234    /**
13235     * @hide
13236     */
13237    public HardwareRenderer getHardwareRenderer() {
13238        return mAttachInfo != null ? mAttachInfo.mHardwareRenderer : null;
13239    }
13240
13241    /**
13242     * <p>Causes the Runnable to be added to the message queue.
13243     * The runnable will be run on the user interface thread.</p>
13244     *
13245     * @param action The Runnable that will be executed.
13246     *
13247     * @return Returns true if the Runnable was successfully placed in to the
13248     *         message queue.  Returns false on failure, usually because the
13249     *         looper processing the message queue is exiting.
13250     *
13251     * @see #postDelayed
13252     * @see #removeCallbacks
13253     */
13254    public boolean post(Runnable action) {
13255        final AttachInfo attachInfo = mAttachInfo;
13256        if (attachInfo != null) {
13257            return attachInfo.mHandler.post(action);
13258        }
13259
13260        // Postpone the runnable until we know on which thread it needs to run.
13261        // Assume that the runnable will be successfully placed after attach.
13262        getRunQueue().post(action);
13263        return true;
13264    }
13265
13266    /**
13267     * <p>Causes the Runnable to be added to the message queue, to be run
13268     * after the specified amount of time elapses.
13269     * The runnable will be run on the user interface thread.</p>
13270     *
13271     * @param action The Runnable that will be executed.
13272     * @param delayMillis The delay (in milliseconds) until the Runnable
13273     *        will be executed.
13274     *
13275     * @return true if the Runnable was successfully placed in to the
13276     *         message queue.  Returns false on failure, usually because the
13277     *         looper processing the message queue is exiting.  Note that a
13278     *         result of true does not mean the Runnable will be processed --
13279     *         if the looper is quit before the delivery time of the message
13280     *         occurs then the message will be dropped.
13281     *
13282     * @see #post
13283     * @see #removeCallbacks
13284     */
13285    public boolean postDelayed(Runnable action, long delayMillis) {
13286        final AttachInfo attachInfo = mAttachInfo;
13287        if (attachInfo != null) {
13288            return attachInfo.mHandler.postDelayed(action, delayMillis);
13289        }
13290
13291        // Postpone the runnable until we know on which thread it needs to run.
13292        // Assume that the runnable will be successfully placed after attach.
13293        getRunQueue().postDelayed(action, delayMillis);
13294        return true;
13295    }
13296
13297    /**
13298     * <p>Causes the Runnable to execute on the next animation time step.
13299     * The runnable will be run on the user interface thread.</p>
13300     *
13301     * @param action The Runnable that will be executed.
13302     *
13303     * @see #postOnAnimationDelayed
13304     * @see #removeCallbacks
13305     */
13306    public void postOnAnimation(Runnable action) {
13307        final AttachInfo attachInfo = mAttachInfo;
13308        if (attachInfo != null) {
13309            attachInfo.mViewRootImpl.mChoreographer.postCallback(
13310                    Choreographer.CALLBACK_ANIMATION, action, null);
13311        } else {
13312            // Postpone the runnable until we know
13313            // on which thread it needs to run.
13314            getRunQueue().post(action);
13315        }
13316    }
13317
13318    /**
13319     * <p>Causes the Runnable to execute on the next animation time step,
13320     * after the specified amount of time elapses.
13321     * The runnable will be run on the user interface thread.</p>
13322     *
13323     * @param action The Runnable that will be executed.
13324     * @param delayMillis The delay (in milliseconds) until the Runnable
13325     *        will be executed.
13326     *
13327     * @see #postOnAnimation
13328     * @see #removeCallbacks
13329     */
13330    public void postOnAnimationDelayed(Runnable action, long delayMillis) {
13331        final AttachInfo attachInfo = mAttachInfo;
13332        if (attachInfo != null) {
13333            attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13334                    Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
13335        } else {
13336            // Postpone the runnable until we know
13337            // on which thread it needs to run.
13338            getRunQueue().postDelayed(action, delayMillis);
13339        }
13340    }
13341
13342    /**
13343     * <p>Removes the specified Runnable from the message queue.</p>
13344     *
13345     * @param action The Runnable to remove from the message handling queue
13346     *
13347     * @return true if this view could ask the Handler to remove the Runnable,
13348     *         false otherwise. When the returned value is true, the Runnable
13349     *         may or may not have been actually removed from the message queue
13350     *         (for instance, if the Runnable was not in the queue already.)
13351     *
13352     * @see #post
13353     * @see #postDelayed
13354     * @see #postOnAnimation
13355     * @see #postOnAnimationDelayed
13356     */
13357    public boolean removeCallbacks(Runnable action) {
13358        if (action != null) {
13359            final AttachInfo attachInfo = mAttachInfo;
13360            if (attachInfo != null) {
13361                attachInfo.mHandler.removeCallbacks(action);
13362                attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13363                        Choreographer.CALLBACK_ANIMATION, action, null);
13364            }
13365            getRunQueue().removeCallbacks(action);
13366        }
13367        return true;
13368    }
13369
13370    /**
13371     * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
13372     * Use this to invalidate the View from a non-UI thread.</p>
13373     *
13374     * <p>This method can be invoked from outside of the UI thread
13375     * only when this View is attached to a window.</p>
13376     *
13377     * @see #invalidate()
13378     * @see #postInvalidateDelayed(long)
13379     */
13380    public void postInvalidate() {
13381        postInvalidateDelayed(0);
13382    }
13383
13384    /**
13385     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13386     * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
13387     *
13388     * <p>This method can be invoked from outside of the UI thread
13389     * only when this View is attached to a window.</p>
13390     *
13391     * @param left The left coordinate of the rectangle to invalidate.
13392     * @param top The top coordinate of the rectangle to invalidate.
13393     * @param right The right coordinate of the rectangle to invalidate.
13394     * @param bottom The bottom coordinate of the rectangle to invalidate.
13395     *
13396     * @see #invalidate(int, int, int, int)
13397     * @see #invalidate(Rect)
13398     * @see #postInvalidateDelayed(long, int, int, int, int)
13399     */
13400    public void postInvalidate(int left, int top, int right, int bottom) {
13401        postInvalidateDelayed(0, left, top, right, bottom);
13402    }
13403
13404    /**
13405     * <p>Cause an invalidate to happen on a subsequent cycle through the event
13406     * loop. Waits for the specified amount of time.</p>
13407     *
13408     * <p>This method can be invoked from outside of the UI thread
13409     * only when this View is attached to a window.</p>
13410     *
13411     * @param delayMilliseconds the duration in milliseconds to delay the
13412     *         invalidation by
13413     *
13414     * @see #invalidate()
13415     * @see #postInvalidate()
13416     */
13417    public void postInvalidateDelayed(long delayMilliseconds) {
13418        // We try only with the AttachInfo because there's no point in invalidating
13419        // if we are not attached to our window
13420        final AttachInfo attachInfo = mAttachInfo;
13421        if (attachInfo != null) {
13422            attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
13423        }
13424    }
13425
13426    /**
13427     * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
13428     * through the event loop. Waits for the specified amount of time.</p>
13429     *
13430     * <p>This method can be invoked from outside of the UI thread
13431     * only when this View is attached to a window.</p>
13432     *
13433     * @param delayMilliseconds the duration in milliseconds to delay the
13434     *         invalidation by
13435     * @param left The left coordinate of the rectangle to invalidate.
13436     * @param top The top coordinate of the rectangle to invalidate.
13437     * @param right The right coordinate of the rectangle to invalidate.
13438     * @param bottom The bottom coordinate of the rectangle to invalidate.
13439     *
13440     * @see #invalidate(int, int, int, int)
13441     * @see #invalidate(Rect)
13442     * @see #postInvalidate(int, int, int, int)
13443     */
13444    public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
13445            int right, int bottom) {
13446
13447        // We try only with the AttachInfo because there's no point in invalidating
13448        // if we are not attached to our window
13449        final AttachInfo attachInfo = mAttachInfo;
13450        if (attachInfo != null) {
13451            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13452            info.target = this;
13453            info.left = left;
13454            info.top = top;
13455            info.right = right;
13456            info.bottom = bottom;
13457
13458            attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
13459        }
13460    }
13461
13462    /**
13463     * <p>Cause an invalidate to happen on the next animation time step, typically the
13464     * next display frame.</p>
13465     *
13466     * <p>This method can be invoked from outside of the UI thread
13467     * only when this View is attached to a window.</p>
13468     *
13469     * @see #invalidate()
13470     */
13471    public void postInvalidateOnAnimation() {
13472        // We try only with the AttachInfo because there's no point in invalidating
13473        // if we are not attached to our window
13474        final AttachInfo attachInfo = mAttachInfo;
13475        if (attachInfo != null) {
13476            attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
13477        }
13478    }
13479
13480    /**
13481     * <p>Cause an invalidate of the specified area to happen on the next animation
13482     * time step, typically the next display frame.</p>
13483     *
13484     * <p>This method can be invoked from outside of the UI thread
13485     * only when this View is attached to a window.</p>
13486     *
13487     * @param left The left coordinate of the rectangle to invalidate.
13488     * @param top The top coordinate of the rectangle to invalidate.
13489     * @param right The right coordinate of the rectangle to invalidate.
13490     * @param bottom The bottom coordinate of the rectangle to invalidate.
13491     *
13492     * @see #invalidate(int, int, int, int)
13493     * @see #invalidate(Rect)
13494     */
13495    public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
13496        // We try only with the AttachInfo because there's no point in invalidating
13497        // if we are not attached to our window
13498        final AttachInfo attachInfo = mAttachInfo;
13499        if (attachInfo != null) {
13500            final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.obtain();
13501            info.target = this;
13502            info.left = left;
13503            info.top = top;
13504            info.right = right;
13505            info.bottom = bottom;
13506
13507            attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
13508        }
13509    }
13510
13511    /**
13512     * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
13513     * This event is sent at most once every
13514     * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
13515     */
13516    private void postSendViewScrolledAccessibilityEventCallback() {
13517        if (mSendViewScrolledAccessibilityEvent == null) {
13518            mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
13519        }
13520        if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
13521            mSendViewScrolledAccessibilityEvent.mIsPending = true;
13522            postDelayed(mSendViewScrolledAccessibilityEvent,
13523                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
13524        }
13525    }
13526
13527    /**
13528     * Called by a parent to request that a child update its values for mScrollX
13529     * and mScrollY if necessary. This will typically be done if the child is
13530     * animating a scroll using a {@link android.widget.Scroller Scroller}
13531     * object.
13532     */
13533    public void computeScroll() {
13534    }
13535
13536    /**
13537     * <p>Indicate whether the horizontal edges are faded when the view is
13538     * scrolled horizontally.</p>
13539     *
13540     * @return true if the horizontal edges should are faded on scroll, false
13541     *         otherwise
13542     *
13543     * @see #setHorizontalFadingEdgeEnabled(boolean)
13544     *
13545     * @attr ref android.R.styleable#View_requiresFadingEdge
13546     */
13547    public boolean isHorizontalFadingEdgeEnabled() {
13548        return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
13549    }
13550
13551    /**
13552     * <p>Define whether the horizontal edges should be faded when this view
13553     * is scrolled horizontally.</p>
13554     *
13555     * @param horizontalFadingEdgeEnabled true if the horizontal edges should
13556     *                                    be faded when the view is scrolled
13557     *                                    horizontally
13558     *
13559     * @see #isHorizontalFadingEdgeEnabled()
13560     *
13561     * @attr ref android.R.styleable#View_requiresFadingEdge
13562     */
13563    public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
13564        if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
13565            if (horizontalFadingEdgeEnabled) {
13566                initScrollCache();
13567            }
13568
13569            mViewFlags ^= FADING_EDGE_HORIZONTAL;
13570        }
13571    }
13572
13573    /**
13574     * <p>Indicate whether the vertical edges are faded when the view is
13575     * scrolled horizontally.</p>
13576     *
13577     * @return true if the vertical edges should are faded on scroll, false
13578     *         otherwise
13579     *
13580     * @see #setVerticalFadingEdgeEnabled(boolean)
13581     *
13582     * @attr ref android.R.styleable#View_requiresFadingEdge
13583     */
13584    public boolean isVerticalFadingEdgeEnabled() {
13585        return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
13586    }
13587
13588    /**
13589     * <p>Define whether the vertical edges should be faded when this view
13590     * is scrolled vertically.</p>
13591     *
13592     * @param verticalFadingEdgeEnabled true if the vertical edges should
13593     *                                  be faded when the view is scrolled
13594     *                                  vertically
13595     *
13596     * @see #isVerticalFadingEdgeEnabled()
13597     *
13598     * @attr ref android.R.styleable#View_requiresFadingEdge
13599     */
13600    public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
13601        if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
13602            if (verticalFadingEdgeEnabled) {
13603                initScrollCache();
13604            }
13605
13606            mViewFlags ^= FADING_EDGE_VERTICAL;
13607        }
13608    }
13609
13610    /**
13611     * Returns the strength, or intensity, of the top faded edge. The strength is
13612     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13613     * returns 0.0 or 1.0 but no value in between.
13614     *
13615     * Subclasses should override this method to provide a smoother fade transition
13616     * when scrolling occurs.
13617     *
13618     * @return the intensity of the top fade as a float between 0.0f and 1.0f
13619     */
13620    protected float getTopFadingEdgeStrength() {
13621        return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
13622    }
13623
13624    /**
13625     * Returns the strength, or intensity, of the bottom faded edge. The strength is
13626     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13627     * returns 0.0 or 1.0 but no value in between.
13628     *
13629     * Subclasses should override this method to provide a smoother fade transition
13630     * when scrolling occurs.
13631     *
13632     * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
13633     */
13634    protected float getBottomFadingEdgeStrength() {
13635        return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
13636                computeVerticalScrollRange() ? 1.0f : 0.0f;
13637    }
13638
13639    /**
13640     * Returns the strength, or intensity, of the left faded edge. The strength is
13641     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13642     * returns 0.0 or 1.0 but no value in between.
13643     *
13644     * Subclasses should override this method to provide a smoother fade transition
13645     * when scrolling occurs.
13646     *
13647     * @return the intensity of the left fade as a float between 0.0f and 1.0f
13648     */
13649    protected float getLeftFadingEdgeStrength() {
13650        return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
13651    }
13652
13653    /**
13654     * Returns the strength, or intensity, of the right faded edge. The strength is
13655     * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
13656     * returns 0.0 or 1.0 but no value in between.
13657     *
13658     * Subclasses should override this method to provide a smoother fade transition
13659     * when scrolling occurs.
13660     *
13661     * @return the intensity of the right fade as a float between 0.0f and 1.0f
13662     */
13663    protected float getRightFadingEdgeStrength() {
13664        return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
13665                computeHorizontalScrollRange() ? 1.0f : 0.0f;
13666    }
13667
13668    /**
13669     * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
13670     * scrollbar is not drawn by default.</p>
13671     *
13672     * @return true if the horizontal scrollbar should be painted, false
13673     *         otherwise
13674     *
13675     * @see #setHorizontalScrollBarEnabled(boolean)
13676     */
13677    public boolean isHorizontalScrollBarEnabled() {
13678        return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
13679    }
13680
13681    /**
13682     * <p>Define whether the horizontal scrollbar should be drawn or not. The
13683     * scrollbar is not drawn by default.</p>
13684     *
13685     * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
13686     *                                   be painted
13687     *
13688     * @see #isHorizontalScrollBarEnabled()
13689     */
13690    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
13691        if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
13692            mViewFlags ^= SCROLLBARS_HORIZONTAL;
13693            computeOpaqueFlags();
13694            resolvePadding();
13695        }
13696    }
13697
13698    /**
13699     * <p>Indicate whether the vertical scrollbar should be drawn or not. The
13700     * scrollbar is not drawn by default.</p>
13701     *
13702     * @return true if the vertical scrollbar should be painted, false
13703     *         otherwise
13704     *
13705     * @see #setVerticalScrollBarEnabled(boolean)
13706     */
13707    public boolean isVerticalScrollBarEnabled() {
13708        return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
13709    }
13710
13711    /**
13712     * <p>Define whether the vertical scrollbar should be drawn or not. The
13713     * scrollbar is not drawn by default.</p>
13714     *
13715     * @param verticalScrollBarEnabled true if the vertical scrollbar should
13716     *                                 be painted
13717     *
13718     * @see #isVerticalScrollBarEnabled()
13719     */
13720    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
13721        if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
13722            mViewFlags ^= SCROLLBARS_VERTICAL;
13723            computeOpaqueFlags();
13724            resolvePadding();
13725        }
13726    }
13727
13728    /**
13729     * @hide
13730     */
13731    protected void recomputePadding() {
13732        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
13733    }
13734
13735    /**
13736     * Define whether scrollbars will fade when the view is not scrolling.
13737     *
13738     * @param fadeScrollbars whether to enable fading
13739     *
13740     * @attr ref android.R.styleable#View_fadeScrollbars
13741     */
13742    public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
13743        initScrollCache();
13744        final ScrollabilityCache scrollabilityCache = mScrollCache;
13745        scrollabilityCache.fadeScrollBars = fadeScrollbars;
13746        if (fadeScrollbars) {
13747            scrollabilityCache.state = ScrollabilityCache.OFF;
13748        } else {
13749            scrollabilityCache.state = ScrollabilityCache.ON;
13750        }
13751    }
13752
13753    /**
13754     *
13755     * Returns true if scrollbars will fade when this view is not scrolling
13756     *
13757     * @return true if scrollbar fading is enabled
13758     *
13759     * @attr ref android.R.styleable#View_fadeScrollbars
13760     */
13761    public boolean isScrollbarFadingEnabled() {
13762        return mScrollCache != null && mScrollCache.fadeScrollBars;
13763    }
13764
13765    /**
13766     *
13767     * Returns the delay before scrollbars fade.
13768     *
13769     * @return the delay before scrollbars fade
13770     *
13771     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13772     */
13773    public int getScrollBarDefaultDelayBeforeFade() {
13774        return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
13775                mScrollCache.scrollBarDefaultDelayBeforeFade;
13776    }
13777
13778    /**
13779     * Define the delay before scrollbars fade.
13780     *
13781     * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
13782     *
13783     * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
13784     */
13785    public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
13786        getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
13787    }
13788
13789    /**
13790     *
13791     * Returns the scrollbar fade duration.
13792     *
13793     * @return the scrollbar fade duration
13794     *
13795     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13796     */
13797    public int getScrollBarFadeDuration() {
13798        return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
13799                mScrollCache.scrollBarFadeDuration;
13800    }
13801
13802    /**
13803     * Define the scrollbar fade duration.
13804     *
13805     * @param scrollBarFadeDuration - the scrollbar fade duration
13806     *
13807     * @attr ref android.R.styleable#View_scrollbarFadeDuration
13808     */
13809    public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
13810        getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
13811    }
13812
13813    /**
13814     *
13815     * Returns the scrollbar size.
13816     *
13817     * @return the scrollbar size
13818     *
13819     * @attr ref android.R.styleable#View_scrollbarSize
13820     */
13821    public int getScrollBarSize() {
13822        return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
13823                mScrollCache.scrollBarSize;
13824    }
13825
13826    /**
13827     * Define the scrollbar size.
13828     *
13829     * @param scrollBarSize - the scrollbar size
13830     *
13831     * @attr ref android.R.styleable#View_scrollbarSize
13832     */
13833    public void setScrollBarSize(int scrollBarSize) {
13834        getScrollCache().scrollBarSize = scrollBarSize;
13835    }
13836
13837    /**
13838     * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
13839     * inset. When inset, they add to the padding of the view. And the scrollbars
13840     * can be drawn inside the padding area or on the edge of the view. For example,
13841     * if a view has a background drawable and you want to draw the scrollbars
13842     * inside the padding specified by the drawable, you can use
13843     * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
13844     * appear at the edge of the view, ignoring the padding, then you can use
13845     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
13846     * @param style the style of the scrollbars. Should be one of
13847     * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
13848     * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
13849     * @see #SCROLLBARS_INSIDE_OVERLAY
13850     * @see #SCROLLBARS_INSIDE_INSET
13851     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13852     * @see #SCROLLBARS_OUTSIDE_INSET
13853     *
13854     * @attr ref android.R.styleable#View_scrollbarStyle
13855     */
13856    public void setScrollBarStyle(@ScrollBarStyle int style) {
13857        if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
13858            mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
13859            computeOpaqueFlags();
13860            resolvePadding();
13861        }
13862    }
13863
13864    /**
13865     * <p>Returns the current scrollbar style.</p>
13866     * @return the current scrollbar style
13867     * @see #SCROLLBARS_INSIDE_OVERLAY
13868     * @see #SCROLLBARS_INSIDE_INSET
13869     * @see #SCROLLBARS_OUTSIDE_OVERLAY
13870     * @see #SCROLLBARS_OUTSIDE_INSET
13871     *
13872     * @attr ref android.R.styleable#View_scrollbarStyle
13873     */
13874    @ViewDebug.ExportedProperty(mapping = {
13875            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
13876            @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
13877            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
13878            @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
13879    })
13880    @ScrollBarStyle
13881    public int getScrollBarStyle() {
13882        return mViewFlags & SCROLLBARS_STYLE_MASK;
13883    }
13884
13885    /**
13886     * <p>Compute the horizontal range that the horizontal scrollbar
13887     * represents.</p>
13888     *
13889     * <p>The range is expressed in arbitrary units that must be the same as the
13890     * units used by {@link #computeHorizontalScrollExtent()} and
13891     * {@link #computeHorizontalScrollOffset()}.</p>
13892     *
13893     * <p>The default range is the drawing width of this view.</p>
13894     *
13895     * @return the total horizontal range represented by the horizontal
13896     *         scrollbar
13897     *
13898     * @see #computeHorizontalScrollExtent()
13899     * @see #computeHorizontalScrollOffset()
13900     * @see android.widget.ScrollBarDrawable
13901     */
13902    protected int computeHorizontalScrollRange() {
13903        return getWidth();
13904    }
13905
13906    /**
13907     * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
13908     * within the horizontal range. This value is used to compute the position
13909     * of the thumb within the scrollbar's track.</p>
13910     *
13911     * <p>The range is expressed in arbitrary units that must be the same as the
13912     * units used by {@link #computeHorizontalScrollRange()} and
13913     * {@link #computeHorizontalScrollExtent()}.</p>
13914     *
13915     * <p>The default offset is the scroll offset of this view.</p>
13916     *
13917     * @return the horizontal offset of the scrollbar's thumb
13918     *
13919     * @see #computeHorizontalScrollRange()
13920     * @see #computeHorizontalScrollExtent()
13921     * @see android.widget.ScrollBarDrawable
13922     */
13923    protected int computeHorizontalScrollOffset() {
13924        return mScrollX;
13925    }
13926
13927    /**
13928     * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
13929     * within the horizontal range. This value is used to compute the length
13930     * of the thumb within the scrollbar's track.</p>
13931     *
13932     * <p>The range is expressed in arbitrary units that must be the same as the
13933     * units used by {@link #computeHorizontalScrollRange()} and
13934     * {@link #computeHorizontalScrollOffset()}.</p>
13935     *
13936     * <p>The default extent is the drawing width of this view.</p>
13937     *
13938     * @return the horizontal extent of the scrollbar's thumb
13939     *
13940     * @see #computeHorizontalScrollRange()
13941     * @see #computeHorizontalScrollOffset()
13942     * @see android.widget.ScrollBarDrawable
13943     */
13944    protected int computeHorizontalScrollExtent() {
13945        return getWidth();
13946    }
13947
13948    /**
13949     * <p>Compute the vertical range that the vertical scrollbar represents.</p>
13950     *
13951     * <p>The range is expressed in arbitrary units that must be the same as the
13952     * units used by {@link #computeVerticalScrollExtent()} and
13953     * {@link #computeVerticalScrollOffset()}.</p>
13954     *
13955     * @return the total vertical range represented by the vertical scrollbar
13956     *
13957     * <p>The default range is the drawing height of this view.</p>
13958     *
13959     * @see #computeVerticalScrollExtent()
13960     * @see #computeVerticalScrollOffset()
13961     * @see android.widget.ScrollBarDrawable
13962     */
13963    protected int computeVerticalScrollRange() {
13964        return getHeight();
13965    }
13966
13967    /**
13968     * <p>Compute the vertical offset of the vertical scrollbar's thumb
13969     * within the horizontal range. This value is used to compute the position
13970     * of the thumb within the scrollbar's track.</p>
13971     *
13972     * <p>The range is expressed in arbitrary units that must be the same as the
13973     * units used by {@link #computeVerticalScrollRange()} and
13974     * {@link #computeVerticalScrollExtent()}.</p>
13975     *
13976     * <p>The default offset is the scroll offset of this view.</p>
13977     *
13978     * @return the vertical offset of the scrollbar's thumb
13979     *
13980     * @see #computeVerticalScrollRange()
13981     * @see #computeVerticalScrollExtent()
13982     * @see android.widget.ScrollBarDrawable
13983     */
13984    protected int computeVerticalScrollOffset() {
13985        return mScrollY;
13986    }
13987
13988    /**
13989     * <p>Compute the vertical extent of the vertical scrollbar's thumb
13990     * within the vertical range. This value is used to compute the length
13991     * of the thumb within the scrollbar's track.</p>
13992     *
13993     * <p>The range is expressed in arbitrary units that must be the same as the
13994     * units used by {@link #computeVerticalScrollRange()} and
13995     * {@link #computeVerticalScrollOffset()}.</p>
13996     *
13997     * <p>The default extent is the drawing height of this view.</p>
13998     *
13999     * @return the vertical extent of the scrollbar's thumb
14000     *
14001     * @see #computeVerticalScrollRange()
14002     * @see #computeVerticalScrollOffset()
14003     * @see android.widget.ScrollBarDrawable
14004     */
14005    protected int computeVerticalScrollExtent() {
14006        return getHeight();
14007    }
14008
14009    /**
14010     * Check if this view can be scrolled horizontally in a certain direction.
14011     *
14012     * @param direction Negative to check scrolling left, positive to check scrolling right.
14013     * @return true if this view can be scrolled in the specified direction, false otherwise.
14014     */
14015    public boolean canScrollHorizontally(int direction) {
14016        final int offset = computeHorizontalScrollOffset();
14017        final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
14018        if (range == 0) return false;
14019        if (direction < 0) {
14020            return offset > 0;
14021        } else {
14022            return offset < range - 1;
14023        }
14024    }
14025
14026    /**
14027     * Check if this view can be scrolled vertically in a certain direction.
14028     *
14029     * @param direction Negative to check scrolling up, positive to check scrolling down.
14030     * @return true if this view can be scrolled in the specified direction, false otherwise.
14031     */
14032    public boolean canScrollVertically(int direction) {
14033        final int offset = computeVerticalScrollOffset();
14034        final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
14035        if (range == 0) return false;
14036        if (direction < 0) {
14037            return offset > 0;
14038        } else {
14039            return offset < range - 1;
14040        }
14041    }
14042
14043    void getScrollIndicatorBounds(@NonNull Rect out) {
14044        out.left = mScrollX;
14045        out.right = mScrollX + mRight - mLeft;
14046        out.top = mScrollY;
14047        out.bottom = mScrollY + mBottom - mTop;
14048    }
14049
14050    private void onDrawScrollIndicators(Canvas c) {
14051        if ((mPrivateFlags3 & SCROLL_INDICATORS_PFLAG3_MASK) == 0) {
14052            // No scroll indicators enabled.
14053            return;
14054        }
14055
14056        final Drawable dr = mScrollIndicatorDrawable;
14057        if (dr == null) {
14058            // Scroll indicators aren't supported here.
14059            return;
14060        }
14061
14062        final int h = dr.getIntrinsicHeight();
14063        final int w = dr.getIntrinsicWidth();
14064        final Rect rect = mAttachInfo.mTmpInvalRect;
14065        getScrollIndicatorBounds(rect);
14066
14067        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_TOP) != 0) {
14068            final boolean canScrollUp = canScrollVertically(-1);
14069            if (canScrollUp) {
14070                dr.setBounds(rect.left, rect.top, rect.right, rect.top + h);
14071                dr.draw(c);
14072            }
14073        }
14074
14075        if ((mPrivateFlags3 & PFLAG3_SCROLL_INDICATOR_BOTTOM) != 0) {
14076            final boolean canScrollDown = canScrollVertically(1);
14077            if (canScrollDown) {
14078                dr.setBounds(rect.left, rect.bottom - h, rect.right, rect.bottom);
14079                dr.draw(c);
14080            }
14081        }
14082
14083        final int leftRtl;
14084        final int rightRtl;
14085        if (getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14086            leftRtl = PFLAG3_SCROLL_INDICATOR_END;
14087            rightRtl = PFLAG3_SCROLL_INDICATOR_START;
14088        } else {
14089            leftRtl = PFLAG3_SCROLL_INDICATOR_START;
14090            rightRtl = PFLAG3_SCROLL_INDICATOR_END;
14091        }
14092
14093        final int leftMask = PFLAG3_SCROLL_INDICATOR_LEFT | leftRtl;
14094        if ((mPrivateFlags3 & leftMask) != 0) {
14095            final boolean canScrollLeft = canScrollHorizontally(-1);
14096            if (canScrollLeft) {
14097                dr.setBounds(rect.left, rect.top, rect.left + w, rect.bottom);
14098                dr.draw(c);
14099            }
14100        }
14101
14102        final int rightMask = PFLAG3_SCROLL_INDICATOR_RIGHT | rightRtl;
14103        if ((mPrivateFlags3 & rightMask) != 0) {
14104            final boolean canScrollRight = canScrollHorizontally(1);
14105            if (canScrollRight) {
14106                dr.setBounds(rect.right - w, rect.top, rect.right, rect.bottom);
14107                dr.draw(c);
14108            }
14109        }
14110    }
14111
14112    /**
14113     * <p>Request the drawing of the horizontal and the vertical scrollbar. The
14114     * scrollbars are painted only if they have been awakened first.</p>
14115     *
14116     * @param canvas the canvas on which to draw the scrollbars
14117     *
14118     * @see #awakenScrollBars(int)
14119     */
14120    protected final void onDrawScrollBars(Canvas canvas) {
14121        // scrollbars are drawn only when the animation is running
14122        final ScrollabilityCache cache = mScrollCache;
14123        if (cache != null) {
14124
14125            int state = cache.state;
14126
14127            if (state == ScrollabilityCache.OFF) {
14128                return;
14129            }
14130
14131            boolean invalidate = false;
14132
14133            if (state == ScrollabilityCache.FADING) {
14134                // We're fading -- get our fade interpolation
14135                if (cache.interpolatorValues == null) {
14136                    cache.interpolatorValues = new float[1];
14137                }
14138
14139                float[] values = cache.interpolatorValues;
14140
14141                // Stops the animation if we're done
14142                if (cache.scrollBarInterpolator.timeToValues(values) ==
14143                        Interpolator.Result.FREEZE_END) {
14144                    cache.state = ScrollabilityCache.OFF;
14145                } else {
14146                    cache.scrollBar.mutate().setAlpha(Math.round(values[0]));
14147                }
14148
14149                // This will make the scroll bars inval themselves after
14150                // drawing. We only want this when we're fading so that
14151                // we prevent excessive redraws
14152                invalidate = true;
14153            } else {
14154                // We're just on -- but we may have been fading before so
14155                // reset alpha
14156                cache.scrollBar.mutate().setAlpha(255);
14157            }
14158
14159
14160            final int viewFlags = mViewFlags;
14161
14162            final boolean drawHorizontalScrollBar =
14163                (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
14164            final boolean drawVerticalScrollBar =
14165                (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
14166                && !isVerticalScrollBarHidden();
14167
14168            if (drawVerticalScrollBar || drawHorizontalScrollBar) {
14169                final int width = mRight - mLeft;
14170                final int height = mBottom - mTop;
14171
14172                final ScrollBarDrawable scrollBar = cache.scrollBar;
14173
14174                final int scrollX = mScrollX;
14175                final int scrollY = mScrollY;
14176                final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
14177
14178                int left;
14179                int top;
14180                int right;
14181                int bottom;
14182
14183                if (drawHorizontalScrollBar) {
14184                    int size = scrollBar.getSize(false);
14185                    if (size <= 0) {
14186                        size = cache.scrollBarSize;
14187                    }
14188
14189                    scrollBar.setParameters(computeHorizontalScrollRange(),
14190                                            computeHorizontalScrollOffset(),
14191                                            computeHorizontalScrollExtent(), false);
14192                    final int verticalScrollBarGap = drawVerticalScrollBar ?
14193                            getVerticalScrollbarWidth() : 0;
14194                    top = scrollY + height - size - (mUserPaddingBottom & inside);
14195                    left = scrollX + (mPaddingLeft & inside);
14196                    right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
14197                    bottom = top + size;
14198                    onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
14199                    if (invalidate) {
14200                        invalidate(left, top, right, bottom);
14201                    }
14202                }
14203
14204                if (drawVerticalScrollBar) {
14205                    int size = scrollBar.getSize(true);
14206                    if (size <= 0) {
14207                        size = cache.scrollBarSize;
14208                    }
14209
14210                    scrollBar.setParameters(computeVerticalScrollRange(),
14211                                            computeVerticalScrollOffset(),
14212                                            computeVerticalScrollExtent(), true);
14213                    int verticalScrollbarPosition = mVerticalScrollbarPosition;
14214                    if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
14215                        verticalScrollbarPosition = isLayoutRtl() ?
14216                                SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
14217                    }
14218                    switch (verticalScrollbarPosition) {
14219                        default:
14220                        case SCROLLBAR_POSITION_RIGHT:
14221                            left = scrollX + width - size - (mUserPaddingRight & inside);
14222                            break;
14223                        case SCROLLBAR_POSITION_LEFT:
14224                            left = scrollX + (mUserPaddingLeft & inside);
14225                            break;
14226                    }
14227                    top = scrollY + (mPaddingTop & inside);
14228                    right = left + size;
14229                    bottom = scrollY + height - (mUserPaddingBottom & inside);
14230                    onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
14231                    if (invalidate) {
14232                        invalidate(left, top, right, bottom);
14233                    }
14234                }
14235            }
14236        }
14237    }
14238
14239    /**
14240     * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
14241     * FastScroller is visible.
14242     * @return whether to temporarily hide the vertical scrollbar
14243     * @hide
14244     */
14245    protected boolean isVerticalScrollBarHidden() {
14246        return false;
14247    }
14248
14249    /**
14250     * <p>Draw the horizontal scrollbar if
14251     * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
14252     *
14253     * @param canvas the canvas on which to draw the scrollbar
14254     * @param scrollBar the scrollbar's drawable
14255     *
14256     * @see #isHorizontalScrollBarEnabled()
14257     * @see #computeHorizontalScrollRange()
14258     * @see #computeHorizontalScrollExtent()
14259     * @see #computeHorizontalScrollOffset()
14260     * @see android.widget.ScrollBarDrawable
14261     * @hide
14262     */
14263    protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
14264            int l, int t, int r, int b) {
14265        scrollBar.setBounds(l, t, r, b);
14266        scrollBar.draw(canvas);
14267    }
14268
14269    /**
14270     * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
14271     * returns true.</p>
14272     *
14273     * @param canvas the canvas on which to draw the scrollbar
14274     * @param scrollBar the scrollbar's drawable
14275     *
14276     * @see #isVerticalScrollBarEnabled()
14277     * @see #computeVerticalScrollRange()
14278     * @see #computeVerticalScrollExtent()
14279     * @see #computeVerticalScrollOffset()
14280     * @see android.widget.ScrollBarDrawable
14281     * @hide
14282     */
14283    protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
14284            int l, int t, int r, int b) {
14285        scrollBar.setBounds(l, t, r, b);
14286        scrollBar.draw(canvas);
14287    }
14288
14289    /**
14290     * Implement this to do your drawing.
14291     *
14292     * @param canvas the canvas on which the background will be drawn
14293     */
14294    protected void onDraw(Canvas canvas) {
14295    }
14296
14297    /*
14298     * Caller is responsible for calling requestLayout if necessary.
14299     * (This allows addViewInLayout to not request a new layout.)
14300     */
14301    void assignParent(ViewParent parent) {
14302        if (mParent == null) {
14303            mParent = parent;
14304        } else if (parent == null) {
14305            mParent = null;
14306        } else {
14307            throw new RuntimeException("view " + this + " being added, but"
14308                    + " it already has a parent");
14309        }
14310    }
14311
14312    /**
14313     * This is called when the view is attached to a window.  At this point it
14314     * has a Surface and will start drawing.  Note that this function is
14315     * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
14316     * however it may be called any time before the first onDraw -- including
14317     * before or after {@link #onMeasure(int, int)}.
14318     *
14319     * @see #onDetachedFromWindow()
14320     */
14321    @CallSuper
14322    protected void onAttachedToWindow() {
14323        if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
14324            mParent.requestTransparentRegion(this);
14325        }
14326
14327        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14328
14329        jumpDrawablesToCurrentState();
14330
14331        resetSubtreeAccessibilityStateChanged();
14332
14333        // rebuild, since Outline not maintained while View is detached
14334        rebuildOutline();
14335
14336        if (isFocused()) {
14337            InputMethodManager imm = InputMethodManager.peekInstance();
14338            if (imm != null) {
14339                imm.focusIn(this);
14340            }
14341        }
14342    }
14343
14344    /**
14345     * Resolve all RTL related properties.
14346     *
14347     * @return true if resolution of RTL properties has been done
14348     *
14349     * @hide
14350     */
14351    public boolean resolveRtlPropertiesIfNeeded() {
14352        if (!needRtlPropertiesResolution()) return false;
14353
14354        // Order is important here: LayoutDirection MUST be resolved first
14355        if (!isLayoutDirectionResolved()) {
14356            resolveLayoutDirection();
14357            resolveLayoutParams();
14358        }
14359        // ... then we can resolve the others properties depending on the resolved LayoutDirection.
14360        if (!isTextDirectionResolved()) {
14361            resolveTextDirection();
14362        }
14363        if (!isTextAlignmentResolved()) {
14364            resolveTextAlignment();
14365        }
14366        // Should resolve Drawables before Padding because we need the layout direction of the
14367        // Drawable to correctly resolve Padding.
14368        if (!areDrawablesResolved()) {
14369            resolveDrawables();
14370        }
14371        if (!isPaddingResolved()) {
14372            resolvePadding();
14373        }
14374        onRtlPropertiesChanged(getLayoutDirection());
14375        return true;
14376    }
14377
14378    /**
14379     * Reset resolution of all RTL related properties.
14380     *
14381     * @hide
14382     */
14383    public void resetRtlProperties() {
14384        resetResolvedLayoutDirection();
14385        resetResolvedTextDirection();
14386        resetResolvedTextAlignment();
14387        resetResolvedPadding();
14388        resetResolvedDrawables();
14389    }
14390
14391    /**
14392     * @see #onScreenStateChanged(int)
14393     */
14394    void dispatchScreenStateChanged(int screenState) {
14395        onScreenStateChanged(screenState);
14396    }
14397
14398    /**
14399     * This method is called whenever the state of the screen this view is
14400     * attached to changes. A state change will usually occurs when the screen
14401     * turns on or off (whether it happens automatically or the user does it
14402     * manually.)
14403     *
14404     * @param screenState The new state of the screen. Can be either
14405     *                    {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
14406     */
14407    public void onScreenStateChanged(int screenState) {
14408    }
14409
14410    /**
14411     * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
14412     */
14413    private boolean hasRtlSupport() {
14414        return mContext.getApplicationInfo().hasRtlSupport();
14415    }
14416
14417    /**
14418     * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or
14419     * RTL not supported)
14420     */
14421    private boolean isRtlCompatibilityMode() {
14422        final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
14423        return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport();
14424    }
14425
14426    /**
14427     * @return true if RTL properties need resolution.
14428     *
14429     */
14430    private boolean needRtlPropertiesResolution() {
14431        return (mPrivateFlags2 & ALL_RTL_PROPERTIES_RESOLVED) != ALL_RTL_PROPERTIES_RESOLVED;
14432    }
14433
14434    /**
14435     * Called when any RTL property (layout direction or text direction or text alignment) has
14436     * been changed.
14437     *
14438     * Subclasses need to override this method to take care of cached information that depends on the
14439     * resolved layout direction, or to inform child views that inherit their layout direction.
14440     *
14441     * The default implementation does nothing.
14442     *
14443     * @param layoutDirection the direction of the layout
14444     *
14445     * @see #LAYOUT_DIRECTION_LTR
14446     * @see #LAYOUT_DIRECTION_RTL
14447     */
14448    public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
14449    }
14450
14451    /**
14452     * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
14453     * that the parent directionality can and will be resolved before its children.
14454     *
14455     * @return true if resolution has been done, false otherwise.
14456     *
14457     * @hide
14458     */
14459    public boolean resolveLayoutDirection() {
14460        // Clear any previous layout direction resolution
14461        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14462
14463        if (hasRtlSupport()) {
14464            // Set resolved depending on layout direction
14465            switch ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >>
14466                    PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) {
14467                case LAYOUT_DIRECTION_INHERIT:
14468                    // We cannot resolve yet. LTR is by default and let the resolution happen again
14469                    // later to get the correct resolved value
14470                    if (!canResolveLayoutDirection()) return false;
14471
14472                    // Parent has not yet resolved, LTR is still the default
14473                    try {
14474                        if (!mParent.isLayoutDirectionResolved()) return false;
14475
14476                        if (mParent.getLayoutDirection() == LAYOUT_DIRECTION_RTL) {
14477                            mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14478                        }
14479                    } catch (AbstractMethodError e) {
14480                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14481                                " does not fully implement ViewParent", e);
14482                    }
14483                    break;
14484                case LAYOUT_DIRECTION_RTL:
14485                    mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14486                    break;
14487                case LAYOUT_DIRECTION_LOCALE:
14488                    if((LAYOUT_DIRECTION_RTL ==
14489                            TextUtils.getLayoutDirectionFromLocale(Locale.getDefault()))) {
14490                        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
14491                    }
14492                    break;
14493                default:
14494                    // Nothing to do, LTR by default
14495            }
14496        }
14497
14498        // Set to resolved
14499        mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14500        return true;
14501    }
14502
14503    /**
14504     * Check if layout direction resolution can be done.
14505     *
14506     * @return true if layout direction resolution can be done otherwise return false.
14507     */
14508    public boolean canResolveLayoutDirection() {
14509        switch (getRawLayoutDirection()) {
14510            case LAYOUT_DIRECTION_INHERIT:
14511                if (mParent != null) {
14512                    try {
14513                        return mParent.canResolveLayoutDirection();
14514                    } catch (AbstractMethodError e) {
14515                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
14516                                " does not fully implement ViewParent", e);
14517                    }
14518                }
14519                return false;
14520
14521            default:
14522                return true;
14523        }
14524    }
14525
14526    /**
14527     * Reset the resolved layout direction. Layout direction will be resolved during a call to
14528     * {@link #onMeasure(int, int)}.
14529     *
14530     * @hide
14531     */
14532    public void resetResolvedLayoutDirection() {
14533        // Reset the current resolved bits
14534        mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
14535    }
14536
14537    /**
14538     * @return true if the layout direction is inherited.
14539     *
14540     * @hide
14541     */
14542    public boolean isLayoutDirectionInherited() {
14543        return (getRawLayoutDirection() == LAYOUT_DIRECTION_INHERIT);
14544    }
14545
14546    /**
14547     * @return true if layout direction has been resolved.
14548     */
14549    public boolean isLayoutDirectionResolved() {
14550        return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) == PFLAG2_LAYOUT_DIRECTION_RESOLVED;
14551    }
14552
14553    /**
14554     * Return if padding has been resolved
14555     *
14556     * @hide
14557     */
14558    boolean isPaddingResolved() {
14559        return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) == PFLAG2_PADDING_RESOLVED;
14560    }
14561
14562    /**
14563     * Resolves padding depending on layout direction, if applicable, and
14564     * recomputes internal padding values to adjust for scroll bars.
14565     *
14566     * @hide
14567     */
14568    public void resolvePadding() {
14569        final int resolvedLayoutDirection = getLayoutDirection();
14570
14571        if (!isRtlCompatibilityMode()) {
14572            // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
14573            // If start / end padding are defined, they will be resolved (hence overriding) to
14574            // left / right or right / left depending on the resolved layout direction.
14575            // If start / end padding are not defined, use the left / right ones.
14576            if (mBackground != null && (!mLeftPaddingDefined || !mRightPaddingDefined)) {
14577                Rect padding = sThreadLocal.get();
14578                if (padding == null) {
14579                    padding = new Rect();
14580                    sThreadLocal.set(padding);
14581                }
14582                mBackground.getPadding(padding);
14583                if (!mLeftPaddingDefined) {
14584                    mUserPaddingLeftInitial = padding.left;
14585                }
14586                if (!mRightPaddingDefined) {
14587                    mUserPaddingRightInitial = padding.right;
14588                }
14589            }
14590            switch (resolvedLayoutDirection) {
14591                case LAYOUT_DIRECTION_RTL:
14592                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14593                        mUserPaddingRight = mUserPaddingStart;
14594                    } else {
14595                        mUserPaddingRight = mUserPaddingRightInitial;
14596                    }
14597                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14598                        mUserPaddingLeft = mUserPaddingEnd;
14599                    } else {
14600                        mUserPaddingLeft = mUserPaddingLeftInitial;
14601                    }
14602                    break;
14603                case LAYOUT_DIRECTION_LTR:
14604                default:
14605                    if (mUserPaddingStart != UNDEFINED_PADDING) {
14606                        mUserPaddingLeft = mUserPaddingStart;
14607                    } else {
14608                        mUserPaddingLeft = mUserPaddingLeftInitial;
14609                    }
14610                    if (mUserPaddingEnd != UNDEFINED_PADDING) {
14611                        mUserPaddingRight = mUserPaddingEnd;
14612                    } else {
14613                        mUserPaddingRight = mUserPaddingRightInitial;
14614                    }
14615            }
14616
14617            mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
14618        }
14619
14620        internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
14621        onRtlPropertiesChanged(resolvedLayoutDirection);
14622
14623        mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
14624    }
14625
14626    /**
14627     * Reset the resolved layout direction.
14628     *
14629     * @hide
14630     */
14631    public void resetResolvedPadding() {
14632        resetResolvedPaddingInternal();
14633    }
14634
14635    /**
14636     * Used when we only want to reset *this* view's padding and not trigger overrides
14637     * in ViewGroup that reset children too.
14638     */
14639    void resetResolvedPaddingInternal() {
14640        mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
14641    }
14642
14643    /**
14644     * This is called when the view is detached from a window.  At this point it
14645     * no longer has a surface for drawing.
14646     *
14647     * @see #onAttachedToWindow()
14648     */
14649    @CallSuper
14650    protected void onDetachedFromWindow() {
14651    }
14652
14653    /**
14654     * This is a framework-internal mirror of onDetachedFromWindow() that's called
14655     * after onDetachedFromWindow().
14656     *
14657     * If you override this you *MUST* call super.onDetachedFromWindowInternal()!
14658     * The super method should be called at the end of the overridden method to ensure
14659     * subclasses are destroyed first
14660     *
14661     * @hide
14662     */
14663    @CallSuper
14664    protected void onDetachedFromWindowInternal() {
14665        mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
14666        mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
14667
14668        removeUnsetPressCallback();
14669        removeLongPressCallback();
14670        removePerformClickCallback();
14671        removeSendViewScrolledAccessibilityEventCallback();
14672        stopNestedScroll();
14673
14674        // Anything that started animating right before detach should already
14675        // be in its final state when re-attached.
14676        jumpDrawablesToCurrentState();
14677
14678        destroyDrawingCache();
14679
14680        cleanupDraw();
14681        mCurrentAnimation = null;
14682    }
14683
14684    private void cleanupDraw() {
14685        resetDisplayList();
14686        if (mAttachInfo != null) {
14687            mAttachInfo.mViewRootImpl.cancelInvalidate(this);
14688        }
14689    }
14690
14691    void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
14692    }
14693
14694    /**
14695     * @return The number of times this view has been attached to a window
14696     */
14697    protected int getWindowAttachCount() {
14698        return mWindowAttachCount;
14699    }
14700
14701    /**
14702     * Retrieve a unique token identifying the window this view is attached to.
14703     * @return Return the window's token for use in
14704     * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
14705     */
14706    public IBinder getWindowToken() {
14707        return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
14708    }
14709
14710    /**
14711     * Retrieve the {@link WindowId} for the window this view is
14712     * currently attached to.
14713     */
14714    public WindowId getWindowId() {
14715        if (mAttachInfo == null) {
14716            return null;
14717        }
14718        if (mAttachInfo.mWindowId == null) {
14719            try {
14720                mAttachInfo.mIWindowId = mAttachInfo.mSession.getWindowId(
14721                        mAttachInfo.mWindowToken);
14722                mAttachInfo.mWindowId = new WindowId(
14723                        mAttachInfo.mIWindowId);
14724            } catch (RemoteException e) {
14725            }
14726        }
14727        return mAttachInfo.mWindowId;
14728    }
14729
14730    /**
14731     * Retrieve a unique token identifying the top-level "real" window of
14732     * the window that this view is attached to.  That is, this is like
14733     * {@link #getWindowToken}, except if the window this view in is a panel
14734     * window (attached to another containing window), then the token of
14735     * the containing window is returned instead.
14736     *
14737     * @return Returns the associated window token, either
14738     * {@link #getWindowToken()} or the containing window's token.
14739     */
14740    public IBinder getApplicationWindowToken() {
14741        AttachInfo ai = mAttachInfo;
14742        if (ai != null) {
14743            IBinder appWindowToken = ai.mPanelParentWindowToken;
14744            if (appWindowToken == null) {
14745                appWindowToken = ai.mWindowToken;
14746            }
14747            return appWindowToken;
14748        }
14749        return null;
14750    }
14751
14752    /**
14753     * Gets the logical display to which the view's window has been attached.
14754     *
14755     * @return The logical display, or null if the view is not currently attached to a window.
14756     */
14757    public Display getDisplay() {
14758        return mAttachInfo != null ? mAttachInfo.mDisplay : null;
14759    }
14760
14761    /**
14762     * Retrieve private session object this view hierarchy is using to
14763     * communicate with the window manager.
14764     * @return the session object to communicate with the window manager
14765     */
14766    /*package*/ IWindowSession getWindowSession() {
14767        return mAttachInfo != null ? mAttachInfo.mSession : null;
14768    }
14769
14770    /**
14771     * Return the visibility value of the least visible component passed.
14772     */
14773    int combineVisibility(int vis1, int vis2) {
14774        // This works because VISIBLE < INVISIBLE < GONE.
14775        return Math.max(vis1, vis2);
14776    }
14777
14778    /**
14779     * @param info the {@link android.view.View.AttachInfo} to associated with
14780     *        this view
14781     */
14782    void dispatchAttachedToWindow(AttachInfo info, int visibility) {
14783        mAttachInfo = info;
14784        if (mOverlay != null) {
14785            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
14786        }
14787        mWindowAttachCount++;
14788        // We will need to evaluate the drawable state at least once.
14789        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
14790        if (mFloatingTreeObserver != null) {
14791            info.mTreeObserver.merge(mFloatingTreeObserver);
14792            mFloatingTreeObserver = null;
14793        }
14794        if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
14795            mAttachInfo.mScrollContainers.add(this);
14796            mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
14797        }
14798        // Transfer all pending runnables.
14799        if (mRunQueue != null) {
14800            mRunQueue.executeActions(info.mHandler);
14801            mRunQueue = null;
14802        }
14803        performCollectViewAttributes(mAttachInfo, visibility);
14804        onAttachedToWindow();
14805
14806        ListenerInfo li = mListenerInfo;
14807        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14808                li != null ? li.mOnAttachStateChangeListeners : null;
14809        if (listeners != null && listeners.size() > 0) {
14810            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14811            // perform the dispatching. The iterator is a safe guard against listeners that
14812            // could mutate the list by calling the various add/remove methods. This prevents
14813            // the array from being modified while we iterate it.
14814            for (OnAttachStateChangeListener listener : listeners) {
14815                listener.onViewAttachedToWindow(this);
14816            }
14817        }
14818
14819        int vis = info.mWindowVisibility;
14820        if (vis != GONE) {
14821            onWindowVisibilityChanged(vis);
14822        }
14823
14824        // Send onVisibilityChanged directly instead of dispatchVisibilityChanged.
14825        // As all views in the subtree will already receive dispatchAttachedToWindow
14826        // traversing the subtree again here is not desired.
14827        onVisibilityChanged(this, visibility);
14828
14829        if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
14830            // If nobody has evaluated the drawable state yet, then do it now.
14831            refreshDrawableState();
14832        }
14833        needGlobalAttributesUpdate(false);
14834    }
14835
14836    void dispatchDetachedFromWindow() {
14837        AttachInfo info = mAttachInfo;
14838        if (info != null) {
14839            int vis = info.mWindowVisibility;
14840            if (vis != GONE) {
14841                onWindowVisibilityChanged(GONE);
14842            }
14843        }
14844
14845        onDetachedFromWindow();
14846        onDetachedFromWindowInternal();
14847
14848        InputMethodManager imm = InputMethodManager.peekInstance();
14849        if (imm != null) {
14850            imm.onViewDetachedFromWindow(this);
14851        }
14852
14853        ListenerInfo li = mListenerInfo;
14854        final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
14855                li != null ? li.mOnAttachStateChangeListeners : null;
14856        if (listeners != null && listeners.size() > 0) {
14857            // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
14858            // perform the dispatching. The iterator is a safe guard against listeners that
14859            // could mutate the list by calling the various add/remove methods. This prevents
14860            // the array from being modified while we iterate it.
14861            for (OnAttachStateChangeListener listener : listeners) {
14862                listener.onViewDetachedFromWindow(this);
14863            }
14864        }
14865
14866        if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
14867            mAttachInfo.mScrollContainers.remove(this);
14868            mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
14869        }
14870
14871        mAttachInfo = null;
14872        if (mOverlay != null) {
14873            mOverlay.getOverlayView().dispatchDetachedFromWindow();
14874        }
14875    }
14876
14877    /**
14878     * Cancel any deferred high-level input events that were previously posted to the event queue.
14879     *
14880     * <p>Many views post high-level events such as click handlers to the event queue
14881     * to run deferred in order to preserve a desired user experience - clearing visible
14882     * pressed states before executing, etc. This method will abort any events of this nature
14883     * that are currently in flight.</p>
14884     *
14885     * <p>Custom views that generate their own high-level deferred input events should override
14886     * {@link #onCancelPendingInputEvents()} and remove those pending events from the queue.</p>
14887     *
14888     * <p>This will also cancel pending input events for any child views.</p>
14889     *
14890     * <p>Note that this may not be sufficient as a debouncing strategy for clicks in all cases.
14891     * This will not impact newer events posted after this call that may occur as a result of
14892     * lower-level input events still waiting in the queue. If you are trying to prevent
14893     * double-submitted  events for the duration of some sort of asynchronous transaction
14894     * you should also take other steps to protect against unexpected double inputs e.g. calling
14895     * {@link #setEnabled(boolean) setEnabled(false)} and re-enabling the view when
14896     * the transaction completes, tracking already submitted transaction IDs, etc.</p>
14897     */
14898    public final void cancelPendingInputEvents() {
14899        dispatchCancelPendingInputEvents();
14900    }
14901
14902    /**
14903     * Called by {@link #cancelPendingInputEvents()} to cancel input events in flight.
14904     * Overridden by ViewGroup to dispatch. Package scoped to prevent app-side meddling.
14905     */
14906    void dispatchCancelPendingInputEvents() {
14907        mPrivateFlags3 &= ~PFLAG3_CALLED_SUPER;
14908        onCancelPendingInputEvents();
14909        if ((mPrivateFlags3 & PFLAG3_CALLED_SUPER) != PFLAG3_CALLED_SUPER) {
14910            throw new SuperNotCalledException("View " + getClass().getSimpleName() +
14911                    " did not call through to super.onCancelPendingInputEvents()");
14912        }
14913    }
14914
14915    /**
14916     * Called as the result of a call to {@link #cancelPendingInputEvents()} on this view or
14917     * a parent view.
14918     *
14919     * <p>This method is responsible for removing any pending high-level input events that were
14920     * posted to the event queue to run later. Custom view classes that post their own deferred
14921     * high-level events via {@link #post(Runnable)}, {@link #postDelayed(Runnable, long)} or
14922     * {@link android.os.Handler} should override this method, call
14923     * <code>super.onCancelPendingInputEvents()</code> and remove those callbacks as appropriate.
14924     * </p>
14925     */
14926    public void onCancelPendingInputEvents() {
14927        removePerformClickCallback();
14928        cancelLongPress();
14929        mPrivateFlags3 |= PFLAG3_CALLED_SUPER;
14930    }
14931
14932    /**
14933     * Store this view hierarchy's frozen state into the given container.
14934     *
14935     * @param container The SparseArray in which to save the view's state.
14936     *
14937     * @see #restoreHierarchyState(android.util.SparseArray)
14938     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14939     * @see #onSaveInstanceState()
14940     */
14941    public void saveHierarchyState(SparseArray<Parcelable> container) {
14942        dispatchSaveInstanceState(container);
14943    }
14944
14945    /**
14946     * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
14947     * this view and its children. May be overridden to modify how freezing happens to a
14948     * view's children; for example, some views may want to not store state for their children.
14949     *
14950     * @param container The SparseArray in which to save the view's state.
14951     *
14952     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
14953     * @see #saveHierarchyState(android.util.SparseArray)
14954     * @see #onSaveInstanceState()
14955     */
14956    protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
14957        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
14958            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
14959            Parcelable state = onSaveInstanceState();
14960            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
14961                throw new IllegalStateException(
14962                        "Derived class did not call super.onSaveInstanceState()");
14963            }
14964            if (state != null) {
14965                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
14966                // + ": " + state);
14967                container.put(mID, state);
14968            }
14969        }
14970    }
14971
14972    /**
14973     * Hook allowing a view to generate a representation of its internal state
14974     * that can later be used to create a new instance with that same state.
14975     * This state should only contain information that is not persistent or can
14976     * not be reconstructed later. For example, you will never store your
14977     * current position on screen because that will be computed again when a
14978     * new instance of the view is placed in its view hierarchy.
14979     * <p>
14980     * Some examples of things you may store here: the current cursor position
14981     * in a text view (but usually not the text itself since that is stored in a
14982     * content provider or other persistent storage), the currently selected
14983     * item in a list view.
14984     *
14985     * @return Returns a Parcelable object containing the view's current dynamic
14986     *         state, or null if there is nothing interesting to save. The
14987     *         default implementation returns null.
14988     * @see #onRestoreInstanceState(android.os.Parcelable)
14989     * @see #saveHierarchyState(android.util.SparseArray)
14990     * @see #dispatchSaveInstanceState(android.util.SparseArray)
14991     * @see #setSaveEnabled(boolean)
14992     */
14993    @CallSuper
14994    protected Parcelable onSaveInstanceState() {
14995        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
14996        if (mStartActivityRequestWho != null) {
14997            BaseSavedState state = new BaseSavedState(AbsSavedState.EMPTY_STATE);
14998            state.mStartActivityRequestWhoSaved = mStartActivityRequestWho;
14999            return state;
15000        }
15001        return BaseSavedState.EMPTY_STATE;
15002    }
15003
15004    /**
15005     * Restore this view hierarchy's frozen state from the given container.
15006     *
15007     * @param container The SparseArray which holds previously frozen states.
15008     *
15009     * @see #saveHierarchyState(android.util.SparseArray)
15010     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15011     * @see #onRestoreInstanceState(android.os.Parcelable)
15012     */
15013    public void restoreHierarchyState(SparseArray<Parcelable> container) {
15014        dispatchRestoreInstanceState(container);
15015    }
15016
15017    /**
15018     * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
15019     * state for this view and its children. May be overridden to modify how restoring
15020     * happens to a view's children; for example, some views may want to not store state
15021     * for their children.
15022     *
15023     * @param container The SparseArray which holds previously saved state.
15024     *
15025     * @see #dispatchSaveInstanceState(android.util.SparseArray)
15026     * @see #restoreHierarchyState(android.util.SparseArray)
15027     * @see #onRestoreInstanceState(android.os.Parcelable)
15028     */
15029    protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
15030        if (mID != NO_ID) {
15031            Parcelable state = container.get(mID);
15032            if (state != null) {
15033                // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
15034                // + ": " + state);
15035                mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
15036                onRestoreInstanceState(state);
15037                if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
15038                    throw new IllegalStateException(
15039                            "Derived class did not call super.onRestoreInstanceState()");
15040                }
15041            }
15042        }
15043    }
15044
15045    /**
15046     * Hook allowing a view to re-apply a representation of its internal state that had previously
15047     * been generated by {@link #onSaveInstanceState}. This function will never be called with a
15048     * null state.
15049     *
15050     * @param state The frozen state that had previously been returned by
15051     *        {@link #onSaveInstanceState}.
15052     *
15053     * @see #onSaveInstanceState()
15054     * @see #restoreHierarchyState(android.util.SparseArray)
15055     * @see #dispatchRestoreInstanceState(android.util.SparseArray)
15056     */
15057    @CallSuper
15058    protected void onRestoreInstanceState(Parcelable state) {
15059        mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
15060        if (state != null && !(state instanceof AbsSavedState)) {
15061            throw new IllegalArgumentException("Wrong state class, expecting View State but "
15062                    + "received " + state.getClass().toString() + " instead. This usually happens "
15063                    + "when two views of different type have the same id in the same hierarchy. "
15064                    + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
15065                    + "other views do not use the same id.");
15066        }
15067        if (state != null && state instanceof BaseSavedState) {
15068            mStartActivityRequestWho = ((BaseSavedState) state).mStartActivityRequestWhoSaved;
15069        }
15070    }
15071
15072    /**
15073     * <p>Return the time at which the drawing of the view hierarchy started.</p>
15074     *
15075     * @return the drawing start time in milliseconds
15076     */
15077    public long getDrawingTime() {
15078        return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
15079    }
15080
15081    /**
15082     * <p>Enables or disables the duplication of the parent's state into this view. When
15083     * duplication is enabled, this view gets its drawable state from its parent rather
15084     * than from its own internal properties.</p>
15085     *
15086     * <p>Note: in the current implementation, setting this property to true after the
15087     * view was added to a ViewGroup might have no effect at all. This property should
15088     * always be used from XML or set to true before adding this view to a ViewGroup.</p>
15089     *
15090     * <p>Note: if this view's parent addStateFromChildren property is enabled and this
15091     * property is enabled, an exception will be thrown.</p>
15092     *
15093     * <p>Note: if the child view uses and updates additional states which are unknown to the
15094     * parent, these states should not be affected by this method.</p>
15095     *
15096     * @param enabled True to enable duplication of the parent's drawable state, false
15097     *                to disable it.
15098     *
15099     * @see #getDrawableState()
15100     * @see #isDuplicateParentStateEnabled()
15101     */
15102    public void setDuplicateParentStateEnabled(boolean enabled) {
15103        setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
15104    }
15105
15106    /**
15107     * <p>Indicates whether this duplicates its drawable state from its parent.</p>
15108     *
15109     * @return True if this view's drawable state is duplicated from the parent,
15110     *         false otherwise
15111     *
15112     * @see #getDrawableState()
15113     * @see #setDuplicateParentStateEnabled(boolean)
15114     */
15115    public boolean isDuplicateParentStateEnabled() {
15116        return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
15117    }
15118
15119    /**
15120     * <p>Specifies the type of layer backing this view. The layer can be
15121     * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15122     * {@link #LAYER_TYPE_HARDWARE}.</p>
15123     *
15124     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15125     * instance that controls how the layer is composed on screen. The following
15126     * properties of the paint are taken into account when composing the layer:</p>
15127     * <ul>
15128     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15129     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15130     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15131     * </ul>
15132     *
15133     * <p>If this view has an alpha value set to < 1.0 by calling
15134     * {@link #setAlpha(float)}, the alpha value of the layer's paint is superseded
15135     * by this view's alpha value.</p>
15136     *
15137     * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE},
15138     * {@link #LAYER_TYPE_SOFTWARE} and {@link #LAYER_TYPE_HARDWARE}
15139     * for more information on when and how to use layers.</p>
15140     *
15141     * @param layerType The type of layer to use with this view, must be one of
15142     *        {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15143     *        {@link #LAYER_TYPE_HARDWARE}
15144     * @param paint The paint used to compose the layer. This argument is optional
15145     *        and can be null. It is ignored when the layer type is
15146     *        {@link #LAYER_TYPE_NONE}
15147     *
15148     * @see #getLayerType()
15149     * @see #LAYER_TYPE_NONE
15150     * @see #LAYER_TYPE_SOFTWARE
15151     * @see #LAYER_TYPE_HARDWARE
15152     * @see #setAlpha(float)
15153     *
15154     * @attr ref android.R.styleable#View_layerType
15155     */
15156    public void setLayerType(int layerType, Paint paint) {
15157        if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
15158            throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
15159                    + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
15160        }
15161
15162        boolean typeChanged = mRenderNode.setLayerType(layerType);
15163
15164        if (!typeChanged) {
15165            setLayerPaint(paint);
15166            return;
15167        }
15168
15169        // Destroy any previous software drawing cache if needed
15170        if (mLayerType == LAYER_TYPE_SOFTWARE) {
15171            destroyDrawingCache();
15172        }
15173
15174        mLayerType = layerType;
15175        final boolean layerDisabled = (mLayerType == LAYER_TYPE_NONE);
15176        mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
15177        mRenderNode.setLayerPaint(mLayerPaint);
15178
15179        // draw() behaves differently if we are on a layer, so we need to
15180        // invalidate() here
15181        invalidateParentCaches();
15182        invalidate(true);
15183    }
15184
15185    /**
15186     * Updates the {@link Paint} object used with the current layer (used only if the current
15187     * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
15188     * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
15189     * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
15190     * ensure that the view gets redrawn immediately.
15191     *
15192     * <p>A layer is associated with an optional {@link android.graphics.Paint}
15193     * instance that controls how the layer is composed on screen. The following
15194     * properties of the paint are taken into account when composing the layer:</p>
15195     * <ul>
15196     * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
15197     * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
15198     * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
15199     * </ul>
15200     *
15201     * <p>If this view has an alpha value set to < 1.0 by calling {@link #setAlpha(float)}, the
15202     * alpha value of the layer's paint is superseded by this view's alpha value.</p>
15203     *
15204     * @param paint The paint used to compose the layer. This argument is optional
15205     *        and can be null. It is ignored when the layer type is
15206     *        {@link #LAYER_TYPE_NONE}
15207     *
15208     * @see #setLayerType(int, android.graphics.Paint)
15209     */
15210    public void setLayerPaint(Paint paint) {
15211        int layerType = getLayerType();
15212        if (layerType != LAYER_TYPE_NONE) {
15213            mLayerPaint = paint == null ? new Paint() : paint;
15214            if (layerType == LAYER_TYPE_HARDWARE) {
15215                if (mRenderNode.setLayerPaint(mLayerPaint)) {
15216                    invalidateViewProperty(false, false);
15217                }
15218            } else {
15219                invalidate();
15220            }
15221        }
15222    }
15223
15224    /**
15225     * Indicates what type of layer is currently associated with this view. By default
15226     * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
15227     * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
15228     * for more information on the different types of layers.
15229     *
15230     * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
15231     *         {@link #LAYER_TYPE_HARDWARE}
15232     *
15233     * @see #setLayerType(int, android.graphics.Paint)
15234     * @see #buildLayer()
15235     * @see #LAYER_TYPE_NONE
15236     * @see #LAYER_TYPE_SOFTWARE
15237     * @see #LAYER_TYPE_HARDWARE
15238     */
15239    public int getLayerType() {
15240        return mLayerType;
15241    }
15242
15243    /**
15244     * Forces this view's layer to be created and this view to be rendered
15245     * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
15246     * invoking this method will have no effect.
15247     *
15248     * This method can for instance be used to render a view into its layer before
15249     * starting an animation. If this view is complex, rendering into the layer
15250     * before starting the animation will avoid skipping frames.
15251     *
15252     * @throws IllegalStateException If this view is not attached to a window
15253     *
15254     * @see #setLayerType(int, android.graphics.Paint)
15255     */
15256    public void buildLayer() {
15257        if (mLayerType == LAYER_TYPE_NONE) return;
15258
15259        final AttachInfo attachInfo = mAttachInfo;
15260        if (attachInfo == null) {
15261            throw new IllegalStateException("This view must be attached to a window first");
15262        }
15263
15264        if (getWidth() == 0 || getHeight() == 0) {
15265            return;
15266        }
15267
15268        switch (mLayerType) {
15269            case LAYER_TYPE_HARDWARE:
15270                updateDisplayListIfDirty();
15271                if (attachInfo.mHardwareRenderer != null && mRenderNode.isValid()) {
15272                    attachInfo.mHardwareRenderer.buildLayer(mRenderNode);
15273                }
15274                break;
15275            case LAYER_TYPE_SOFTWARE:
15276                buildDrawingCache(true);
15277                break;
15278        }
15279    }
15280
15281    /**
15282     * Destroys all hardware rendering resources. This method is invoked
15283     * when the system needs to reclaim resources. Upon execution of this
15284     * method, you should free any OpenGL resources created by the view.
15285     *
15286     * Note: you <strong>must</strong> call
15287     * <code>super.destroyHardwareResources()</code> when overriding
15288     * this method.
15289     *
15290     * @hide
15291     */
15292    @CallSuper
15293    protected void destroyHardwareResources() {
15294        // Although the Layer will be destroyed by RenderNode, we want to release
15295        // the staging display list, which is also a signal to RenderNode that it's
15296        // safe to free its copy of the display list as it knows that we will
15297        // push an updated DisplayList if we try to draw again
15298        resetDisplayList();
15299    }
15300
15301    /**
15302     * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
15303     * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
15304     * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
15305     * the cache is enabled. To benefit from the cache, you must request the drawing cache by
15306     * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
15307     * null.</p>
15308     *
15309     * <p>Enabling the drawing cache is similar to
15310     * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
15311     * acceleration is turned off. When hardware acceleration is turned on, enabling the
15312     * drawing cache has no effect on rendering because the system uses a different mechanism
15313     * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
15314     * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
15315     * for information on how to enable software and hardware layers.</p>
15316     *
15317     * <p>This API can be used to manually generate
15318     * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
15319     * {@link #getDrawingCache()}.</p>
15320     *
15321     * @param enabled true to enable the drawing cache, false otherwise
15322     *
15323     * @see #isDrawingCacheEnabled()
15324     * @see #getDrawingCache()
15325     * @see #buildDrawingCache()
15326     * @see #setLayerType(int, android.graphics.Paint)
15327     */
15328    public void setDrawingCacheEnabled(boolean enabled) {
15329        mCachingFailed = false;
15330        setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
15331    }
15332
15333    /**
15334     * <p>Indicates whether the drawing cache is enabled for this view.</p>
15335     *
15336     * @return true if the drawing cache is enabled
15337     *
15338     * @see #setDrawingCacheEnabled(boolean)
15339     * @see #getDrawingCache()
15340     */
15341    @ViewDebug.ExportedProperty(category = "drawing")
15342    public boolean isDrawingCacheEnabled() {
15343        return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
15344    }
15345
15346    /**
15347     * Debugging utility which recursively outputs the dirty state of a view and its
15348     * descendants.
15349     *
15350     * @hide
15351     */
15352    @SuppressWarnings({"UnusedDeclaration"})
15353    public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
15354        Log.d("View", indent + this + "             DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
15355                ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
15356                (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
15357                ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
15358        if (clear) {
15359            mPrivateFlags &= clearMask;
15360        }
15361        if (this instanceof ViewGroup) {
15362            ViewGroup parent = (ViewGroup) this;
15363            final int count = parent.getChildCount();
15364            for (int i = 0; i < count; i++) {
15365                final View child = parent.getChildAt(i);
15366                child.outputDirtyFlags(indent + "  ", clear, clearMask);
15367            }
15368        }
15369    }
15370
15371    /**
15372     * This method is used by ViewGroup to cause its children to restore or recreate their
15373     * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
15374     * to recreate its own display list, which would happen if it went through the normal
15375     * draw/dispatchDraw mechanisms.
15376     *
15377     * @hide
15378     */
15379    protected void dispatchGetDisplayList() {}
15380
15381    /**
15382     * A view that is not attached or hardware accelerated cannot create a display list.
15383     * This method checks these conditions and returns the appropriate result.
15384     *
15385     * @return true if view has the ability to create a display list, false otherwise.
15386     *
15387     * @hide
15388     */
15389    public boolean canHaveDisplayList() {
15390        return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
15391    }
15392
15393    /**
15394     * Gets the RenderNode for the view, and updates its DisplayList (if needed and supported)
15395     * @hide
15396     */
15397    @NonNull
15398    public RenderNode updateDisplayListIfDirty() {
15399        final RenderNode renderNode = mRenderNode;
15400        if (!canHaveDisplayList()) {
15401            // can't populate RenderNode, don't try
15402            return renderNode;
15403        }
15404
15405        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0
15406                || !renderNode.isValid()
15407                || (mRecreateDisplayList)) {
15408            // Don't need to recreate the display list, just need to tell our
15409            // children to restore/recreate theirs
15410            if (renderNode.isValid()
15411                    && !mRecreateDisplayList) {
15412                mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15413                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15414                dispatchGetDisplayList();
15415
15416                return renderNode; // no work needed
15417            }
15418
15419            // If we got here, we're recreating it. Mark it as such to ensure that
15420            // we copy in child display lists into ours in drawChild()
15421            mRecreateDisplayList = true;
15422
15423            int width = mRight - mLeft;
15424            int height = mBottom - mTop;
15425            int layerType = getLayerType();
15426
15427            final DisplayListCanvas canvas = renderNode.start(width, height);
15428            canvas.setHighContrastText(mAttachInfo.mHighContrastText);
15429
15430            try {
15431                if (layerType == LAYER_TYPE_SOFTWARE) {
15432                    buildDrawingCache(true);
15433                    Bitmap cache = getDrawingCache(true);
15434                    if (cache != null) {
15435                        canvas.drawBitmap(cache, 0, 0, mLayerPaint);
15436                    }
15437                } else {
15438                    computeScroll();
15439
15440                    canvas.translate(-mScrollX, -mScrollY);
15441                    mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15442                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15443
15444                    // Fast path for layouts with no backgrounds
15445                    if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15446                        dispatchDraw(canvas);
15447                        if (mOverlay != null && !mOverlay.isEmpty()) {
15448                            mOverlay.getOverlayView().draw(canvas);
15449                        }
15450                    } else {
15451                        draw(canvas);
15452                    }
15453                }
15454            } finally {
15455                renderNode.end(canvas);
15456                setDisplayListProperties(renderNode);
15457            }
15458        } else {
15459            mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
15460            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15461        }
15462        return renderNode;
15463    }
15464
15465    private void resetDisplayList() {
15466        if (mRenderNode.isValid()) {
15467            mRenderNode.discardDisplayList();
15468        }
15469
15470        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
15471            mBackgroundRenderNode.discardDisplayList();
15472        }
15473    }
15474
15475    /**
15476     * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
15477     *
15478     * @return A non-scaled bitmap representing this view or null if cache is disabled.
15479     *
15480     * @see #getDrawingCache(boolean)
15481     */
15482    public Bitmap getDrawingCache() {
15483        return getDrawingCache(false);
15484    }
15485
15486    /**
15487     * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
15488     * is null when caching is disabled. If caching is enabled and the cache is not ready,
15489     * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
15490     * draw from the cache when the cache is enabled. To benefit from the cache, you must
15491     * request the drawing cache by calling this method and draw it on screen if the
15492     * returned bitmap is not null.</p>
15493     *
15494     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15495     * this method will create a bitmap of the same size as this view. Because this bitmap
15496     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15497     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15498     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15499     * size than the view. This implies that your application must be able to handle this
15500     * size.</p>
15501     *
15502     * @param autoScale Indicates whether the generated bitmap should be scaled based on
15503     *        the current density of the screen when the application is in compatibility
15504     *        mode.
15505     *
15506     * @return A bitmap representing this view or null if cache is disabled.
15507     *
15508     * @see #setDrawingCacheEnabled(boolean)
15509     * @see #isDrawingCacheEnabled()
15510     * @see #buildDrawingCache(boolean)
15511     * @see #destroyDrawingCache()
15512     */
15513    public Bitmap getDrawingCache(boolean autoScale) {
15514        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
15515            return null;
15516        }
15517        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
15518            buildDrawingCache(autoScale);
15519        }
15520        return autoScale ? mDrawingCache : mUnscaledDrawingCache;
15521    }
15522
15523    /**
15524     * <p>Frees the resources used by the drawing cache. If you call
15525     * {@link #buildDrawingCache()} manually without calling
15526     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15527     * should cleanup the cache with this method afterwards.</p>
15528     *
15529     * @see #setDrawingCacheEnabled(boolean)
15530     * @see #buildDrawingCache()
15531     * @see #getDrawingCache()
15532     */
15533    public void destroyDrawingCache() {
15534        if (mDrawingCache != null) {
15535            mDrawingCache.recycle();
15536            mDrawingCache = null;
15537        }
15538        if (mUnscaledDrawingCache != null) {
15539            mUnscaledDrawingCache.recycle();
15540            mUnscaledDrawingCache = null;
15541        }
15542    }
15543
15544    /**
15545     * Setting a solid background color for the drawing cache's bitmaps will improve
15546     * performance and memory usage. Note, though that this should only be used if this
15547     * view will always be drawn on top of a solid color.
15548     *
15549     * @param color The background color to use for the drawing cache's bitmap
15550     *
15551     * @see #setDrawingCacheEnabled(boolean)
15552     * @see #buildDrawingCache()
15553     * @see #getDrawingCache()
15554     */
15555    public void setDrawingCacheBackgroundColor(@ColorInt int color) {
15556        if (color != mDrawingCacheBackgroundColor) {
15557            mDrawingCacheBackgroundColor = color;
15558            mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
15559        }
15560    }
15561
15562    /**
15563     * @see #setDrawingCacheBackgroundColor(int)
15564     *
15565     * @return The background color to used for the drawing cache's bitmap
15566     */
15567    @ColorInt
15568    public int getDrawingCacheBackgroundColor() {
15569        return mDrawingCacheBackgroundColor;
15570    }
15571
15572    /**
15573     * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
15574     *
15575     * @see #buildDrawingCache(boolean)
15576     */
15577    public void buildDrawingCache() {
15578        buildDrawingCache(false);
15579    }
15580
15581    /**
15582     * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
15583     *
15584     * <p>If you call {@link #buildDrawingCache()} manually without calling
15585     * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
15586     * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
15587     *
15588     * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
15589     * this method will create a bitmap of the same size as this view. Because this bitmap
15590     * will be drawn scaled by the parent ViewGroup, the result on screen might show
15591     * scaling artifacts. To avoid such artifacts, you should call this method by setting
15592     * the auto scaling to true. Doing so, however, will generate a bitmap of a different
15593     * size than the view. This implies that your application must be able to handle this
15594     * size.</p>
15595     *
15596     * <p>You should avoid calling this method when hardware acceleration is enabled. If
15597     * you do not need the drawing cache bitmap, calling this method will increase memory
15598     * usage and cause the view to be rendered in software once, thus negatively impacting
15599     * performance.</p>
15600     *
15601     * @see #getDrawingCache()
15602     * @see #destroyDrawingCache()
15603     */
15604    public void buildDrawingCache(boolean autoScale) {
15605        if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
15606                mDrawingCache == null : mUnscaledDrawingCache == null)) {
15607            if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
15608                Trace.traceBegin(Trace.TRACE_TAG_VIEW,
15609                        "buildDrawingCache/SW Layer for " + getClass().getSimpleName());
15610            }
15611            try {
15612                buildDrawingCacheImpl(autoScale);
15613            } finally {
15614                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
15615            }
15616        }
15617    }
15618
15619    /**
15620     * private, internal implementation of buildDrawingCache, used to enable tracing
15621     */
15622    private void buildDrawingCacheImpl(boolean autoScale) {
15623        mCachingFailed = false;
15624
15625        int width = mRight - mLeft;
15626        int height = mBottom - mTop;
15627
15628        final AttachInfo attachInfo = mAttachInfo;
15629        final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
15630
15631        if (autoScale && scalingRequired) {
15632            width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
15633            height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
15634        }
15635
15636        final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
15637        final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
15638        final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
15639
15640        final long projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
15641        final long drawingCacheSize =
15642                ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
15643        if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
15644            if (width > 0 && height > 0) {
15645                Log.w(VIEW_LOG_TAG, getClass().getSimpleName() + " not displayed because it is"
15646                        + " too large to fit into a software layer (or drawing cache), needs "
15647                        + projectedBitmapSize + " bytes, only "
15648                        + drawingCacheSize + " available");
15649            }
15650            destroyDrawingCache();
15651            mCachingFailed = true;
15652            return;
15653        }
15654
15655        boolean clear = true;
15656        Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
15657
15658        if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
15659            Bitmap.Config quality;
15660            if (!opaque) {
15661                // Never pick ARGB_4444 because it looks awful
15662                // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
15663                switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
15664                    case DRAWING_CACHE_QUALITY_AUTO:
15665                    case DRAWING_CACHE_QUALITY_LOW:
15666                    case DRAWING_CACHE_QUALITY_HIGH:
15667                    default:
15668                        quality = Bitmap.Config.ARGB_8888;
15669                        break;
15670                }
15671            } else {
15672                // Optimization for translucent windows
15673                // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
15674                quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
15675            }
15676
15677            // Try to cleanup memory
15678            if (bitmap != null) bitmap.recycle();
15679
15680            try {
15681                bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15682                        width, height, quality);
15683                bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
15684                if (autoScale) {
15685                    mDrawingCache = bitmap;
15686                } else {
15687                    mUnscaledDrawingCache = bitmap;
15688                }
15689                if (opaque && use32BitCache) bitmap.setHasAlpha(false);
15690            } catch (OutOfMemoryError e) {
15691                // If there is not enough memory to create the bitmap cache, just
15692                // ignore the issue as bitmap caches are not required to draw the
15693                // view hierarchy
15694                if (autoScale) {
15695                    mDrawingCache = null;
15696                } else {
15697                    mUnscaledDrawingCache = null;
15698                }
15699                mCachingFailed = true;
15700                return;
15701            }
15702
15703            clear = drawingCacheBackgroundColor != 0;
15704        }
15705
15706        Canvas canvas;
15707        if (attachInfo != null) {
15708            canvas = attachInfo.mCanvas;
15709            if (canvas == null) {
15710                canvas = new Canvas();
15711            }
15712            canvas.setBitmap(bitmap);
15713            // Temporarily clobber the cached Canvas in case one of our children
15714            // is also using a drawing cache. Without this, the children would
15715            // steal the canvas by attaching their own bitmap to it and bad, bad
15716            // thing would happen (invisible views, corrupted drawings, etc.)
15717            attachInfo.mCanvas = null;
15718        } else {
15719            // This case should hopefully never or seldom happen
15720            canvas = new Canvas(bitmap);
15721        }
15722
15723        if (clear) {
15724            bitmap.eraseColor(drawingCacheBackgroundColor);
15725        }
15726
15727        computeScroll();
15728        final int restoreCount = canvas.save();
15729
15730        if (autoScale && scalingRequired) {
15731            final float scale = attachInfo.mApplicationScale;
15732            canvas.scale(scale, scale);
15733        }
15734
15735        canvas.translate(-mScrollX, -mScrollY);
15736
15737        mPrivateFlags |= PFLAG_DRAWN;
15738        if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
15739                mLayerType != LAYER_TYPE_NONE) {
15740            mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
15741        }
15742
15743        // Fast path for layouts with no backgrounds
15744        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15745            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15746            dispatchDraw(canvas);
15747            if (mOverlay != null && !mOverlay.isEmpty()) {
15748                mOverlay.getOverlayView().draw(canvas);
15749            }
15750        } else {
15751            draw(canvas);
15752        }
15753
15754        canvas.restoreToCount(restoreCount);
15755        canvas.setBitmap(null);
15756
15757        if (attachInfo != null) {
15758            // Restore the cached Canvas for our siblings
15759            attachInfo.mCanvas = canvas;
15760        }
15761    }
15762
15763    /**
15764     * Create a snapshot of the view into a bitmap.  We should probably make
15765     * some form of this public, but should think about the API.
15766     */
15767    Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
15768        int width = mRight - mLeft;
15769        int height = mBottom - mTop;
15770
15771        final AttachInfo attachInfo = mAttachInfo;
15772        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
15773        width = (int) ((width * scale) + 0.5f);
15774        height = (int) ((height * scale) + 0.5f);
15775
15776        Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
15777                width > 0 ? width : 1, height > 0 ? height : 1, quality);
15778        if (bitmap == null) {
15779            throw new OutOfMemoryError();
15780        }
15781
15782        Resources resources = getResources();
15783        if (resources != null) {
15784            bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
15785        }
15786
15787        Canvas canvas;
15788        if (attachInfo != null) {
15789            canvas = attachInfo.mCanvas;
15790            if (canvas == null) {
15791                canvas = new Canvas();
15792            }
15793            canvas.setBitmap(bitmap);
15794            // Temporarily clobber the cached Canvas in case one of our children
15795            // is also using a drawing cache. Without this, the children would
15796            // steal the canvas by attaching their own bitmap to it and bad, bad
15797            // things would happen (invisible views, corrupted drawings, etc.)
15798            attachInfo.mCanvas = null;
15799        } else {
15800            // This case should hopefully never or seldom happen
15801            canvas = new Canvas(bitmap);
15802        }
15803
15804        if ((backgroundColor & 0xff000000) != 0) {
15805            bitmap.eraseColor(backgroundColor);
15806        }
15807
15808        computeScroll();
15809        final int restoreCount = canvas.save();
15810        canvas.scale(scale, scale);
15811        canvas.translate(-mScrollX, -mScrollY);
15812
15813        // Temporarily remove the dirty mask
15814        int flags = mPrivateFlags;
15815        mPrivateFlags &= ~PFLAG_DIRTY_MASK;
15816
15817        // Fast path for layouts with no backgrounds
15818        if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
15819            dispatchDraw(canvas);
15820            if (mOverlay != null && !mOverlay.isEmpty()) {
15821                mOverlay.getOverlayView().draw(canvas);
15822            }
15823        } else {
15824            draw(canvas);
15825        }
15826
15827        mPrivateFlags = flags;
15828
15829        canvas.restoreToCount(restoreCount);
15830        canvas.setBitmap(null);
15831
15832        if (attachInfo != null) {
15833            // Restore the cached Canvas for our siblings
15834            attachInfo.mCanvas = canvas;
15835        }
15836
15837        return bitmap;
15838    }
15839
15840    /**
15841     * Indicates whether this View is currently in edit mode. A View is usually
15842     * in edit mode when displayed within a developer tool. For instance, if
15843     * this View is being drawn by a visual user interface builder, this method
15844     * should return true.
15845     *
15846     * Subclasses should check the return value of this method to provide
15847     * different behaviors if their normal behavior might interfere with the
15848     * host environment. For instance: the class spawns a thread in its
15849     * constructor, the drawing code relies on device-specific features, etc.
15850     *
15851     * This method is usually checked in the drawing code of custom widgets.
15852     *
15853     * @return True if this View is in edit mode, false otherwise.
15854     */
15855    public boolean isInEditMode() {
15856        return false;
15857    }
15858
15859    /**
15860     * If the View draws content inside its padding and enables fading edges,
15861     * it needs to support padding offsets. Padding offsets are added to the
15862     * fading edges to extend the length of the fade so that it covers pixels
15863     * drawn inside the padding.
15864     *
15865     * Subclasses of this class should override this method if they need
15866     * to draw content inside the padding.
15867     *
15868     * @return True if padding offset must be applied, false otherwise.
15869     *
15870     * @see #getLeftPaddingOffset()
15871     * @see #getRightPaddingOffset()
15872     * @see #getTopPaddingOffset()
15873     * @see #getBottomPaddingOffset()
15874     *
15875     * @since CURRENT
15876     */
15877    protected boolean isPaddingOffsetRequired() {
15878        return false;
15879    }
15880
15881    /**
15882     * Amount by which to extend the left fading region. Called only when
15883     * {@link #isPaddingOffsetRequired()} returns true.
15884     *
15885     * @return The left padding offset in pixels.
15886     *
15887     * @see #isPaddingOffsetRequired()
15888     *
15889     * @since CURRENT
15890     */
15891    protected int getLeftPaddingOffset() {
15892        return 0;
15893    }
15894
15895    /**
15896     * Amount by which to extend the right fading region. Called only when
15897     * {@link #isPaddingOffsetRequired()} returns true.
15898     *
15899     * @return The right padding offset in pixels.
15900     *
15901     * @see #isPaddingOffsetRequired()
15902     *
15903     * @since CURRENT
15904     */
15905    protected int getRightPaddingOffset() {
15906        return 0;
15907    }
15908
15909    /**
15910     * Amount by which to extend the top fading region. Called only when
15911     * {@link #isPaddingOffsetRequired()} returns true.
15912     *
15913     * @return The top padding offset in pixels.
15914     *
15915     * @see #isPaddingOffsetRequired()
15916     *
15917     * @since CURRENT
15918     */
15919    protected int getTopPaddingOffset() {
15920        return 0;
15921    }
15922
15923    /**
15924     * Amount by which to extend the bottom fading region. Called only when
15925     * {@link #isPaddingOffsetRequired()} returns true.
15926     *
15927     * @return The bottom padding offset in pixels.
15928     *
15929     * @see #isPaddingOffsetRequired()
15930     *
15931     * @since CURRENT
15932     */
15933    protected int getBottomPaddingOffset() {
15934        return 0;
15935    }
15936
15937    /**
15938     * @hide
15939     * @param offsetRequired
15940     */
15941    protected int getFadeTop(boolean offsetRequired) {
15942        int top = mPaddingTop;
15943        if (offsetRequired) top += getTopPaddingOffset();
15944        return top;
15945    }
15946
15947    /**
15948     * @hide
15949     * @param offsetRequired
15950     */
15951    protected int getFadeHeight(boolean offsetRequired) {
15952        int padding = mPaddingTop;
15953        if (offsetRequired) padding += getTopPaddingOffset();
15954        return mBottom - mTop - mPaddingBottom - padding;
15955    }
15956
15957    /**
15958     * <p>Indicates whether this view is attached to a hardware accelerated
15959     * window or not.</p>
15960     *
15961     * <p>Even if this method returns true, it does not mean that every call
15962     * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
15963     * accelerated {@link android.graphics.Canvas}. For instance, if this view
15964     * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
15965     * window is hardware accelerated,
15966     * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
15967     * return false, and this method will return true.</p>
15968     *
15969     * @return True if the view is attached to a window and the window is
15970     *         hardware accelerated; false in any other case.
15971     */
15972    @ViewDebug.ExportedProperty(category = "drawing")
15973    public boolean isHardwareAccelerated() {
15974        return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
15975    }
15976
15977    /**
15978     * Sets a rectangular area on this view to which the view will be clipped
15979     * when it is drawn. Setting the value to null will remove the clip bounds
15980     * and the view will draw normally, using its full bounds.
15981     *
15982     * @param clipBounds The rectangular area, in the local coordinates of
15983     * this view, to which future drawing operations will be clipped.
15984     */
15985    public void setClipBounds(Rect clipBounds) {
15986        if (clipBounds == mClipBounds
15987                || (clipBounds != null && clipBounds.equals(mClipBounds))) {
15988            return;
15989        }
15990        if (clipBounds != null) {
15991            if (mClipBounds == null) {
15992                mClipBounds = new Rect(clipBounds);
15993            } else {
15994                mClipBounds.set(clipBounds);
15995            }
15996        } else {
15997            mClipBounds = null;
15998        }
15999        mRenderNode.setClipBounds(mClipBounds);
16000        invalidateViewProperty(false, false);
16001    }
16002
16003    /**
16004     * Returns a copy of the current {@link #setClipBounds(Rect) clipBounds}.
16005     *
16006     * @return A copy of the current clip bounds if clip bounds are set,
16007     * otherwise null.
16008     */
16009    public Rect getClipBounds() {
16010        return (mClipBounds != null) ? new Rect(mClipBounds) : null;
16011    }
16012
16013
16014    /**
16015     * Populates an output rectangle with the clip bounds of the view,
16016     * returning {@code true} if successful or {@code false} if the view's
16017     * clip bounds are {@code null}.
16018     *
16019     * @param outRect rectangle in which to place the clip bounds of the view
16020     * @return {@code true} if successful or {@code false} if the view's
16021     *         clip bounds are {@code null}
16022     */
16023    public boolean getClipBounds(Rect outRect) {
16024        if (mClipBounds != null) {
16025            outRect.set(mClipBounds);
16026            return true;
16027        }
16028        return false;
16029    }
16030
16031    /**
16032     * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
16033     * case of an active Animation being run on the view.
16034     */
16035    private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
16036            Animation a, boolean scalingRequired) {
16037        Transformation invalidationTransform;
16038        final int flags = parent.mGroupFlags;
16039        final boolean initialized = a.isInitialized();
16040        if (!initialized) {
16041            a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
16042            a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
16043            if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
16044            onAnimationStart();
16045        }
16046
16047        final Transformation t = parent.getChildTransformation();
16048        boolean more = a.getTransformation(drawingTime, t, 1f);
16049        if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
16050            if (parent.mInvalidationTransformation == null) {
16051                parent.mInvalidationTransformation = new Transformation();
16052            }
16053            invalidationTransform = parent.mInvalidationTransformation;
16054            a.getTransformation(drawingTime, invalidationTransform, 1f);
16055        } else {
16056            invalidationTransform = t;
16057        }
16058
16059        if (more) {
16060            if (!a.willChangeBounds()) {
16061                if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
16062                        ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
16063                    parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
16064                } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
16065                    // The child need to draw an animation, potentially offscreen, so
16066                    // make sure we do not cancel invalidate requests
16067                    parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16068                    parent.invalidate(mLeft, mTop, mRight, mBottom);
16069                }
16070            } else {
16071                if (parent.mInvalidateRegion == null) {
16072                    parent.mInvalidateRegion = new RectF();
16073                }
16074                final RectF region = parent.mInvalidateRegion;
16075                a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
16076                        invalidationTransform);
16077
16078                // The child need to draw an animation, potentially offscreen, so
16079                // make sure we do not cancel invalidate requests
16080                parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
16081
16082                final int left = mLeft + (int) region.left;
16083                final int top = mTop + (int) region.top;
16084                parent.invalidate(left, top, left + (int) (region.width() + .5f),
16085                        top + (int) (region.height() + .5f));
16086            }
16087        }
16088        return more;
16089    }
16090
16091    /**
16092     * This method is called by getDisplayList() when a display list is recorded for a View.
16093     * It pushes any properties to the RenderNode that aren't managed by the RenderNode.
16094     */
16095    void setDisplayListProperties(RenderNode renderNode) {
16096        if (renderNode != null) {
16097            renderNode.setHasOverlappingRendering(hasOverlappingRendering());
16098            renderNode.setClipToBounds(mParent instanceof ViewGroup
16099                    && ((ViewGroup) mParent).getClipChildren());
16100
16101            float alpha = 1;
16102            if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
16103                    ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16104                ViewGroup parentVG = (ViewGroup) mParent;
16105                final Transformation t = parentVG.getChildTransformation();
16106                if (parentVG.getChildStaticTransformation(this, t)) {
16107                    final int transformType = t.getTransformationType();
16108                    if (transformType != Transformation.TYPE_IDENTITY) {
16109                        if ((transformType & Transformation.TYPE_ALPHA) != 0) {
16110                            alpha = t.getAlpha();
16111                        }
16112                        if ((transformType & Transformation.TYPE_MATRIX) != 0) {
16113                            renderNode.setStaticMatrix(t.getMatrix());
16114                        }
16115                    }
16116                }
16117            }
16118            if (mTransformationInfo != null) {
16119                alpha *= getFinalAlpha();
16120                if (alpha < 1) {
16121                    final int multipliedAlpha = (int) (255 * alpha);
16122                    if (onSetAlpha(multipliedAlpha)) {
16123                        alpha = 1;
16124                    }
16125                }
16126                renderNode.setAlpha(alpha);
16127            } else if (alpha < 1) {
16128                renderNode.setAlpha(alpha);
16129            }
16130        }
16131    }
16132
16133    /**
16134     * This method is called by ViewGroup.drawChild() to have each child view draw itself.
16135     *
16136     * This is where the View specializes rendering behavior based on layer type,
16137     * and hardware acceleration.
16138     */
16139    boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
16140        final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
16141        /* If an attached view draws to a HW canvas, it may use its RenderNode + DisplayList.
16142         *
16143         * If a view is dettached, its DisplayList shouldn't exist. If the canvas isn't
16144         * HW accelerated, it can't handle drawing RenderNodes.
16145         */
16146        boolean drawingWithRenderNode = mAttachInfo != null
16147                && mAttachInfo.mHardwareAccelerated
16148                && hardwareAcceleratedCanvas;
16149
16150        boolean more = false;
16151        final boolean childHasIdentityMatrix = hasIdentityMatrix();
16152        final int parentFlags = parent.mGroupFlags;
16153
16154        if ((parentFlags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) != 0) {
16155            parent.getChildTransformation().clear();
16156            parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16157        }
16158
16159        Transformation transformToApply = null;
16160        boolean concatMatrix = false;
16161        final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
16162        final Animation a = getAnimation();
16163        if (a != null) {
16164            more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
16165            concatMatrix = a.willChangeTransformationMatrix();
16166            if (concatMatrix) {
16167                mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16168            }
16169            transformToApply = parent.getChildTransformation();
16170        } else {
16171            if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) != 0) {
16172                // No longer animating: clear out old animation matrix
16173                mRenderNode.setAnimationMatrix(null);
16174                mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
16175            }
16176            if (!drawingWithRenderNode
16177                    && (parentFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
16178                final Transformation t = parent.getChildTransformation();
16179                final boolean hasTransform = parent.getChildStaticTransformation(this, t);
16180                if (hasTransform) {
16181                    final int transformType = t.getTransformationType();
16182                    transformToApply = transformType != Transformation.TYPE_IDENTITY ? t : null;
16183                    concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
16184                }
16185            }
16186        }
16187
16188        concatMatrix |= !childHasIdentityMatrix;
16189
16190        // Sets the flag as early as possible to allow draw() implementations
16191        // to call invalidate() successfully when doing animations
16192        mPrivateFlags |= PFLAG_DRAWN;
16193
16194        if (!concatMatrix &&
16195                (parentFlags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
16196                        ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
16197                canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
16198                (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
16199            mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
16200            return more;
16201        }
16202        mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
16203
16204        if (hardwareAcceleratedCanvas) {
16205            // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
16206            // retain the flag's value temporarily in the mRecreateDisplayList flag
16207            mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) != 0;
16208            mPrivateFlags &= ~PFLAG_INVALIDATED;
16209        }
16210
16211        RenderNode renderNode = null;
16212        Bitmap cache = null;
16213        int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
16214        if (layerType == LAYER_TYPE_SOFTWARE
16215                || (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
16216            // If not drawing with RenderNode, treat HW layers as SW
16217            layerType = LAYER_TYPE_SOFTWARE;
16218            buildDrawingCache(true);
16219            cache = getDrawingCache(true);
16220        }
16221
16222        if (drawingWithRenderNode) {
16223            // Delay getting the display list until animation-driven alpha values are
16224            // set up and possibly passed on to the view
16225            renderNode = updateDisplayListIfDirty();
16226            if (!renderNode.isValid()) {
16227                // Uncommon, but possible. If a view is removed from the hierarchy during the call
16228                // to getDisplayList(), the display list will be marked invalid and we should not
16229                // try to use it again.
16230                renderNode = null;
16231                drawingWithRenderNode = false;
16232            }
16233        }
16234
16235        int sx = 0;
16236        int sy = 0;
16237        if (!drawingWithRenderNode) {
16238            computeScroll();
16239            sx = mScrollX;
16240            sy = mScrollY;
16241        }
16242
16243        final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
16244        final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
16245
16246        int restoreTo = -1;
16247        if (!drawingWithRenderNode || transformToApply != null) {
16248            restoreTo = canvas.save();
16249        }
16250        if (offsetForScroll) {
16251            canvas.translate(mLeft - sx, mTop - sy);
16252        } else {
16253            if (!drawingWithRenderNode) {
16254                canvas.translate(mLeft, mTop);
16255            }
16256            if (scalingRequired) {
16257                if (drawingWithRenderNode) {
16258                    // TODO: Might not need this if we put everything inside the DL
16259                    restoreTo = canvas.save();
16260                }
16261                // mAttachInfo cannot be null, otherwise scalingRequired == false
16262                final float scale = 1.0f / mAttachInfo.mApplicationScale;
16263                canvas.scale(scale, scale);
16264            }
16265        }
16266
16267        float alpha = drawingWithRenderNode ? 1 : (getAlpha() * getTransitionAlpha());
16268        if (transformToApply != null
16269                || alpha < 1
16270                || !hasIdentityMatrix()
16271                || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16272            if (transformToApply != null || !childHasIdentityMatrix) {
16273                int transX = 0;
16274                int transY = 0;
16275
16276                if (offsetForScroll) {
16277                    transX = -sx;
16278                    transY = -sy;
16279                }
16280
16281                if (transformToApply != null) {
16282                    if (concatMatrix) {
16283                        if (drawingWithRenderNode) {
16284                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
16285                        } else {
16286                            // Undo the scroll translation, apply the transformation matrix,
16287                            // then redo the scroll translate to get the correct result.
16288                            canvas.translate(-transX, -transY);
16289                            canvas.concat(transformToApply.getMatrix());
16290                            canvas.translate(transX, transY);
16291                        }
16292                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16293                    }
16294
16295                    float transformAlpha = transformToApply.getAlpha();
16296                    if (transformAlpha < 1) {
16297                        alpha *= transformAlpha;
16298                        parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16299                    }
16300                }
16301
16302                if (!childHasIdentityMatrix && !drawingWithRenderNode) {
16303                    canvas.translate(-transX, -transY);
16304                    canvas.concat(getMatrix());
16305                    canvas.translate(transX, transY);
16306                }
16307            }
16308
16309            // Deal with alpha if it is or used to be <1
16310            if (alpha < 1 || (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) != 0) {
16311                if (alpha < 1) {
16312                    mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16313                } else {
16314                    mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
16315                }
16316                parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
16317                if (!drawingWithDrawingCache) {
16318                    final int multipliedAlpha = (int) (255 * alpha);
16319                    if (!onSetAlpha(multipliedAlpha)) {
16320                        if (drawingWithRenderNode) {
16321                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
16322                        } else if (layerType == LAYER_TYPE_NONE) {
16323                            canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
16324                                    multipliedAlpha);
16325                        }
16326                    } else {
16327                        // Alpha is handled by the child directly, clobber the layer's alpha
16328                        mPrivateFlags |= PFLAG_ALPHA_SET;
16329                    }
16330                }
16331            }
16332        } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16333            onSetAlpha(255);
16334            mPrivateFlags &= ~PFLAG_ALPHA_SET;
16335        }
16336
16337        if (!drawingWithRenderNode) {
16338            // apply clips directly, since RenderNode won't do it for this draw
16339            if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 && cache == null) {
16340                if (offsetForScroll) {
16341                    canvas.clipRect(sx, sy, sx + getWidth(), sy + getHeight());
16342                } else {
16343                    if (!scalingRequired || cache == null) {
16344                        canvas.clipRect(0, 0, getWidth(), getHeight());
16345                    } else {
16346                        canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
16347                    }
16348                }
16349            }
16350
16351            if (mClipBounds != null) {
16352                // clip bounds ignore scroll
16353                canvas.clipRect(mClipBounds);
16354            }
16355        }
16356
16357        if (!drawingWithDrawingCache) {
16358            if (drawingWithRenderNode) {
16359                mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16360                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16361            } else {
16362                // Fast path for layouts with no backgrounds
16363                if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
16364                    mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16365                    dispatchDraw(canvas);
16366                } else {
16367                    draw(canvas);
16368                }
16369            }
16370        } else if (cache != null) {
16371            mPrivateFlags &= ~PFLAG_DIRTY_MASK;
16372            if (layerType == LAYER_TYPE_NONE) {
16373                // no layer paint, use temporary paint to draw bitmap
16374                Paint cachePaint = parent.mCachePaint;
16375                if (cachePaint == null) {
16376                    cachePaint = new Paint();
16377                    cachePaint.setDither(false);
16378                    parent.mCachePaint = cachePaint;
16379                }
16380                cachePaint.setAlpha((int) (alpha * 255));
16381                canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
16382            } else {
16383                // use layer paint to draw the bitmap, merging the two alphas, but also restore
16384                int layerPaintAlpha = mLayerPaint.getAlpha();
16385                mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
16386                canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
16387                mLayerPaint.setAlpha(layerPaintAlpha);
16388            }
16389        }
16390
16391        if (restoreTo >= 0) {
16392            canvas.restoreToCount(restoreTo);
16393        }
16394
16395        if (a != null && !more) {
16396            if (!hardwareAcceleratedCanvas && !a.getFillAfter()) {
16397                onSetAlpha(255);
16398            }
16399            parent.finishAnimatingView(this, a);
16400        }
16401
16402        if (more && hardwareAcceleratedCanvas) {
16403            if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
16404                // alpha animations should cause the child to recreate its display list
16405                invalidate(true);
16406            }
16407        }
16408
16409        mRecreateDisplayList = false;
16410
16411        return more;
16412    }
16413
16414    /**
16415     * Manually render this view (and all of its children) to the given Canvas.
16416     * The view must have already done a full layout before this function is
16417     * called.  When implementing a view, implement
16418     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
16419     * If you do need to override this method, call the superclass version.
16420     *
16421     * @param canvas The Canvas to which the View is rendered.
16422     */
16423    @CallSuper
16424    public void draw(Canvas canvas) {
16425        final int privateFlags = mPrivateFlags;
16426        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
16427                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
16428        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
16429
16430        /*
16431         * Draw traversal performs several drawing steps which must be executed
16432         * in the appropriate order:
16433         *
16434         *      1. Draw the background
16435         *      2. If necessary, save the canvas' layers to prepare for fading
16436         *      3. Draw view's content
16437         *      4. Draw children
16438         *      5. If necessary, draw the fading edges and restore layers
16439         *      6. Draw decorations (scrollbars for instance)
16440         */
16441
16442        // Step 1, draw the background, if needed
16443        int saveCount;
16444
16445        if (!dirtyOpaque) {
16446            drawBackground(canvas);
16447        }
16448
16449        // skip step 2 & 5 if possible (common case)
16450        final int viewFlags = mViewFlags;
16451        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
16452        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
16453        if (!verticalEdges && !horizontalEdges) {
16454            // Step 3, draw the content
16455            if (!dirtyOpaque) onDraw(canvas);
16456
16457            // Step 4, draw the children
16458            dispatchDraw(canvas);
16459
16460            // Overlay is part of the content and draws beneath Foreground
16461            if (mOverlay != null && !mOverlay.isEmpty()) {
16462                mOverlay.getOverlayView().dispatchDraw(canvas);
16463            }
16464
16465            // Step 6, draw decorations (foreground, scrollbars)
16466            onDrawForeground(canvas);
16467
16468            // we're done...
16469            return;
16470        }
16471
16472        /*
16473         * Here we do the full fledged routine...
16474         * (this is an uncommon case where speed matters less,
16475         * this is why we repeat some of the tests that have been
16476         * done above)
16477         */
16478
16479        boolean drawTop = false;
16480        boolean drawBottom = false;
16481        boolean drawLeft = false;
16482        boolean drawRight = false;
16483
16484        float topFadeStrength = 0.0f;
16485        float bottomFadeStrength = 0.0f;
16486        float leftFadeStrength = 0.0f;
16487        float rightFadeStrength = 0.0f;
16488
16489        // Step 2, save the canvas' layers
16490        int paddingLeft = mPaddingLeft;
16491
16492        final boolean offsetRequired = isPaddingOffsetRequired();
16493        if (offsetRequired) {
16494            paddingLeft += getLeftPaddingOffset();
16495        }
16496
16497        int left = mScrollX + paddingLeft;
16498        int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
16499        int top = mScrollY + getFadeTop(offsetRequired);
16500        int bottom = top + getFadeHeight(offsetRequired);
16501
16502        if (offsetRequired) {
16503            right += getRightPaddingOffset();
16504            bottom += getBottomPaddingOffset();
16505        }
16506
16507        final ScrollabilityCache scrollabilityCache = mScrollCache;
16508        final float fadeHeight = scrollabilityCache.fadingEdgeLength;
16509        int length = (int) fadeHeight;
16510
16511        // clip the fade length if top and bottom fades overlap
16512        // overlapping fades produce odd-looking artifacts
16513        if (verticalEdges && (top + length > bottom - length)) {
16514            length = (bottom - top) / 2;
16515        }
16516
16517        // also clip horizontal fades if necessary
16518        if (horizontalEdges && (left + length > right - length)) {
16519            length = (right - left) / 2;
16520        }
16521
16522        if (verticalEdges) {
16523            topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
16524            drawTop = topFadeStrength * fadeHeight > 1.0f;
16525            bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
16526            drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
16527        }
16528
16529        if (horizontalEdges) {
16530            leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
16531            drawLeft = leftFadeStrength * fadeHeight > 1.0f;
16532            rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
16533            drawRight = rightFadeStrength * fadeHeight > 1.0f;
16534        }
16535
16536        saveCount = canvas.getSaveCount();
16537
16538        int solidColor = getSolidColor();
16539        if (solidColor == 0) {
16540            final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
16541
16542            if (drawTop) {
16543                canvas.saveLayer(left, top, right, top + length, null, flags);
16544            }
16545
16546            if (drawBottom) {
16547                canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
16548            }
16549
16550            if (drawLeft) {
16551                canvas.saveLayer(left, top, left + length, bottom, null, flags);
16552            }
16553
16554            if (drawRight) {
16555                canvas.saveLayer(right - length, top, right, bottom, null, flags);
16556            }
16557        } else {
16558            scrollabilityCache.setFadeColor(solidColor);
16559        }
16560
16561        // Step 3, draw the content
16562        if (!dirtyOpaque) onDraw(canvas);
16563
16564        // Step 4, draw the children
16565        dispatchDraw(canvas);
16566
16567        // Step 5, draw the fade effect and restore layers
16568        final Paint p = scrollabilityCache.paint;
16569        final Matrix matrix = scrollabilityCache.matrix;
16570        final Shader fade = scrollabilityCache.shader;
16571
16572        if (drawTop) {
16573            matrix.setScale(1, fadeHeight * topFadeStrength);
16574            matrix.postTranslate(left, top);
16575            fade.setLocalMatrix(matrix);
16576            p.setShader(fade);
16577            canvas.drawRect(left, top, right, top + length, p);
16578        }
16579
16580        if (drawBottom) {
16581            matrix.setScale(1, fadeHeight * bottomFadeStrength);
16582            matrix.postRotate(180);
16583            matrix.postTranslate(left, bottom);
16584            fade.setLocalMatrix(matrix);
16585            p.setShader(fade);
16586            canvas.drawRect(left, bottom - length, right, bottom, p);
16587        }
16588
16589        if (drawLeft) {
16590            matrix.setScale(1, fadeHeight * leftFadeStrength);
16591            matrix.postRotate(-90);
16592            matrix.postTranslate(left, top);
16593            fade.setLocalMatrix(matrix);
16594            p.setShader(fade);
16595            canvas.drawRect(left, top, left + length, bottom, p);
16596        }
16597
16598        if (drawRight) {
16599            matrix.setScale(1, fadeHeight * rightFadeStrength);
16600            matrix.postRotate(90);
16601            matrix.postTranslate(right, top);
16602            fade.setLocalMatrix(matrix);
16603            p.setShader(fade);
16604            canvas.drawRect(right - length, top, right, bottom, p);
16605        }
16606
16607        canvas.restoreToCount(saveCount);
16608
16609        // Overlay is part of the content and draws beneath Foreground
16610        if (mOverlay != null && !mOverlay.isEmpty()) {
16611            mOverlay.getOverlayView().dispatchDraw(canvas);
16612        }
16613
16614        // Step 6, draw decorations (foreground, scrollbars)
16615        onDrawForeground(canvas);
16616    }
16617
16618    /**
16619     * Draws the background onto the specified canvas.
16620     *
16621     * @param canvas Canvas on which to draw the background
16622     */
16623    private void drawBackground(Canvas canvas) {
16624        final Drawable background = mBackground;
16625        if (background == null) {
16626            return;
16627        }
16628
16629        setBackgroundBounds();
16630
16631        // Attempt to use a display list if requested.
16632        if (canvas.isHardwareAccelerated() && mAttachInfo != null
16633                && mAttachInfo.mHardwareRenderer != null) {
16634            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
16635
16636            final RenderNode renderNode = mBackgroundRenderNode;
16637            if (renderNode != null && renderNode.isValid()) {
16638                setBackgroundRenderNodeProperties(renderNode);
16639                ((DisplayListCanvas) canvas).drawRenderNode(renderNode);
16640                return;
16641            }
16642        }
16643
16644        final int scrollX = mScrollX;
16645        final int scrollY = mScrollY;
16646        if ((scrollX | scrollY) == 0) {
16647            background.draw(canvas);
16648        } else {
16649            canvas.translate(scrollX, scrollY);
16650            background.draw(canvas);
16651            canvas.translate(-scrollX, -scrollY);
16652        }
16653    }
16654
16655    /**
16656     * Sets the correct background bounds and rebuilds the outline, if needed.
16657     * <p/>
16658     * This is called by LayoutLib.
16659     */
16660    void setBackgroundBounds() {
16661        if (mBackgroundSizeChanged && mBackground != null) {
16662            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
16663            mBackgroundSizeChanged = false;
16664            rebuildOutline();
16665        }
16666    }
16667
16668    private void setBackgroundRenderNodeProperties(RenderNode renderNode) {
16669        renderNode.setTranslationX(mScrollX);
16670        renderNode.setTranslationY(mScrollY);
16671    }
16672
16673    /**
16674     * Creates a new display list or updates the existing display list for the
16675     * specified Drawable.
16676     *
16677     * @param drawable Drawable for which to create a display list
16678     * @param renderNode Existing RenderNode, or {@code null}
16679     * @return A valid display list for the specified drawable
16680     */
16681    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
16682        if (renderNode == null) {
16683            renderNode = RenderNode.create(drawable.getClass().getName(), this);
16684        }
16685
16686        final Rect bounds = drawable.getBounds();
16687        final int width = bounds.width();
16688        final int height = bounds.height();
16689        final DisplayListCanvas canvas = renderNode.start(width, height);
16690
16691        // Reverse left/top translation done by drawable canvas, which will
16692        // instead be applied by rendernode's LTRB bounds below. This way, the
16693        // drawable's bounds match with its rendernode bounds and its content
16694        // will lie within those bounds in the rendernode tree.
16695        canvas.translate(-bounds.left, -bounds.top);
16696
16697        try {
16698            drawable.draw(canvas);
16699        } finally {
16700            renderNode.end(canvas);
16701        }
16702
16703        // Set up drawable properties that are view-independent.
16704        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
16705        renderNode.setProjectBackwards(drawable.isProjected());
16706        renderNode.setProjectionReceiver(true);
16707        renderNode.setClipToBounds(false);
16708        return renderNode;
16709    }
16710
16711    /**
16712     * Returns the overlay for this view, creating it if it does not yet exist.
16713     * Adding drawables to the overlay will cause them to be displayed whenever
16714     * the view itself is redrawn. Objects in the overlay should be actively
16715     * managed: remove them when they should not be displayed anymore. The
16716     * overlay will always have the same size as its host view.
16717     *
16718     * <p>Note: Overlays do not currently work correctly with {@link
16719     * SurfaceView} or {@link TextureView}; contents in overlays for these
16720     * types of views may not display correctly.</p>
16721     *
16722     * @return The ViewOverlay object for this view.
16723     * @see ViewOverlay
16724     */
16725    public ViewOverlay getOverlay() {
16726        if (mOverlay == null) {
16727            mOverlay = new ViewOverlay(mContext, this);
16728        }
16729        return mOverlay;
16730    }
16731
16732    /**
16733     * Override this if your view is known to always be drawn on top of a solid color background,
16734     * and needs to draw fading edges. Returning a non-zero color enables the view system to
16735     * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
16736     * should be set to 0xFF.
16737     *
16738     * @see #setVerticalFadingEdgeEnabled(boolean)
16739     * @see #setHorizontalFadingEdgeEnabled(boolean)
16740     *
16741     * @return The known solid color background for this view, or 0 if the color may vary
16742     */
16743    @ViewDebug.ExportedProperty(category = "drawing")
16744    @ColorInt
16745    public int getSolidColor() {
16746        return 0;
16747    }
16748
16749    /**
16750     * Build a human readable string representation of the specified view flags.
16751     *
16752     * @param flags the view flags to convert to a string
16753     * @return a String representing the supplied flags
16754     */
16755    private static String printFlags(int flags) {
16756        String output = "";
16757        int numFlags = 0;
16758        if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
16759            output += "TAKES_FOCUS";
16760            numFlags++;
16761        }
16762
16763        switch (flags & VISIBILITY_MASK) {
16764        case INVISIBLE:
16765            if (numFlags > 0) {
16766                output += " ";
16767            }
16768            output += "INVISIBLE";
16769            // USELESS HERE numFlags++;
16770            break;
16771        case GONE:
16772            if (numFlags > 0) {
16773                output += " ";
16774            }
16775            output += "GONE";
16776            // USELESS HERE numFlags++;
16777            break;
16778        default:
16779            break;
16780        }
16781        return output;
16782    }
16783
16784    /**
16785     * Build a human readable string representation of the specified private
16786     * view flags.
16787     *
16788     * @param privateFlags the private view flags to convert to a string
16789     * @return a String representing the supplied flags
16790     */
16791    private static String printPrivateFlags(int privateFlags) {
16792        String output = "";
16793        int numFlags = 0;
16794
16795        if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
16796            output += "WANTS_FOCUS";
16797            numFlags++;
16798        }
16799
16800        if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
16801            if (numFlags > 0) {
16802                output += " ";
16803            }
16804            output += "FOCUSED";
16805            numFlags++;
16806        }
16807
16808        if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
16809            if (numFlags > 0) {
16810                output += " ";
16811            }
16812            output += "SELECTED";
16813            numFlags++;
16814        }
16815
16816        if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
16817            if (numFlags > 0) {
16818                output += " ";
16819            }
16820            output += "IS_ROOT_NAMESPACE";
16821            numFlags++;
16822        }
16823
16824        if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
16825            if (numFlags > 0) {
16826                output += " ";
16827            }
16828            output += "HAS_BOUNDS";
16829            numFlags++;
16830        }
16831
16832        if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
16833            if (numFlags > 0) {
16834                output += " ";
16835            }
16836            output += "DRAWN";
16837            // USELESS HERE numFlags++;
16838        }
16839        return output;
16840    }
16841
16842    /**
16843     * <p>Indicates whether or not this view's layout will be requested during
16844     * the next hierarchy layout pass.</p>
16845     *
16846     * @return true if the layout will be forced during next layout pass
16847     */
16848    public boolean isLayoutRequested() {
16849        return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
16850    }
16851
16852    /**
16853     * Return true if o is a ViewGroup that is laying out using optical bounds.
16854     * @hide
16855     */
16856    public static boolean isLayoutModeOptical(Object o) {
16857        return o instanceof ViewGroup && ((ViewGroup) o).isLayoutModeOptical();
16858    }
16859
16860    private boolean setOpticalFrame(int left, int top, int right, int bottom) {
16861        Insets parentInsets = mParent instanceof View ?
16862                ((View) mParent).getOpticalInsets() : Insets.NONE;
16863        Insets childInsets = getOpticalInsets();
16864        return setFrame(
16865                left   + parentInsets.left - childInsets.left,
16866                top    + parentInsets.top  - childInsets.top,
16867                right  + parentInsets.left + childInsets.right,
16868                bottom + parentInsets.top  + childInsets.bottom);
16869    }
16870
16871    /**
16872     * Assign a size and position to a view and all of its
16873     * descendants
16874     *
16875     * <p>This is the second phase of the layout mechanism.
16876     * (The first is measuring). In this phase, each parent calls
16877     * layout on all of its children to position them.
16878     * This is typically done using the child measurements
16879     * that were stored in the measure pass().</p>
16880     *
16881     * <p>Derived classes should not override this method.
16882     * Derived classes with children should override
16883     * onLayout. In that method, they should
16884     * call layout on each of their children.</p>
16885     *
16886     * @param l Left position, relative to parent
16887     * @param t Top position, relative to parent
16888     * @param r Right position, relative to parent
16889     * @param b Bottom position, relative to parent
16890     */
16891    @SuppressWarnings({"unchecked"})
16892    public void layout(int l, int t, int r, int b) {
16893        if ((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) != 0) {
16894            onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
16895            mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
16896        }
16897
16898        int oldL = mLeft;
16899        int oldT = mTop;
16900        int oldB = mBottom;
16901        int oldR = mRight;
16902
16903        boolean changed = isLayoutModeOptical(mParent) ?
16904                setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
16905
16906        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
16907            onLayout(changed, l, t, r, b);
16908            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
16909
16910            ListenerInfo li = mListenerInfo;
16911            if (li != null && li.mOnLayoutChangeListeners != null) {
16912                ArrayList<OnLayoutChangeListener> listenersCopy =
16913                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
16914                int numListeners = listenersCopy.size();
16915                for (int i = 0; i < numListeners; ++i) {
16916                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
16917                }
16918            }
16919        }
16920
16921        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
16922        mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
16923    }
16924
16925    /**
16926     * Called from layout when this view should
16927     * assign a size and position to each of its children.
16928     *
16929     * Derived classes with children should override
16930     * this method and call layout on each of
16931     * their children.
16932     * @param changed This is a new size or position for this view
16933     * @param left Left position, relative to parent
16934     * @param top Top position, relative to parent
16935     * @param right Right position, relative to parent
16936     * @param bottom Bottom position, relative to parent
16937     */
16938    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
16939    }
16940
16941    /**
16942     * Assign a size and position to this view.
16943     *
16944     * This is called from layout.
16945     *
16946     * @param left Left position, relative to parent
16947     * @param top Top position, relative to parent
16948     * @param right Right position, relative to parent
16949     * @param bottom Bottom position, relative to parent
16950     * @return true if the new size and position are different than the
16951     *         previous ones
16952     * {@hide}
16953     */
16954    protected boolean setFrame(int left, int top, int right, int bottom) {
16955        boolean changed = false;
16956
16957        if (DBG) {
16958            Log.d("View", this + " View.setFrame(" + left + "," + top + ","
16959                    + right + "," + bottom + ")");
16960        }
16961
16962        if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
16963            changed = true;
16964
16965            // Remember our drawn bit
16966            int drawn = mPrivateFlags & PFLAG_DRAWN;
16967
16968            int oldWidth = mRight - mLeft;
16969            int oldHeight = mBottom - mTop;
16970            int newWidth = right - left;
16971            int newHeight = bottom - top;
16972            boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
16973
16974            // Invalidate our old position
16975            invalidate(sizeChanged);
16976
16977            mLeft = left;
16978            mTop = top;
16979            mRight = right;
16980            mBottom = bottom;
16981            mRenderNode.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
16982
16983            mPrivateFlags |= PFLAG_HAS_BOUNDS;
16984
16985
16986            if (sizeChanged) {
16987                sizeChange(newWidth, newHeight, oldWidth, oldHeight);
16988            }
16989
16990            if ((mViewFlags & VISIBILITY_MASK) == VISIBLE || mGhostView != null) {
16991                // If we are visible, force the DRAWN bit to on so that
16992                // this invalidate will go through (at least to our parent).
16993                // This is because someone may have invalidated this view
16994                // before this call to setFrame came in, thereby clearing
16995                // the DRAWN bit.
16996                mPrivateFlags |= PFLAG_DRAWN;
16997                invalidate(sizeChanged);
16998                // parent display list may need to be recreated based on a change in the bounds
16999                // of any child
17000                invalidateParentCaches();
17001            }
17002
17003            // Reset drawn bit to original value (invalidate turns it off)
17004            mPrivateFlags |= drawn;
17005
17006            mBackgroundSizeChanged = true;
17007            if (mForegroundInfo != null) {
17008                mForegroundInfo.mBoundsChanged = true;
17009            }
17010
17011            notifySubtreeAccessibilityStateChangedIfNeeded();
17012        }
17013        return changed;
17014    }
17015
17016    /**
17017     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
17018     * @hide
17019     */
17020    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
17021        setFrame(left, top, right, bottom);
17022    }
17023
17024    private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
17025        onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
17026        if (mOverlay != null) {
17027            mOverlay.getOverlayView().setRight(newWidth);
17028            mOverlay.getOverlayView().setBottom(newHeight);
17029        }
17030        rebuildOutline();
17031    }
17032
17033    /**
17034     * Finalize inflating a view from XML.  This is called as the last phase
17035     * of inflation, after all child views have been added.
17036     *
17037     * <p>Even if the subclass overrides onFinishInflate, they should always be
17038     * sure to call the super method, so that we get called.
17039     */
17040    @CallSuper
17041    protected void onFinishInflate() {
17042    }
17043
17044    /**
17045     * Returns the resources associated with this view.
17046     *
17047     * @return Resources object.
17048     */
17049    public Resources getResources() {
17050        return mResources;
17051    }
17052
17053    /**
17054     * Invalidates the specified Drawable.
17055     *
17056     * @param drawable the drawable to invalidate
17057     */
17058    @Override
17059    public void invalidateDrawable(@NonNull Drawable drawable) {
17060        if (verifyDrawable(drawable)) {
17061            final Rect dirty = drawable.getDirtyBounds();
17062            final int scrollX = mScrollX;
17063            final int scrollY = mScrollY;
17064
17065            invalidate(dirty.left + scrollX, dirty.top + scrollY,
17066                    dirty.right + scrollX, dirty.bottom + scrollY);
17067            rebuildOutline();
17068        }
17069    }
17070
17071    /**
17072     * Schedules an action on a drawable to occur at a specified time.
17073     *
17074     * @param who the recipient of the action
17075     * @param what the action to run on the drawable
17076     * @param when the time at which the action must occur. Uses the
17077     *        {@link SystemClock#uptimeMillis} timebase.
17078     */
17079    @Override
17080    public void scheduleDrawable(Drawable who, Runnable what, long when) {
17081        if (verifyDrawable(who) && what != null) {
17082            final long delay = when - SystemClock.uptimeMillis();
17083            if (mAttachInfo != null) {
17084                mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
17085                        Choreographer.CALLBACK_ANIMATION, what, who,
17086                        Choreographer.subtractFrameDelay(delay));
17087            } else {
17088                // Postpone the runnable until we know
17089                // on which thread it needs to run.
17090                getRunQueue().postDelayed(what, delay);
17091            }
17092        }
17093    }
17094
17095    /**
17096     * Cancels a scheduled action on a drawable.
17097     *
17098     * @param who the recipient of the action
17099     * @param what the action to cancel
17100     */
17101    @Override
17102    public void unscheduleDrawable(Drawable who, Runnable what) {
17103        if (verifyDrawable(who) && what != null) {
17104            if (mAttachInfo != null) {
17105                mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17106                        Choreographer.CALLBACK_ANIMATION, what, who);
17107            }
17108            getRunQueue().removeCallbacks(what);
17109        }
17110    }
17111
17112    /**
17113     * Unschedule any events associated with the given Drawable.  This can be
17114     * used when selecting a new Drawable into a view, so that the previous
17115     * one is completely unscheduled.
17116     *
17117     * @param who The Drawable to unschedule.
17118     *
17119     * @see #drawableStateChanged
17120     */
17121    public void unscheduleDrawable(Drawable who) {
17122        if (mAttachInfo != null && who != null) {
17123            mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
17124                    Choreographer.CALLBACK_ANIMATION, null, who);
17125        }
17126    }
17127
17128    /**
17129     * Resolve the Drawables depending on the layout direction. This is implicitly supposing
17130     * that the View directionality can and will be resolved before its Drawables.
17131     *
17132     * Will call {@link View#onResolveDrawables} when resolution is done.
17133     *
17134     * @hide
17135     */
17136    protected void resolveDrawables() {
17137        // Drawables resolution may need to happen before resolving the layout direction (which is
17138        // done only during the measure() call).
17139        // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
17140        // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
17141        // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
17142        // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
17143        // direction to be resolved as its resolved value will be the same as its raw value.
17144        if (!isLayoutDirectionResolved() &&
17145                getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
17146            return;
17147        }
17148
17149        final int layoutDirection = isLayoutDirectionResolved() ?
17150                getLayoutDirection() : getRawLayoutDirection();
17151
17152        if (mBackground != null) {
17153            mBackground.setLayoutDirection(layoutDirection);
17154        }
17155        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17156            mForegroundInfo.mDrawable.setLayoutDirection(layoutDirection);
17157        }
17158        mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
17159        onResolveDrawables(layoutDirection);
17160    }
17161
17162    boolean areDrawablesResolved() {
17163        return (mPrivateFlags2 & PFLAG2_DRAWABLE_RESOLVED) == PFLAG2_DRAWABLE_RESOLVED;
17164    }
17165
17166    /**
17167     * Called when layout direction has been resolved.
17168     *
17169     * The default implementation does nothing.
17170     *
17171     * @param layoutDirection The resolved layout direction.
17172     *
17173     * @see #LAYOUT_DIRECTION_LTR
17174     * @see #LAYOUT_DIRECTION_RTL
17175     *
17176     * @hide
17177     */
17178    public void onResolveDrawables(@ResolvedLayoutDir int layoutDirection) {
17179    }
17180
17181    /**
17182     * @hide
17183     */
17184    protected void resetResolvedDrawables() {
17185        resetResolvedDrawablesInternal();
17186    }
17187
17188    void resetResolvedDrawablesInternal() {
17189        mPrivateFlags2 &= ~PFLAG2_DRAWABLE_RESOLVED;
17190    }
17191
17192    /**
17193     * If your view subclass is displaying its own Drawable objects, it should
17194     * override this function and return true for any Drawable it is
17195     * displaying.  This allows animations for those drawables to be
17196     * scheduled.
17197     *
17198     * <p>Be sure to call through to the super class when overriding this
17199     * function.
17200     *
17201     * @param who The Drawable to verify.  Return true if it is one you are
17202     *            displaying, else return the result of calling through to the
17203     *            super class.
17204     *
17205     * @return boolean If true than the Drawable is being displayed in the
17206     *         view; else false and it is not allowed to animate.
17207     *
17208     * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
17209     * @see #drawableStateChanged()
17210     */
17211    @CallSuper
17212    protected boolean verifyDrawable(Drawable who) {
17213        return who == mBackground || (mScrollCache != null && mScrollCache.scrollBar == who)
17214                || (mForegroundInfo != null && mForegroundInfo.mDrawable == who);
17215    }
17216
17217    /**
17218     * This function is called whenever the state of the view changes in such
17219     * a way that it impacts the state of drawables being shown.
17220     * <p>
17221     * If the View has a StateListAnimator, it will also be called to run necessary state
17222     * change animations.
17223     * <p>
17224     * Be sure to call through to the superclass when overriding this function.
17225     *
17226     * @see Drawable#setState(int[])
17227     */
17228    @CallSuper
17229    protected void drawableStateChanged() {
17230        final int[] state = getDrawableState();
17231        boolean changed = false;
17232
17233        final Drawable bg = mBackground;
17234        if (bg != null && bg.isStateful()) {
17235            changed |= bg.setState(state);
17236        }
17237
17238        final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17239        if (fg != null && fg.isStateful()) {
17240            changed |= fg.setState(state);
17241        }
17242
17243        if (mScrollCache != null) {
17244            final Drawable scrollBar = mScrollCache.scrollBar;
17245            if (scrollBar != null && scrollBar.isStateful()) {
17246                changed |= scrollBar.setState(state)
17247                        && mScrollCache.state != ScrollabilityCache.OFF;
17248            }
17249        }
17250
17251        if (mStateListAnimator != null) {
17252            mStateListAnimator.setState(state);
17253        }
17254
17255        if (changed) {
17256            invalidate();
17257        }
17258    }
17259
17260    /**
17261     * This function is called whenever the view hotspot changes and needs to
17262     * be propagated to drawables or child views managed by the view.
17263     * <p>
17264     * Dispatching to child views is handled by
17265     * {@link #dispatchDrawableHotspotChanged(float, float)}.
17266     * <p>
17267     * Be sure to call through to the superclass when overriding this function.
17268     *
17269     * @param x hotspot x coordinate
17270     * @param y hotspot y coordinate
17271     */
17272    @CallSuper
17273    public void drawableHotspotChanged(float x, float y) {
17274        if (mBackground != null) {
17275            mBackground.setHotspot(x, y);
17276        }
17277        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17278            mForegroundInfo.mDrawable.setHotspot(x, y);
17279        }
17280
17281        dispatchDrawableHotspotChanged(x, y);
17282    }
17283
17284    /**
17285     * Dispatches drawableHotspotChanged to all of this View's children.
17286     *
17287     * @param x hotspot x coordinate
17288     * @param y hotspot y coordinate
17289     * @see #drawableHotspotChanged(float, float)
17290     */
17291    public void dispatchDrawableHotspotChanged(float x, float y) {
17292    }
17293
17294    /**
17295     * Call this to force a view to update its drawable state. This will cause
17296     * drawableStateChanged to be called on this view. Views that are interested
17297     * in the new state should call getDrawableState.
17298     *
17299     * @see #drawableStateChanged
17300     * @see #getDrawableState
17301     */
17302    public void refreshDrawableState() {
17303        mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
17304        drawableStateChanged();
17305
17306        ViewParent parent = mParent;
17307        if (parent != null) {
17308            parent.childDrawableStateChanged(this);
17309        }
17310    }
17311
17312    /**
17313     * Return an array of resource IDs of the drawable states representing the
17314     * current state of the view.
17315     *
17316     * @return The current drawable state
17317     *
17318     * @see Drawable#setState(int[])
17319     * @see #drawableStateChanged()
17320     * @see #onCreateDrawableState(int)
17321     */
17322    public final int[] getDrawableState() {
17323        if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
17324            return mDrawableState;
17325        } else {
17326            mDrawableState = onCreateDrawableState(0);
17327            mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
17328            return mDrawableState;
17329        }
17330    }
17331
17332    /**
17333     * Generate the new {@link android.graphics.drawable.Drawable} state for
17334     * this view. This is called by the view
17335     * system when the cached Drawable state is determined to be invalid.  To
17336     * retrieve the current state, you should use {@link #getDrawableState}.
17337     *
17338     * @param extraSpace if non-zero, this is the number of extra entries you
17339     * would like in the returned array in which you can place your own
17340     * states.
17341     *
17342     * @return Returns an array holding the current {@link Drawable} state of
17343     * the view.
17344     *
17345     * @see #mergeDrawableStates(int[], int[])
17346     */
17347    protected int[] onCreateDrawableState(int extraSpace) {
17348        if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
17349                mParent instanceof View) {
17350            return ((View) mParent).onCreateDrawableState(extraSpace);
17351        }
17352
17353        int[] drawableState;
17354
17355        int privateFlags = mPrivateFlags;
17356
17357        int viewStateIndex = 0;
17358        if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= StateSet.VIEW_STATE_PRESSED;
17359        if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= StateSet.VIEW_STATE_ENABLED;
17360        if (isFocused()) viewStateIndex |= StateSet.VIEW_STATE_FOCUSED;
17361        if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= StateSet.VIEW_STATE_SELECTED;
17362        if (hasWindowFocus()) viewStateIndex |= StateSet.VIEW_STATE_WINDOW_FOCUSED;
17363        if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= StateSet.VIEW_STATE_ACTIVATED;
17364        if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
17365                HardwareRenderer.isAvailable()) {
17366            // This is set if HW acceleration is requested, even if the current
17367            // process doesn't allow it.  This is just to allow app preview
17368            // windows to better match their app.
17369            viewStateIndex |= StateSet.VIEW_STATE_ACCELERATED;
17370        }
17371        if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= StateSet.VIEW_STATE_HOVERED;
17372
17373        final int privateFlags2 = mPrivateFlags2;
17374        if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) {
17375            viewStateIndex |= StateSet.VIEW_STATE_DRAG_CAN_ACCEPT;
17376        }
17377        if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) {
17378            viewStateIndex |= StateSet.VIEW_STATE_DRAG_HOVERED;
17379        }
17380
17381        drawableState = StateSet.get(viewStateIndex);
17382
17383        //noinspection ConstantIfStatement
17384        if (false) {
17385            Log.i("View", "drawableStateIndex=" + viewStateIndex);
17386            Log.i("View", toString()
17387                    + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
17388                    + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
17389                    + " fo=" + hasFocus()
17390                    + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
17391                    + " wf=" + hasWindowFocus()
17392                    + ": " + Arrays.toString(drawableState));
17393        }
17394
17395        if (extraSpace == 0) {
17396            return drawableState;
17397        }
17398
17399        final int[] fullState;
17400        if (drawableState != null) {
17401            fullState = new int[drawableState.length + extraSpace];
17402            System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
17403        } else {
17404            fullState = new int[extraSpace];
17405        }
17406
17407        return fullState;
17408    }
17409
17410    /**
17411     * Merge your own state values in <var>additionalState</var> into the base
17412     * state values <var>baseState</var> that were returned by
17413     * {@link #onCreateDrawableState(int)}.
17414     *
17415     * @param baseState The base state values returned by
17416     * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
17417     * own additional state values.
17418     *
17419     * @param additionalState The additional state values you would like
17420     * added to <var>baseState</var>; this array is not modified.
17421     *
17422     * @return As a convenience, the <var>baseState</var> array you originally
17423     * passed into the function is returned.
17424     *
17425     * @see #onCreateDrawableState(int)
17426     */
17427    protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
17428        final int N = baseState.length;
17429        int i = N - 1;
17430        while (i >= 0 && baseState[i] == 0) {
17431            i--;
17432        }
17433        System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
17434        return baseState;
17435    }
17436
17437    /**
17438     * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
17439     * on all Drawable objects associated with this view.
17440     * <p>
17441     * Also calls {@link StateListAnimator#jumpToCurrentState()} if there is a StateListAnimator
17442     * attached to this view.
17443     */
17444    @CallSuper
17445    public void jumpDrawablesToCurrentState() {
17446        if (mBackground != null) {
17447            mBackground.jumpToCurrentState();
17448        }
17449        if (mStateListAnimator != null) {
17450            mStateListAnimator.jumpToCurrentState();
17451        }
17452        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null) {
17453            mForegroundInfo.mDrawable.jumpToCurrentState();
17454        }
17455    }
17456
17457    /**
17458     * Sets the background color for this view.
17459     * @param color the color of the background
17460     */
17461    @RemotableViewMethod
17462    public void setBackgroundColor(@ColorInt int color) {
17463        if (mBackground instanceof ColorDrawable) {
17464            ((ColorDrawable) mBackground.mutate()).setColor(color);
17465            computeOpaqueFlags();
17466            mBackgroundResource = 0;
17467        } else {
17468            setBackground(new ColorDrawable(color));
17469        }
17470    }
17471
17472    /**
17473     * Set the background to a given resource. The resource should refer to
17474     * a Drawable object or 0 to remove the background.
17475     * @param resid The identifier of the resource.
17476     *
17477     * @attr ref android.R.styleable#View_background
17478     */
17479    @RemotableViewMethod
17480    public void setBackgroundResource(@DrawableRes int resid) {
17481        if (resid != 0 && resid == mBackgroundResource) {
17482            return;
17483        }
17484
17485        Drawable d = null;
17486        if (resid != 0) {
17487            d = mContext.getDrawable(resid);
17488        }
17489        setBackground(d);
17490
17491        mBackgroundResource = resid;
17492    }
17493
17494    /**
17495     * Set the background to a given Drawable, or remove the background. If the
17496     * background has padding, this View's padding is set to the background's
17497     * padding. However, when a background is removed, this View's padding isn't
17498     * touched. If setting the padding is desired, please use
17499     * {@link #setPadding(int, int, int, int)}.
17500     *
17501     * @param background The Drawable to use as the background, or null to remove the
17502     *        background
17503     */
17504    public void setBackground(Drawable background) {
17505        //noinspection deprecation
17506        setBackgroundDrawable(background);
17507    }
17508
17509    /**
17510     * @deprecated use {@link #setBackground(Drawable)} instead
17511     */
17512    @Deprecated
17513    public void setBackgroundDrawable(Drawable background) {
17514        computeOpaqueFlags();
17515
17516        if (background == mBackground) {
17517            return;
17518        }
17519
17520        boolean requestLayout = false;
17521
17522        mBackgroundResource = 0;
17523
17524        /*
17525         * Regardless of whether we're setting a new background or not, we want
17526         * to clear the previous drawable.
17527         */
17528        if (mBackground != null) {
17529            mBackground.setCallback(null);
17530            unscheduleDrawable(mBackground);
17531        }
17532
17533        if (background != null) {
17534            Rect padding = sThreadLocal.get();
17535            if (padding == null) {
17536                padding = new Rect();
17537                sThreadLocal.set(padding);
17538            }
17539            resetResolvedDrawablesInternal();
17540            background.setLayoutDirection(getLayoutDirection());
17541            if (background.getPadding(padding)) {
17542                resetResolvedPaddingInternal();
17543                switch (background.getLayoutDirection()) {
17544                    case LAYOUT_DIRECTION_RTL:
17545                        mUserPaddingLeftInitial = padding.right;
17546                        mUserPaddingRightInitial = padding.left;
17547                        internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
17548                        break;
17549                    case LAYOUT_DIRECTION_LTR:
17550                    default:
17551                        mUserPaddingLeftInitial = padding.left;
17552                        mUserPaddingRightInitial = padding.right;
17553                        internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
17554                }
17555                mLeftPaddingDefined = false;
17556                mRightPaddingDefined = false;
17557            }
17558
17559            // Compare the minimum sizes of the old Drawable and the new.  If there isn't an old or
17560            // if it has a different minimum size, we should layout again
17561            if (mBackground == null
17562                    || mBackground.getMinimumHeight() != background.getMinimumHeight()
17563                    || mBackground.getMinimumWidth() != background.getMinimumWidth()) {
17564                requestLayout = true;
17565            }
17566
17567            background.setCallback(this);
17568            if (background.isStateful()) {
17569                background.setState(getDrawableState());
17570            }
17571            background.setVisible(getVisibility() == VISIBLE, false);
17572            mBackground = background;
17573
17574            applyBackgroundTint();
17575
17576            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17577                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17578                requestLayout = true;
17579            }
17580        } else {
17581            /* Remove the background */
17582            mBackground = null;
17583            if ((mViewFlags & WILL_NOT_DRAW) != 0
17584                    && (mForegroundInfo == null || mForegroundInfo.mDrawable == null)) {
17585                mPrivateFlags |= PFLAG_SKIP_DRAW;
17586            }
17587
17588            /*
17589             * When the background is set, we try to apply its padding to this
17590             * View. When the background is removed, we don't touch this View's
17591             * padding. This is noted in the Javadocs. Hence, we don't need to
17592             * requestLayout(), the invalidate() below is sufficient.
17593             */
17594
17595            // The old background's minimum size could have affected this
17596            // View's layout, so let's requestLayout
17597            requestLayout = true;
17598        }
17599
17600        computeOpaqueFlags();
17601
17602        if (requestLayout) {
17603            requestLayout();
17604        }
17605
17606        mBackgroundSizeChanged = true;
17607        invalidate(true);
17608    }
17609
17610    /**
17611     * Gets the background drawable
17612     *
17613     * @return The drawable used as the background for this view, if any.
17614     *
17615     * @see #setBackground(Drawable)
17616     *
17617     * @attr ref android.R.styleable#View_background
17618     */
17619    public Drawable getBackground() {
17620        return mBackground;
17621    }
17622
17623    /**
17624     * Applies a tint to the background drawable. Does not modify the current tint
17625     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17626     * <p>
17627     * Subsequent calls to {@link #setBackground(Drawable)} will automatically
17628     * mutate the drawable and apply the specified tint and tint mode using
17629     * {@link Drawable#setTintList(ColorStateList)}.
17630     *
17631     * @param tint the tint to apply, may be {@code null} to clear tint
17632     *
17633     * @attr ref android.R.styleable#View_backgroundTint
17634     * @see #getBackgroundTintList()
17635     * @see Drawable#setTintList(ColorStateList)
17636     */
17637    public void setBackgroundTintList(@Nullable ColorStateList tint) {
17638        if (mBackgroundTint == null) {
17639            mBackgroundTint = new TintInfo();
17640        }
17641        mBackgroundTint.mTintList = tint;
17642        mBackgroundTint.mHasTintList = true;
17643
17644        applyBackgroundTint();
17645    }
17646
17647    /**
17648     * Return the tint applied to the background drawable, if specified.
17649     *
17650     * @return the tint applied to the background drawable
17651     * @attr ref android.R.styleable#View_backgroundTint
17652     * @see #setBackgroundTintList(ColorStateList)
17653     */
17654    @Nullable
17655    public ColorStateList getBackgroundTintList() {
17656        return mBackgroundTint != null ? mBackgroundTint.mTintList : null;
17657    }
17658
17659    /**
17660     * Specifies the blending mode used to apply the tint specified by
17661     * {@link #setBackgroundTintList(ColorStateList)}} to the background
17662     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17663     *
17664     * @param tintMode the blending mode used to apply the tint, may be
17665     *                 {@code null} to clear tint
17666     * @attr ref android.R.styleable#View_backgroundTintMode
17667     * @see #getBackgroundTintMode()
17668     * @see Drawable#setTintMode(PorterDuff.Mode)
17669     */
17670    public void setBackgroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17671        if (mBackgroundTint == null) {
17672            mBackgroundTint = new TintInfo();
17673        }
17674        mBackgroundTint.mTintMode = tintMode;
17675        mBackgroundTint.mHasTintMode = true;
17676
17677        applyBackgroundTint();
17678    }
17679
17680    /**
17681     * Return the blending mode used to apply the tint to the background
17682     * drawable, if specified.
17683     *
17684     * @return the blending mode used to apply the tint to the background
17685     *         drawable
17686     * @attr ref android.R.styleable#View_backgroundTintMode
17687     * @see #setBackgroundTintMode(PorterDuff.Mode)
17688     */
17689    @Nullable
17690    public PorterDuff.Mode getBackgroundTintMode() {
17691        return mBackgroundTint != null ? mBackgroundTint.mTintMode : null;
17692    }
17693
17694    private void applyBackgroundTint() {
17695        if (mBackground != null && mBackgroundTint != null) {
17696            final TintInfo tintInfo = mBackgroundTint;
17697            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17698                mBackground = mBackground.mutate();
17699
17700                if (tintInfo.mHasTintList) {
17701                    mBackground.setTintList(tintInfo.mTintList);
17702                }
17703
17704                if (tintInfo.mHasTintMode) {
17705                    mBackground.setTintMode(tintInfo.mTintMode);
17706                }
17707
17708                // The drawable (or one of its children) may not have been
17709                // stateful before applying the tint, so let's try again.
17710                if (mBackground.isStateful()) {
17711                    mBackground.setState(getDrawableState());
17712                }
17713            }
17714        }
17715    }
17716
17717    /**
17718     * Returns the drawable used as the foreground of this View. The
17719     * foreground drawable, if non-null, is always drawn on top of the view's content.
17720     *
17721     * @return a Drawable or null if no foreground was set
17722     *
17723     * @see #onDrawForeground(Canvas)
17724     */
17725    public Drawable getForeground() {
17726        return mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17727    }
17728
17729    /**
17730     * Supply a Drawable that is to be rendered on top of all of the content in the view.
17731     *
17732     * @param foreground the Drawable to be drawn on top of the children
17733     *
17734     * @attr ref android.R.styleable#View_foreground
17735     */
17736    public void setForeground(Drawable foreground) {
17737        if (mForegroundInfo == null) {
17738            if (foreground == null) {
17739                // Nothing to do.
17740                return;
17741            }
17742            mForegroundInfo = new ForegroundInfo();
17743        }
17744
17745        if (foreground == mForegroundInfo.mDrawable) {
17746            // Nothing to do
17747            return;
17748        }
17749
17750        if (mForegroundInfo.mDrawable != null) {
17751            mForegroundInfo.mDrawable.setCallback(null);
17752            unscheduleDrawable(mForegroundInfo.mDrawable);
17753        }
17754
17755        mForegroundInfo.mDrawable = foreground;
17756        mForegroundInfo.mBoundsChanged = true;
17757        if (foreground != null) {
17758            if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
17759                mPrivateFlags &= ~PFLAG_SKIP_DRAW;
17760            }
17761            foreground.setCallback(this);
17762            foreground.setLayoutDirection(getLayoutDirection());
17763            if (foreground.isStateful()) {
17764                foreground.setState(getDrawableState());
17765            }
17766            applyForegroundTint();
17767        } else if ((mViewFlags & WILL_NOT_DRAW) != 0 && mBackground == null) {
17768            mPrivateFlags |= PFLAG_SKIP_DRAW;
17769        }
17770        requestLayout();
17771        invalidate();
17772    }
17773
17774    /**
17775     * Magic bit used to support features of framework-internal window decor implementation details.
17776     * This used to live exclusively in FrameLayout.
17777     *
17778     * @return true if the foreground should draw inside the padding region or false
17779     *         if it should draw inset by the view's padding
17780     * @hide internal use only; only used by FrameLayout and internal screen layouts.
17781     */
17782    public boolean isForegroundInsidePadding() {
17783        return mForegroundInfo != null ? mForegroundInfo.mInsidePadding : true;
17784    }
17785
17786    /**
17787     * Describes how the foreground is positioned.
17788     *
17789     * @return foreground gravity.
17790     *
17791     * @see #setForegroundGravity(int)
17792     *
17793     * @attr ref android.R.styleable#View_foregroundGravity
17794     */
17795    public int getForegroundGravity() {
17796        return mForegroundInfo != null ? mForegroundInfo.mGravity
17797                : Gravity.START | Gravity.TOP;
17798    }
17799
17800    /**
17801     * Describes how the foreground is positioned. Defaults to START and TOP.
17802     *
17803     * @param gravity see {@link android.view.Gravity}
17804     *
17805     * @see #getForegroundGravity()
17806     *
17807     * @attr ref android.R.styleable#View_foregroundGravity
17808     */
17809    public void setForegroundGravity(int gravity) {
17810        if (mForegroundInfo == null) {
17811            mForegroundInfo = new ForegroundInfo();
17812        }
17813
17814        if (mForegroundInfo.mGravity != gravity) {
17815            if ((gravity & Gravity.RELATIVE_HORIZONTAL_GRAVITY_MASK) == 0) {
17816                gravity |= Gravity.START;
17817            }
17818
17819            if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == 0) {
17820                gravity |= Gravity.TOP;
17821            }
17822
17823            mForegroundInfo.mGravity = gravity;
17824            requestLayout();
17825        }
17826    }
17827
17828    /**
17829     * Applies a tint to the foreground drawable. Does not modify the current tint
17830     * mode, which is {@link PorterDuff.Mode#SRC_IN} by default.
17831     * <p>
17832     * Subsequent calls to {@link #setForeground(Drawable)} will automatically
17833     * mutate the drawable and apply the specified tint and tint mode using
17834     * {@link Drawable#setTintList(ColorStateList)}.
17835     *
17836     * @param tint the tint to apply, may be {@code null} to clear tint
17837     *
17838     * @attr ref android.R.styleable#View_foregroundTint
17839     * @see #getForegroundTintList()
17840     * @see Drawable#setTintList(ColorStateList)
17841     */
17842    public void setForegroundTintList(@Nullable ColorStateList tint) {
17843        if (mForegroundInfo == null) {
17844            mForegroundInfo = new ForegroundInfo();
17845        }
17846        if (mForegroundInfo.mTintInfo == null) {
17847            mForegroundInfo.mTintInfo = new TintInfo();
17848        }
17849        mForegroundInfo.mTintInfo.mTintList = tint;
17850        mForegroundInfo.mTintInfo.mHasTintList = true;
17851
17852        applyForegroundTint();
17853    }
17854
17855    /**
17856     * Return the tint applied to the foreground drawable, if specified.
17857     *
17858     * @return the tint applied to the foreground drawable
17859     * @attr ref android.R.styleable#View_foregroundTint
17860     * @see #setForegroundTintList(ColorStateList)
17861     */
17862    @Nullable
17863    public ColorStateList getForegroundTintList() {
17864        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17865                ? mForegroundInfo.mTintInfo.mTintList : null;
17866    }
17867
17868    /**
17869     * Specifies the blending mode used to apply the tint specified by
17870     * {@link #setForegroundTintList(ColorStateList)}} to the background
17871     * drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
17872     *
17873     * @param tintMode the blending mode used to apply the tint, may be
17874     *                 {@code null} to clear tint
17875     * @attr ref android.R.styleable#View_foregroundTintMode
17876     * @see #getForegroundTintMode()
17877     * @see Drawable#setTintMode(PorterDuff.Mode)
17878     */
17879    public void setForegroundTintMode(@Nullable PorterDuff.Mode tintMode) {
17880        if (mForegroundInfo == null) {
17881            mForegroundInfo = new ForegroundInfo();
17882        }
17883        if (mForegroundInfo.mTintInfo == null) {
17884            mForegroundInfo.mTintInfo = new TintInfo();
17885        }
17886        mForegroundInfo.mTintInfo.mTintMode = tintMode;
17887        mForegroundInfo.mTintInfo.mHasTintMode = true;
17888
17889        applyForegroundTint();
17890    }
17891
17892    /**
17893     * Return the blending mode used to apply the tint to the foreground
17894     * drawable, if specified.
17895     *
17896     * @return the blending mode used to apply the tint to the foreground
17897     *         drawable
17898     * @attr ref android.R.styleable#View_foregroundTintMode
17899     * @see #setForegroundTintMode(PorterDuff.Mode)
17900     */
17901    @Nullable
17902    public PorterDuff.Mode getForegroundTintMode() {
17903        return mForegroundInfo != null && mForegroundInfo.mTintInfo != null
17904                ? mForegroundInfo.mTintInfo.mTintMode : null;
17905    }
17906
17907    private void applyForegroundTint() {
17908        if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
17909                && mForegroundInfo.mTintInfo != null) {
17910            final TintInfo tintInfo = mForegroundInfo.mTintInfo;
17911            if (tintInfo.mHasTintList || tintInfo.mHasTintMode) {
17912                mForegroundInfo.mDrawable = mForegroundInfo.mDrawable.mutate();
17913
17914                if (tintInfo.mHasTintList) {
17915                    mForegroundInfo.mDrawable.setTintList(tintInfo.mTintList);
17916                }
17917
17918                if (tintInfo.mHasTintMode) {
17919                    mForegroundInfo.mDrawable.setTintMode(tintInfo.mTintMode);
17920                }
17921
17922                // The drawable (or one of its children) may not have been
17923                // stateful before applying the tint, so let's try again.
17924                if (mForegroundInfo.mDrawable.isStateful()) {
17925                    mForegroundInfo.mDrawable.setState(getDrawableState());
17926                }
17927            }
17928        }
17929    }
17930
17931    /**
17932     * Draw any foreground content for this view.
17933     *
17934     * <p>Foreground content may consist of scroll bars, a {@link #setForeground foreground}
17935     * drawable or other view-specific decorations. The foreground is drawn on top of the
17936     * primary view content.</p>
17937     *
17938     * @param canvas canvas to draw into
17939     */
17940    public void onDrawForeground(Canvas canvas) {
17941        onDrawScrollIndicators(canvas);
17942        onDrawScrollBars(canvas);
17943
17944        final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
17945        if (foreground != null) {
17946            if (mForegroundInfo.mBoundsChanged) {
17947                mForegroundInfo.mBoundsChanged = false;
17948                final Rect selfBounds = mForegroundInfo.mSelfBounds;
17949                final Rect overlayBounds = mForegroundInfo.mOverlayBounds;
17950
17951                if (mForegroundInfo.mInsidePadding) {
17952                    selfBounds.set(0, 0, getWidth(), getHeight());
17953                } else {
17954                    selfBounds.set(getPaddingLeft(), getPaddingTop(),
17955                            getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());
17956                }
17957
17958                final int ld = getLayoutDirection();
17959                Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),
17960                        foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);
17961                foreground.setBounds(overlayBounds);
17962            }
17963
17964            foreground.draw(canvas);
17965        }
17966    }
17967
17968    /**
17969     * Sets the padding. The view may add on the space required to display
17970     * the scrollbars, depending on the style and visibility of the scrollbars.
17971     * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
17972     * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
17973     * from the values set in this call.
17974     *
17975     * @attr ref android.R.styleable#View_padding
17976     * @attr ref android.R.styleable#View_paddingBottom
17977     * @attr ref android.R.styleable#View_paddingLeft
17978     * @attr ref android.R.styleable#View_paddingRight
17979     * @attr ref android.R.styleable#View_paddingTop
17980     * @param left the left padding in pixels
17981     * @param top the top padding in pixels
17982     * @param right the right padding in pixels
17983     * @param bottom the bottom padding in pixels
17984     */
17985    public void setPadding(int left, int top, int right, int bottom) {
17986        resetResolvedPaddingInternal();
17987
17988        mUserPaddingStart = UNDEFINED_PADDING;
17989        mUserPaddingEnd = UNDEFINED_PADDING;
17990
17991        mUserPaddingLeftInitial = left;
17992        mUserPaddingRightInitial = right;
17993
17994        mLeftPaddingDefined = true;
17995        mRightPaddingDefined = true;
17996
17997        internalSetPadding(left, top, right, bottom);
17998    }
17999
18000    /**
18001     * @hide
18002     */
18003    protected void internalSetPadding(int left, int top, int right, int bottom) {
18004        mUserPaddingLeft = left;
18005        mUserPaddingRight = right;
18006        mUserPaddingBottom = bottom;
18007
18008        final int viewFlags = mViewFlags;
18009        boolean changed = false;
18010
18011        // Common case is there are no scroll bars.
18012        if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
18013            if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
18014                final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
18015                        ? 0 : getVerticalScrollbarWidth();
18016                switch (mVerticalScrollbarPosition) {
18017                    case SCROLLBAR_POSITION_DEFAULT:
18018                        if (isLayoutRtl()) {
18019                            left += offset;
18020                        } else {
18021                            right += offset;
18022                        }
18023                        break;
18024                    case SCROLLBAR_POSITION_RIGHT:
18025                        right += offset;
18026                        break;
18027                    case SCROLLBAR_POSITION_LEFT:
18028                        left += offset;
18029                        break;
18030                }
18031            }
18032            if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
18033                bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
18034                        ? 0 : getHorizontalScrollbarHeight();
18035            }
18036        }
18037
18038        if (mPaddingLeft != left) {
18039            changed = true;
18040            mPaddingLeft = left;
18041        }
18042        if (mPaddingTop != top) {
18043            changed = true;
18044            mPaddingTop = top;
18045        }
18046        if (mPaddingRight != right) {
18047            changed = true;
18048            mPaddingRight = right;
18049        }
18050        if (mPaddingBottom != bottom) {
18051            changed = true;
18052            mPaddingBottom = bottom;
18053        }
18054
18055        if (changed) {
18056            requestLayout();
18057            invalidateOutline();
18058        }
18059    }
18060
18061    /**
18062     * Sets the relative padding. The view may add on the space required to display
18063     * the scrollbars, depending on the style and visibility of the scrollbars.
18064     * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
18065     * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
18066     * from the values set in this call.
18067     *
18068     * @attr ref android.R.styleable#View_padding
18069     * @attr ref android.R.styleable#View_paddingBottom
18070     * @attr ref android.R.styleable#View_paddingStart
18071     * @attr ref android.R.styleable#View_paddingEnd
18072     * @attr ref android.R.styleable#View_paddingTop
18073     * @param start the start padding in pixels
18074     * @param top the top padding in pixels
18075     * @param end the end padding in pixels
18076     * @param bottom the bottom padding in pixels
18077     */
18078    public void setPaddingRelative(int start, int top, int end, int bottom) {
18079        resetResolvedPaddingInternal();
18080
18081        mUserPaddingStart = start;
18082        mUserPaddingEnd = end;
18083        mLeftPaddingDefined = true;
18084        mRightPaddingDefined = true;
18085
18086        switch(getLayoutDirection()) {
18087            case LAYOUT_DIRECTION_RTL:
18088                mUserPaddingLeftInitial = end;
18089                mUserPaddingRightInitial = start;
18090                internalSetPadding(end, top, start, bottom);
18091                break;
18092            case LAYOUT_DIRECTION_LTR:
18093            default:
18094                mUserPaddingLeftInitial = start;
18095                mUserPaddingRightInitial = end;
18096                internalSetPadding(start, top, end, bottom);
18097        }
18098    }
18099
18100    /**
18101     * Returns the top padding of this view.
18102     *
18103     * @return the top padding in pixels
18104     */
18105    public int getPaddingTop() {
18106        return mPaddingTop;
18107    }
18108
18109    /**
18110     * Returns the bottom padding of this view. If there are inset and enabled
18111     * scrollbars, this value may include the space required to display the
18112     * scrollbars as well.
18113     *
18114     * @return the bottom padding in pixels
18115     */
18116    public int getPaddingBottom() {
18117        return mPaddingBottom;
18118    }
18119
18120    /**
18121     * Returns the left padding of this view. If there are inset and enabled
18122     * scrollbars, this value may include the space required to display the
18123     * scrollbars as well.
18124     *
18125     * @return the left padding in pixels
18126     */
18127    public int getPaddingLeft() {
18128        if (!isPaddingResolved()) {
18129            resolvePadding();
18130        }
18131        return mPaddingLeft;
18132    }
18133
18134    /**
18135     * Returns the start padding of this view depending on its resolved layout direction.
18136     * If there are inset and enabled scrollbars, this value may include the space
18137     * required to display the scrollbars as well.
18138     *
18139     * @return the start padding in pixels
18140     */
18141    public int getPaddingStart() {
18142        if (!isPaddingResolved()) {
18143            resolvePadding();
18144        }
18145        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18146                mPaddingRight : mPaddingLeft;
18147    }
18148
18149    /**
18150     * Returns the right padding of this view. If there are inset and enabled
18151     * scrollbars, this value may include the space required to display the
18152     * scrollbars as well.
18153     *
18154     * @return the right padding in pixels
18155     */
18156    public int getPaddingRight() {
18157        if (!isPaddingResolved()) {
18158            resolvePadding();
18159        }
18160        return mPaddingRight;
18161    }
18162
18163    /**
18164     * Returns the end padding of this view depending on its resolved layout direction.
18165     * If there are inset and enabled scrollbars, this value may include the space
18166     * required to display the scrollbars as well.
18167     *
18168     * @return the end padding in pixels
18169     */
18170    public int getPaddingEnd() {
18171        if (!isPaddingResolved()) {
18172            resolvePadding();
18173        }
18174        return (getLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
18175                mPaddingLeft : mPaddingRight;
18176    }
18177
18178    /**
18179     * Return if the padding has been set through relative values
18180     * {@link #setPaddingRelative(int, int, int, int)} or through
18181     * @attr ref android.R.styleable#View_paddingStart or
18182     * @attr ref android.R.styleable#View_paddingEnd
18183     *
18184     * @return true if the padding is relative or false if it is not.
18185     */
18186    public boolean isPaddingRelative() {
18187        return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
18188    }
18189
18190    Insets computeOpticalInsets() {
18191        return (mBackground == null) ? Insets.NONE : mBackground.getOpticalInsets();
18192    }
18193
18194    /**
18195     * @hide
18196     */
18197    public void resetPaddingToInitialValues() {
18198        if (isRtlCompatibilityMode()) {
18199            mPaddingLeft = mUserPaddingLeftInitial;
18200            mPaddingRight = mUserPaddingRightInitial;
18201            return;
18202        }
18203        if (isLayoutRtl()) {
18204            mPaddingLeft = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingLeftInitial;
18205            mPaddingRight = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingRightInitial;
18206        } else {
18207            mPaddingLeft = (mUserPaddingStart >= 0) ? mUserPaddingStart : mUserPaddingLeftInitial;
18208            mPaddingRight = (mUserPaddingEnd >= 0) ? mUserPaddingEnd : mUserPaddingRightInitial;
18209        }
18210    }
18211
18212    /**
18213     * @hide
18214     */
18215    public Insets getOpticalInsets() {
18216        if (mLayoutInsets == null) {
18217            mLayoutInsets = computeOpticalInsets();
18218        }
18219        return mLayoutInsets;
18220    }
18221
18222    /**
18223     * Set this view's optical insets.
18224     *
18225     * <p>This method should be treated similarly to setMeasuredDimension and not as a general
18226     * property. Views that compute their own optical insets should call it as part of measurement.
18227     * This method does not request layout. If you are setting optical insets outside of
18228     * measure/layout itself you will want to call requestLayout() yourself.
18229     * </p>
18230     * @hide
18231     */
18232    public void setOpticalInsets(Insets insets) {
18233        mLayoutInsets = insets;
18234    }
18235
18236    /**
18237     * Changes the selection state of this view. A view can be selected or not.
18238     * Note that selection is not the same as focus. Views are typically
18239     * selected in the context of an AdapterView like ListView or GridView;
18240     * the selected view is the view that is highlighted.
18241     *
18242     * @param selected true if the view must be selected, false otherwise
18243     */
18244    public void setSelected(boolean selected) {
18245        //noinspection DoubleNegation
18246        if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
18247            mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
18248            if (!selected) resetPressedState();
18249            invalidate(true);
18250            refreshDrawableState();
18251            dispatchSetSelected(selected);
18252            if (selected) {
18253                sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
18254            } else {
18255                notifyViewAccessibilityStateChangedIfNeeded(
18256                        AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
18257            }
18258        }
18259    }
18260
18261    /**
18262     * Dispatch setSelected to all of this View's children.
18263     *
18264     * @see #setSelected(boolean)
18265     *
18266     * @param selected The new selected state
18267     */
18268    protected void dispatchSetSelected(boolean selected) {
18269    }
18270
18271    /**
18272     * Indicates the selection state of this view.
18273     *
18274     * @return true if the view is selected, false otherwise
18275     */
18276    @ViewDebug.ExportedProperty
18277    public boolean isSelected() {
18278        return (mPrivateFlags & PFLAG_SELECTED) != 0;
18279    }
18280
18281    /**
18282     * Changes the activated state of this view. A view can be activated or not.
18283     * Note that activation is not the same as selection.  Selection is
18284     * a transient property, representing the view (hierarchy) the user is
18285     * currently interacting with.  Activation is a longer-term state that the
18286     * user can move views in and out of.  For example, in a list view with
18287     * single or multiple selection enabled, the views in the current selection
18288     * set are activated.  (Um, yeah, we are deeply sorry about the terminology
18289     * here.)  The activated state is propagated down to children of the view it
18290     * is set on.
18291     *
18292     * @param activated true if the view must be activated, false otherwise
18293     */
18294    public void setActivated(boolean activated) {
18295        //noinspection DoubleNegation
18296        if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
18297            mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
18298            invalidate(true);
18299            refreshDrawableState();
18300            dispatchSetActivated(activated);
18301        }
18302    }
18303
18304    /**
18305     * Dispatch setActivated to all of this View's children.
18306     *
18307     * @see #setActivated(boolean)
18308     *
18309     * @param activated The new activated state
18310     */
18311    protected void dispatchSetActivated(boolean activated) {
18312    }
18313
18314    /**
18315     * Indicates the activation state of this view.
18316     *
18317     * @return true if the view is activated, false otherwise
18318     */
18319    @ViewDebug.ExportedProperty
18320    public boolean isActivated() {
18321        return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
18322    }
18323
18324    /**
18325     * Returns the ViewTreeObserver for this view's hierarchy. The view tree
18326     * observer can be used to get notifications when global events, like
18327     * layout, happen.
18328     *
18329     * The returned ViewTreeObserver observer is not guaranteed to remain
18330     * valid for the lifetime of this View. If the caller of this method keeps
18331     * a long-lived reference to ViewTreeObserver, it should always check for
18332     * the return value of {@link ViewTreeObserver#isAlive()}.
18333     *
18334     * @return The ViewTreeObserver for this view's hierarchy.
18335     */
18336    public ViewTreeObserver getViewTreeObserver() {
18337        if (mAttachInfo != null) {
18338            return mAttachInfo.mTreeObserver;
18339        }
18340        if (mFloatingTreeObserver == null) {
18341            mFloatingTreeObserver = new ViewTreeObserver();
18342        }
18343        return mFloatingTreeObserver;
18344    }
18345
18346    /**
18347     * <p>Finds the topmost view in the current view hierarchy.</p>
18348     *
18349     * @return the topmost view containing this view
18350     */
18351    public View getRootView() {
18352        if (mAttachInfo != null) {
18353            final View v = mAttachInfo.mRootView;
18354            if (v != null) {
18355                return v;
18356            }
18357        }
18358
18359        View parent = this;
18360
18361        while (parent.mParent != null && parent.mParent instanceof View) {
18362            parent = (View) parent.mParent;
18363        }
18364
18365        return parent;
18366    }
18367
18368    /**
18369     * Transforms a motion event from view-local coordinates to on-screen
18370     * coordinates.
18371     *
18372     * @param ev the view-local motion event
18373     * @return false if the transformation could not be applied
18374     * @hide
18375     */
18376    public boolean toGlobalMotionEvent(MotionEvent ev) {
18377        final AttachInfo info = mAttachInfo;
18378        if (info == null) {
18379            return false;
18380        }
18381
18382        final Matrix m = info.mTmpMatrix;
18383        m.set(Matrix.IDENTITY_MATRIX);
18384        transformMatrixToGlobal(m);
18385        ev.transform(m);
18386        return true;
18387    }
18388
18389    /**
18390     * Transforms a motion event from on-screen coordinates to view-local
18391     * coordinates.
18392     *
18393     * @param ev the on-screen motion event
18394     * @return false if the transformation could not be applied
18395     * @hide
18396     */
18397    public boolean toLocalMotionEvent(MotionEvent ev) {
18398        final AttachInfo info = mAttachInfo;
18399        if (info == null) {
18400            return false;
18401        }
18402
18403        final Matrix m = info.mTmpMatrix;
18404        m.set(Matrix.IDENTITY_MATRIX);
18405        transformMatrixToLocal(m);
18406        ev.transform(m);
18407        return true;
18408    }
18409
18410    /**
18411     * Modifies the input matrix such that it maps view-local coordinates to
18412     * on-screen coordinates.
18413     *
18414     * @param m input matrix to modify
18415     * @hide
18416     */
18417    public void transformMatrixToGlobal(Matrix m) {
18418        final ViewParent parent = mParent;
18419        if (parent instanceof View) {
18420            final View vp = (View) parent;
18421            vp.transformMatrixToGlobal(m);
18422            m.preTranslate(-vp.mScrollX, -vp.mScrollY);
18423        } else if (parent instanceof ViewRootImpl) {
18424            final ViewRootImpl vr = (ViewRootImpl) parent;
18425            vr.transformMatrixToGlobal(m);
18426            m.preTranslate(0, -vr.mCurScrollY);
18427        }
18428
18429        m.preTranslate(mLeft, mTop);
18430
18431        if (!hasIdentityMatrix()) {
18432            m.preConcat(getMatrix());
18433        }
18434    }
18435
18436    /**
18437     * Modifies the input matrix such that it maps on-screen coordinates to
18438     * view-local coordinates.
18439     *
18440     * @param m input matrix to modify
18441     * @hide
18442     */
18443    public void transformMatrixToLocal(Matrix m) {
18444        final ViewParent parent = mParent;
18445        if (parent instanceof View) {
18446            final View vp = (View) parent;
18447            vp.transformMatrixToLocal(m);
18448            m.postTranslate(vp.mScrollX, vp.mScrollY);
18449        } else if (parent instanceof ViewRootImpl) {
18450            final ViewRootImpl vr = (ViewRootImpl) parent;
18451            vr.transformMatrixToLocal(m);
18452            m.postTranslate(0, vr.mCurScrollY);
18453        }
18454
18455        m.postTranslate(-mLeft, -mTop);
18456
18457        if (!hasIdentityMatrix()) {
18458            m.postConcat(getInverseMatrix());
18459        }
18460    }
18461
18462    /**
18463     * @hide
18464     */
18465    @ViewDebug.ExportedProperty(category = "layout", indexMapping = {
18466            @ViewDebug.IntToString(from = 0, to = "x"),
18467            @ViewDebug.IntToString(from = 1, to = "y")
18468    })
18469    public int[] getLocationOnScreen() {
18470        int[] location = new int[2];
18471        getLocationOnScreen(location);
18472        return location;
18473    }
18474
18475    /**
18476     * <p>Computes the coordinates of this view on the screen. The argument
18477     * must be an array of two integers. After the method returns, the array
18478     * contains the x and y location in that order.</p>
18479     *
18480     * @param location an array of two integers in which to hold the coordinates
18481     */
18482    public void getLocationOnScreen(@Size(2) int[] location) {
18483        getLocationInWindow(location);
18484
18485        final AttachInfo info = mAttachInfo;
18486        if (info != null) {
18487            location[0] += info.mWindowLeft;
18488            location[1] += info.mWindowTop;
18489        }
18490    }
18491
18492    /**
18493     * <p>Computes the coordinates of this view in its window. The argument
18494     * must be an array of two integers. After the method returns, the array
18495     * contains the x and y location in that order.</p>
18496     *
18497     * @param outWindowSpace an array of two integers in which to hold the coordinates
18498     */
18499    public void getLocationInWindow(@Size(2) int[] outWindowSpace) {
18500        outWindowSpace[0] = 0;
18501        outWindowSpace[1] = 0;
18502
18503        transformFromViewToWindowSpace(outWindowSpace);
18504    }
18505
18506    void transformFromViewToWindowSpace(@Size(2) int[] inOutLocation) {
18507        if (inOutLocation == null || inOutLocation.length < 2) {
18508            throw new IllegalArgumentException("inOutLocation must be an array of two integers");
18509        }
18510
18511        if (mAttachInfo == null) {
18512            // When the view is not attached to a window, this method does not make sense
18513            inOutLocation[0] = inOutLocation[1] = 0;
18514            return;
18515        }
18516
18517        float position[] = mAttachInfo.mTmpTransformLocation;
18518        position[0] = inOutLocation[0];
18519        position[1] = inOutLocation[1];
18520
18521        if (!hasIdentityMatrix()) {
18522            getMatrix().mapPoints(position);
18523        }
18524
18525        position[0] += mLeft;
18526        position[1] += mTop;
18527
18528        ViewParent viewParent = mParent;
18529        while (viewParent instanceof View) {
18530            final View view = (View) viewParent;
18531
18532            position[0] -= view.mScrollX;
18533            position[1] -= view.mScrollY;
18534
18535            if (!view.hasIdentityMatrix()) {
18536                view.getMatrix().mapPoints(position);
18537            }
18538
18539            position[0] += view.mLeft;
18540            position[1] += view.mTop;
18541
18542            viewParent = view.mParent;
18543         }
18544
18545        if (viewParent instanceof ViewRootImpl) {
18546            // *cough*
18547            final ViewRootImpl vr = (ViewRootImpl) viewParent;
18548            position[1] -= vr.mCurScrollY;
18549        }
18550
18551        inOutLocation[0] = Math.round(position[0]);
18552        inOutLocation[1] = Math.round(position[1]);
18553    }
18554
18555    /**
18556     * {@hide}
18557     * @param id the id of the view to be found
18558     * @return the view of the specified id, null if cannot be found
18559     */
18560    protected View findViewTraversal(@IdRes int id) {
18561        if (id == mID) {
18562            return this;
18563        }
18564        return null;
18565    }
18566
18567    /**
18568     * {@hide}
18569     * @param tag the tag of the view to be found
18570     * @return the view of specified tag, null if cannot be found
18571     */
18572    protected View findViewWithTagTraversal(Object tag) {
18573        if (tag != null && tag.equals(mTag)) {
18574            return this;
18575        }
18576        return null;
18577    }
18578
18579    /**
18580     * {@hide}
18581     * @param predicate The predicate to evaluate.
18582     * @param childToSkip If not null, ignores this child during the recursive traversal.
18583     * @return The first view that matches the predicate or null.
18584     */
18585    protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
18586        if (predicate.apply(this)) {
18587            return this;
18588        }
18589        return null;
18590    }
18591
18592    /**
18593     * Look for a child view with the given id.  If this view has the given
18594     * id, return this view.
18595     *
18596     * @param id The id to search for.
18597     * @return The view that has the given id in the hierarchy or null
18598     */
18599    @Nullable
18600    public final View findViewById(@IdRes int id) {
18601        if (id < 0) {
18602            return null;
18603        }
18604        return findViewTraversal(id);
18605    }
18606
18607    /**
18608     * Finds a view by its unuque and stable accessibility id.
18609     *
18610     * @param accessibilityId The searched accessibility id.
18611     * @return The found view.
18612     */
18613    final View findViewByAccessibilityId(int accessibilityId) {
18614        if (accessibilityId < 0) {
18615            return null;
18616        }
18617        View view = findViewByAccessibilityIdTraversal(accessibilityId);
18618        if (view != null) {
18619            return view.includeForAccessibility() ? view : null;
18620        }
18621        return null;
18622    }
18623
18624    /**
18625     * Performs the traversal to find a view by its unuque and stable accessibility id.
18626     *
18627     * <strong>Note:</strong>This method does not stop at the root namespace
18628     * boundary since the user can touch the screen at an arbitrary location
18629     * potentially crossing the root namespace bounday which will send an
18630     * accessibility event to accessibility services and they should be able
18631     * to obtain the event source. Also accessibility ids are guaranteed to be
18632     * unique in the window.
18633     *
18634     * @param accessibilityId The accessibility id.
18635     * @return The found view.
18636     *
18637     * @hide
18638     */
18639    public View findViewByAccessibilityIdTraversal(int accessibilityId) {
18640        if (getAccessibilityViewId() == accessibilityId) {
18641            return this;
18642        }
18643        return null;
18644    }
18645
18646    /**
18647     * Look for a child view with the given tag.  If this view has the given
18648     * tag, return this view.
18649     *
18650     * @param tag The tag to search for, using "tag.equals(getTag())".
18651     * @return The View that has the given tag in the hierarchy or null
18652     */
18653    public final View findViewWithTag(Object tag) {
18654        if (tag == null) {
18655            return null;
18656        }
18657        return findViewWithTagTraversal(tag);
18658    }
18659
18660    /**
18661     * {@hide}
18662     * Look for a child view that matches the specified predicate.
18663     * If this view matches the predicate, return this view.
18664     *
18665     * @param predicate The predicate to evaluate.
18666     * @return The first view that matches the predicate or null.
18667     */
18668    public final View findViewByPredicate(Predicate<View> predicate) {
18669        return findViewByPredicateTraversal(predicate, null);
18670    }
18671
18672    /**
18673     * {@hide}
18674     * Look for a child view that matches the specified predicate,
18675     * starting with the specified view and its descendents and then
18676     * recusively searching the ancestors and siblings of that view
18677     * until this view is reached.
18678     *
18679     * This method is useful in cases where the predicate does not match
18680     * a single unique view (perhaps multiple views use the same id)
18681     * and we are trying to find the view that is "closest" in scope to the
18682     * starting view.
18683     *
18684     * @param start The view to start from.
18685     * @param predicate The predicate to evaluate.
18686     * @return The first view that matches the predicate or null.
18687     */
18688    public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
18689        View childToSkip = null;
18690        for (;;) {
18691            View view = start.findViewByPredicateTraversal(predicate, childToSkip);
18692            if (view != null || start == this) {
18693                return view;
18694            }
18695
18696            ViewParent parent = start.getParent();
18697            if (parent == null || !(parent instanceof View)) {
18698                return null;
18699            }
18700
18701            childToSkip = start;
18702            start = (View) parent;
18703        }
18704    }
18705
18706    /**
18707     * Sets the identifier for this view. The identifier does not have to be
18708     * unique in this view's hierarchy. The identifier should be a positive
18709     * number.
18710     *
18711     * @see #NO_ID
18712     * @see #getId()
18713     * @see #findViewById(int)
18714     *
18715     * @param id a number used to identify the view
18716     *
18717     * @attr ref android.R.styleable#View_id
18718     */
18719    public void setId(@IdRes int id) {
18720        mID = id;
18721        if (mID == View.NO_ID && mLabelForId != View.NO_ID) {
18722            mID = generateViewId();
18723        }
18724    }
18725
18726    /**
18727     * {@hide}
18728     *
18729     * @param isRoot true if the view belongs to the root namespace, false
18730     *        otherwise
18731     */
18732    public void setIsRootNamespace(boolean isRoot) {
18733        if (isRoot) {
18734            mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
18735        } else {
18736            mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
18737        }
18738    }
18739
18740    /**
18741     * {@hide}
18742     *
18743     * @return true if the view belongs to the root namespace, false otherwise
18744     */
18745    public boolean isRootNamespace() {
18746        return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
18747    }
18748
18749    /**
18750     * Returns this view's identifier.
18751     *
18752     * @return a positive integer used to identify the view or {@link #NO_ID}
18753     *         if the view has no ID
18754     *
18755     * @see #setId(int)
18756     * @see #findViewById(int)
18757     * @attr ref android.R.styleable#View_id
18758     */
18759    @IdRes
18760    @ViewDebug.CapturedViewProperty
18761    public int getId() {
18762        return mID;
18763    }
18764
18765    /**
18766     * Returns this view's tag.
18767     *
18768     * @return the Object stored in this view as a tag, or {@code null} if not
18769     *         set
18770     *
18771     * @see #setTag(Object)
18772     * @see #getTag(int)
18773     */
18774    @ViewDebug.ExportedProperty
18775    public Object getTag() {
18776        return mTag;
18777    }
18778
18779    /**
18780     * Sets the tag associated with this view. A tag can be used to mark
18781     * a view in its hierarchy and does not have to be unique within the
18782     * hierarchy. Tags can also be used to store data within a view without
18783     * resorting to another data structure.
18784     *
18785     * @param tag an Object to tag the view with
18786     *
18787     * @see #getTag()
18788     * @see #setTag(int, Object)
18789     */
18790    public void setTag(final Object tag) {
18791        mTag = tag;
18792    }
18793
18794    /**
18795     * Returns the tag associated with this view and the specified key.
18796     *
18797     * @param key The key identifying the tag
18798     *
18799     * @return the Object stored in this view as a tag, or {@code null} if not
18800     *         set
18801     *
18802     * @see #setTag(int, Object)
18803     * @see #getTag()
18804     */
18805    public Object getTag(int key) {
18806        if (mKeyedTags != null) return mKeyedTags.get(key);
18807        return null;
18808    }
18809
18810    /**
18811     * Sets a tag associated with this view and a key. A tag can be used
18812     * to mark a view in its hierarchy and does not have to be unique within
18813     * the hierarchy. Tags can also be used to store data within a view
18814     * without resorting to another data structure.
18815     *
18816     * The specified key should be an id declared in the resources of the
18817     * application to ensure it is unique (see the <a
18818     * href="{@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
18819     * Keys identified as belonging to
18820     * the Android framework or not associated with any package will cause
18821     * an {@link IllegalArgumentException} to be thrown.
18822     *
18823     * @param key The key identifying the tag
18824     * @param tag An Object to tag the view with
18825     *
18826     * @throws IllegalArgumentException If they specified key is not valid
18827     *
18828     * @see #setTag(Object)
18829     * @see #getTag(int)
18830     */
18831    public void setTag(int key, final Object tag) {
18832        // If the package id is 0x00 or 0x01, it's either an undefined package
18833        // or a framework id
18834        if ((key >>> 24) < 2) {
18835            throw new IllegalArgumentException("The key must be an application-specific "
18836                    + "resource id.");
18837        }
18838
18839        setKeyedTag(key, tag);
18840    }
18841
18842    /**
18843     * Variation of {@link #setTag(int, Object)} that enforces the key to be a
18844     * framework id.
18845     *
18846     * @hide
18847     */
18848    public void setTagInternal(int key, Object tag) {
18849        if ((key >>> 24) != 0x1) {
18850            throw new IllegalArgumentException("The key must be a framework-specific "
18851                    + "resource id.");
18852        }
18853
18854        setKeyedTag(key, tag);
18855    }
18856
18857    private void setKeyedTag(int key, Object tag) {
18858        if (mKeyedTags == null) {
18859            mKeyedTags = new SparseArray<Object>(2);
18860        }
18861
18862        mKeyedTags.put(key, tag);
18863    }
18864
18865    /**
18866     * Prints information about this view in the log output, with the tag
18867     * {@link #VIEW_LOG_TAG}.
18868     *
18869     * @hide
18870     */
18871    public void debug() {
18872        debug(0);
18873    }
18874
18875    /**
18876     * Prints information about this view in the log output, with the tag
18877     * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
18878     * indentation defined by the <code>depth</code>.
18879     *
18880     * @param depth the indentation level
18881     *
18882     * @hide
18883     */
18884    protected void debug(int depth) {
18885        String output = debugIndent(depth - 1);
18886
18887        output += "+ " + this;
18888        int id = getId();
18889        if (id != -1) {
18890            output += " (id=" + id + ")";
18891        }
18892        Object tag = getTag();
18893        if (tag != null) {
18894            output += " (tag=" + tag + ")";
18895        }
18896        Log.d(VIEW_LOG_TAG, output);
18897
18898        if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
18899            output = debugIndent(depth) + " FOCUSED";
18900            Log.d(VIEW_LOG_TAG, output);
18901        }
18902
18903        output = debugIndent(depth);
18904        output += "frame={" + mLeft + ", " + mTop + ", " + mRight
18905                + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
18906                + "} ";
18907        Log.d(VIEW_LOG_TAG, output);
18908
18909        if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
18910                || mPaddingBottom != 0) {
18911            output = debugIndent(depth);
18912            output += "padding={" + mPaddingLeft + ", " + mPaddingTop
18913                    + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
18914            Log.d(VIEW_LOG_TAG, output);
18915        }
18916
18917        output = debugIndent(depth);
18918        output += "mMeasureWidth=" + mMeasuredWidth +
18919                " mMeasureHeight=" + mMeasuredHeight;
18920        Log.d(VIEW_LOG_TAG, output);
18921
18922        output = debugIndent(depth);
18923        if (mLayoutParams == null) {
18924            output += "BAD! no layout params";
18925        } else {
18926            output = mLayoutParams.debug(output);
18927        }
18928        Log.d(VIEW_LOG_TAG, output);
18929
18930        output = debugIndent(depth);
18931        output += "flags={";
18932        output += View.printFlags(mViewFlags);
18933        output += "}";
18934        Log.d(VIEW_LOG_TAG, output);
18935
18936        output = debugIndent(depth);
18937        output += "privateFlags={";
18938        output += View.printPrivateFlags(mPrivateFlags);
18939        output += "}";
18940        Log.d(VIEW_LOG_TAG, output);
18941    }
18942
18943    /**
18944     * Creates a string of whitespaces used for indentation.
18945     *
18946     * @param depth the indentation level
18947     * @return a String containing (depth * 2 + 3) * 2 white spaces
18948     *
18949     * @hide
18950     */
18951    protected static String debugIndent(int depth) {
18952        StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
18953        for (int i = 0; i < (depth * 2) + 3; i++) {
18954            spaces.append(' ').append(' ');
18955        }
18956        return spaces.toString();
18957    }
18958
18959    /**
18960     * <p>Return the offset of the widget's text baseline from the widget's top
18961     * boundary. If this widget does not support baseline alignment, this
18962     * method returns -1. </p>
18963     *
18964     * @return the offset of the baseline within the widget's bounds or -1
18965     *         if baseline alignment is not supported
18966     */
18967    @ViewDebug.ExportedProperty(category = "layout")
18968    public int getBaseline() {
18969        return -1;
18970    }
18971
18972    /**
18973     * Returns whether the view hierarchy is currently undergoing a layout pass. This
18974     * information is useful to avoid situations such as calling {@link #requestLayout()} during
18975     * a layout pass.
18976     *
18977     * @return whether the view hierarchy is currently undergoing a layout pass
18978     */
18979    public boolean isInLayout() {
18980        ViewRootImpl viewRoot = getViewRootImpl();
18981        return (viewRoot != null && viewRoot.isInLayout());
18982    }
18983
18984    /**
18985     * Call this when something has changed which has invalidated the
18986     * layout of this view. This will schedule a layout pass of the view
18987     * tree. This should not be called while the view hierarchy is currently in a layout
18988     * pass ({@link #isInLayout()}. If layout is happening, the request may be honored at the
18989     * end of the current layout pass (and then layout will run again) or after the current
18990     * frame is drawn and the next layout occurs.
18991     *
18992     * <p>Subclasses which override this method should call the superclass method to
18993     * handle possible request-during-layout errors correctly.</p>
18994     */
18995    @CallSuper
18996    public void requestLayout() {
18997        if (mMeasureCache != null) mMeasureCache.clear();
18998
18999        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == null) {
19000            // Only trigger request-during-layout logic if this is the view requesting it,
19001            // not the views in its parent hierarchy
19002            ViewRootImpl viewRoot = getViewRootImpl();
19003            if (viewRoot != null && viewRoot.isInLayout()) {
19004                if (!viewRoot.requestLayoutDuringLayout(this)) {
19005                    return;
19006                }
19007            }
19008            mAttachInfo.mViewRequestingLayout = this;
19009        }
19010
19011        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19012        mPrivateFlags |= PFLAG_INVALIDATED;
19013
19014        if (mParent != null && !mParent.isLayoutRequested()) {
19015            mParent.requestLayout();
19016        }
19017        if (mAttachInfo != null && mAttachInfo.mViewRequestingLayout == this) {
19018            mAttachInfo.mViewRequestingLayout = null;
19019        }
19020    }
19021
19022    /**
19023     * Forces this view to be laid out during the next layout pass.
19024     * This method does not call requestLayout() or forceLayout()
19025     * on the parent.
19026     */
19027    public void forceLayout() {
19028        if (mMeasureCache != null) mMeasureCache.clear();
19029
19030        mPrivateFlags |= PFLAG_FORCE_LAYOUT;
19031        mPrivateFlags |= PFLAG_INVALIDATED;
19032    }
19033
19034    /**
19035     * <p>
19036     * This is called to find out how big a view should be. The parent
19037     * supplies constraint information in the width and height parameters.
19038     * </p>
19039     *
19040     * <p>
19041     * The actual measurement work of a view is performed in
19042     * {@link #onMeasure(int, int)}, called by this method. Therefore, only
19043     * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
19044     * </p>
19045     *
19046     *
19047     * @param widthMeasureSpec Horizontal space requirements as imposed by the
19048     *        parent
19049     * @param heightMeasureSpec Vertical space requirements as imposed by the
19050     *        parent
19051     *
19052     * @see #onMeasure(int, int)
19053     */
19054    public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
19055        boolean optical = isLayoutModeOptical(this);
19056        if (optical != isLayoutModeOptical(mParent)) {
19057            Insets insets = getOpticalInsets();
19058            int oWidth  = insets.left + insets.right;
19059            int oHeight = insets.top  + insets.bottom;
19060            widthMeasureSpec  = MeasureSpec.adjust(widthMeasureSpec,  optical ? -oWidth  : oWidth);
19061            heightMeasureSpec = MeasureSpec.adjust(heightMeasureSpec, optical ? -oHeight : oHeight);
19062        }
19063
19064        // Suppress sign extension for the low bytes
19065        long key = (long) widthMeasureSpec << 32 | (long) heightMeasureSpec & 0xffffffffL;
19066        if (mMeasureCache == null) mMeasureCache = new LongSparseLongArray(2);
19067
19068        final boolean forceLayout = (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
19069
19070        // Optimize layout by avoiding an extra EXACTLY pass when the view is
19071        // already measured as the correct size. In API 23 and below, this
19072        // extra pass is required to make LinearLayout re-distribute weight.
19073        final boolean specChanged = widthMeasureSpec != mOldWidthMeasureSpec
19074                || heightMeasureSpec != mOldHeightMeasureSpec;
19075        final boolean isSpecExactly = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY
19076                && MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY;
19077        final boolean matchesSpecSize = getMeasuredWidth() == MeasureSpec.getSize(widthMeasureSpec)
19078                && getMeasuredHeight() == MeasureSpec.getSize(heightMeasureSpec);
19079        final boolean needsLayout = specChanged
19080                && (sAlwaysRemeasureExactly || !isSpecExactly || !matchesSpecSize);
19081
19082        if (forceLayout || needsLayout) {
19083            // first clears the measured dimension flag
19084            mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
19085
19086            resolveRtlPropertiesIfNeeded();
19087
19088            int cacheIndex = forceLayout ? -1 : mMeasureCache.indexOfKey(key);
19089            if (cacheIndex < 0 || sIgnoreMeasureCache) {
19090                // measure ourselves, this should set the measured dimension flag back
19091                onMeasure(widthMeasureSpec, heightMeasureSpec);
19092                mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19093            } else {
19094                long value = mMeasureCache.valueAt(cacheIndex);
19095                // Casting a long to int drops the high 32 bits, no mask needed
19096                setMeasuredDimensionRaw((int) (value >> 32), (int) value);
19097                mPrivateFlags3 |= PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
19098            }
19099
19100            // flag not set, setMeasuredDimension() was not invoked, we raise
19101            // an exception to warn the developer
19102            if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
19103                throw new IllegalStateException("View with id " + getId() + ": "
19104                        + getClass().getName() + "#onMeasure() did not set the"
19105                        + " measured dimension by calling"
19106                        + " setMeasuredDimension()");
19107            }
19108
19109            mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
19110        }
19111
19112        mOldWidthMeasureSpec = widthMeasureSpec;
19113        mOldHeightMeasureSpec = heightMeasureSpec;
19114
19115        mMeasureCache.put(key, ((long) mMeasuredWidth) << 32 |
19116                (long) mMeasuredHeight & 0xffffffffL); // suppress sign extension
19117    }
19118
19119    /**
19120     * <p>
19121     * Measure the view and its content to determine the measured width and the
19122     * measured height. This method is invoked by {@link #measure(int, int)} and
19123     * should be overridden by subclasses to provide accurate and efficient
19124     * measurement of their contents.
19125     * </p>
19126     *
19127     * <p>
19128     * <strong>CONTRACT:</strong> When overriding this method, you
19129     * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
19130     * measured width and height of this view. Failure to do so will trigger an
19131     * <code>IllegalStateException</code>, thrown by
19132     * {@link #measure(int, int)}. Calling the superclass'
19133     * {@link #onMeasure(int, int)} is a valid use.
19134     * </p>
19135     *
19136     * <p>
19137     * The base class implementation of measure defaults to the background size,
19138     * unless a larger size is allowed by the MeasureSpec. Subclasses should
19139     * override {@link #onMeasure(int, int)} to provide better measurements of
19140     * their content.
19141     * </p>
19142     *
19143     * <p>
19144     * If this method is overridden, it is the subclass's responsibility to make
19145     * sure the measured height and width are at least the view's minimum height
19146     * and width ({@link #getSuggestedMinimumHeight()} and
19147     * {@link #getSuggestedMinimumWidth()}).
19148     * </p>
19149     *
19150     * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
19151     *                         The requirements are encoded with
19152     *                         {@link android.view.View.MeasureSpec}.
19153     * @param heightMeasureSpec vertical space requirements as imposed by the parent.
19154     *                         The requirements are encoded with
19155     *                         {@link android.view.View.MeasureSpec}.
19156     *
19157     * @see #getMeasuredWidth()
19158     * @see #getMeasuredHeight()
19159     * @see #setMeasuredDimension(int, int)
19160     * @see #getSuggestedMinimumHeight()
19161     * @see #getSuggestedMinimumWidth()
19162     * @see android.view.View.MeasureSpec#getMode(int)
19163     * @see android.view.View.MeasureSpec#getSize(int)
19164     */
19165    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
19166        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
19167                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
19168    }
19169
19170    /**
19171     * <p>This method must be called by {@link #onMeasure(int, int)} to store the
19172     * measured width and measured height. Failing to do so will trigger an
19173     * exception at measurement time.</p>
19174     *
19175     * @param measuredWidth The measured width of this view.  May be a complex
19176     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19177     * {@link #MEASURED_STATE_TOO_SMALL}.
19178     * @param measuredHeight The measured height of this view.  May be a complex
19179     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19180     * {@link #MEASURED_STATE_TOO_SMALL}.
19181     */
19182    protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
19183        boolean optical = isLayoutModeOptical(this);
19184        if (optical != isLayoutModeOptical(mParent)) {
19185            Insets insets = getOpticalInsets();
19186            int opticalWidth  = insets.left + insets.right;
19187            int opticalHeight = insets.top  + insets.bottom;
19188
19189            measuredWidth  += optical ? opticalWidth  : -opticalWidth;
19190            measuredHeight += optical ? opticalHeight : -opticalHeight;
19191        }
19192        setMeasuredDimensionRaw(measuredWidth, measuredHeight);
19193    }
19194
19195    /**
19196     * Sets the measured dimension without extra processing for things like optical bounds.
19197     * Useful for reapplying consistent values that have already been cooked with adjustments
19198     * for optical bounds, etc. such as those from the measurement cache.
19199     *
19200     * @param measuredWidth The measured width of this view.  May be a complex
19201     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19202     * {@link #MEASURED_STATE_TOO_SMALL}.
19203     * @param measuredHeight The measured height of this view.  May be a complex
19204     * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
19205     * {@link #MEASURED_STATE_TOO_SMALL}.
19206     */
19207    private void setMeasuredDimensionRaw(int measuredWidth, int measuredHeight) {
19208        mMeasuredWidth = measuredWidth;
19209        mMeasuredHeight = measuredHeight;
19210
19211        mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
19212    }
19213
19214    /**
19215     * Merge two states as returned by {@link #getMeasuredState()}.
19216     * @param curState The current state as returned from a view or the result
19217     * of combining multiple views.
19218     * @param newState The new view state to combine.
19219     * @return Returns a new integer reflecting the combination of the two
19220     * states.
19221     */
19222    public static int combineMeasuredStates(int curState, int newState) {
19223        return curState | newState;
19224    }
19225
19226    /**
19227     * Version of {@link #resolveSizeAndState(int, int, int)}
19228     * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
19229     */
19230    public static int resolveSize(int size, int measureSpec) {
19231        return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
19232    }
19233
19234    /**
19235     * Utility to reconcile a desired size and state, with constraints imposed
19236     * by a MeasureSpec. Will take the desired size, unless a different size
19237     * is imposed by the constraints. The returned value is a compound integer,
19238     * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
19239     * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the
19240     * resulting size is smaller than the size the view wants to be.
19241     *
19242     * @param size How big the view wants to be.
19243     * @param measureSpec Constraints imposed by the parent.
19244     * @param childMeasuredState Size information bit mask for the view's
19245     *                           children.
19246     * @return Size information bit mask as defined by
19247     *         {@link #MEASURED_SIZE_MASK} and
19248     *         {@link #MEASURED_STATE_TOO_SMALL}.
19249     */
19250    public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
19251        final int specMode = MeasureSpec.getMode(measureSpec);
19252        final int specSize = MeasureSpec.getSize(measureSpec);
19253        final int result;
19254        switch (specMode) {
19255            case MeasureSpec.AT_MOST:
19256                if (specSize < size) {
19257                    result = specSize | MEASURED_STATE_TOO_SMALL;
19258                } else {
19259                    result = size;
19260                }
19261                break;
19262            case MeasureSpec.EXACTLY:
19263                result = specSize;
19264                break;
19265            case MeasureSpec.UNSPECIFIED:
19266            default:
19267                result = size;
19268        }
19269        return result | (childMeasuredState & MEASURED_STATE_MASK);
19270    }
19271
19272    /**
19273     * Utility to return a default size. Uses the supplied size if the
19274     * MeasureSpec imposed no constraints. Will get larger if allowed
19275     * by the MeasureSpec.
19276     *
19277     * @param size Default size for this view
19278     * @param measureSpec Constraints imposed by the parent
19279     * @return The size this view should be.
19280     */
19281    public static int getDefaultSize(int size, int measureSpec) {
19282        int result = size;
19283        int specMode = MeasureSpec.getMode(measureSpec);
19284        int specSize = MeasureSpec.getSize(measureSpec);
19285
19286        switch (specMode) {
19287        case MeasureSpec.UNSPECIFIED:
19288            result = size;
19289            break;
19290        case MeasureSpec.AT_MOST:
19291        case MeasureSpec.EXACTLY:
19292            result = specSize;
19293            break;
19294        }
19295        return result;
19296    }
19297
19298    /**
19299     * Returns the suggested minimum height that the view should use. This
19300     * returns the maximum of the view's minimum height
19301     * and the background's minimum height
19302     * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
19303     * <p>
19304     * When being used in {@link #onMeasure(int, int)}, the caller should still
19305     * ensure the returned height is within the requirements of the parent.
19306     *
19307     * @return The suggested minimum height of the view.
19308     */
19309    protected int getSuggestedMinimumHeight() {
19310        return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
19311
19312    }
19313
19314    /**
19315     * Returns the suggested minimum width that the view should use. This
19316     * returns the maximum of the view's minimum width
19317     * and the background's minimum width
19318     *  ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
19319     * <p>
19320     * When being used in {@link #onMeasure(int, int)}, the caller should still
19321     * ensure the returned width is within the requirements of the parent.
19322     *
19323     * @return The suggested minimum width of the view.
19324     */
19325    protected int getSuggestedMinimumWidth() {
19326        return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
19327    }
19328
19329    /**
19330     * Returns the minimum height of the view.
19331     *
19332     * @return the minimum height the view will try to be.
19333     *
19334     * @see #setMinimumHeight(int)
19335     *
19336     * @attr ref android.R.styleable#View_minHeight
19337     */
19338    public int getMinimumHeight() {
19339        return mMinHeight;
19340    }
19341
19342    /**
19343     * Sets the minimum height of the view. It is not guaranteed the view will
19344     * be able to achieve this minimum height (for example, if its parent layout
19345     * constrains it with less available height).
19346     *
19347     * @param minHeight The minimum height the view will try to be.
19348     *
19349     * @see #getMinimumHeight()
19350     *
19351     * @attr ref android.R.styleable#View_minHeight
19352     */
19353    public void setMinimumHeight(int minHeight) {
19354        mMinHeight = minHeight;
19355        requestLayout();
19356    }
19357
19358    /**
19359     * Returns the minimum width of the view.
19360     *
19361     * @return the minimum width the view will try to be.
19362     *
19363     * @see #setMinimumWidth(int)
19364     *
19365     * @attr ref android.R.styleable#View_minWidth
19366     */
19367    public int getMinimumWidth() {
19368        return mMinWidth;
19369    }
19370
19371    /**
19372     * Sets the minimum width of the view. It is not guaranteed the view will
19373     * be able to achieve this minimum width (for example, if its parent layout
19374     * constrains it with less available width).
19375     *
19376     * @param minWidth The minimum width the view will try to be.
19377     *
19378     * @see #getMinimumWidth()
19379     *
19380     * @attr ref android.R.styleable#View_minWidth
19381     */
19382    public void setMinimumWidth(int minWidth) {
19383        mMinWidth = minWidth;
19384        requestLayout();
19385
19386    }
19387
19388    /**
19389     * Get the animation currently associated with this view.
19390     *
19391     * @return The animation that is currently playing or
19392     *         scheduled to play for this view.
19393     */
19394    public Animation getAnimation() {
19395        return mCurrentAnimation;
19396    }
19397
19398    /**
19399     * Start the specified animation now.
19400     *
19401     * @param animation the animation to start now
19402     */
19403    public void startAnimation(Animation animation) {
19404        animation.setStartTime(Animation.START_ON_FIRST_FRAME);
19405        setAnimation(animation);
19406        invalidateParentCaches();
19407        invalidate(true);
19408    }
19409
19410    /**
19411     * Cancels any animations for this view.
19412     */
19413    public void clearAnimation() {
19414        if (mCurrentAnimation != null) {
19415            mCurrentAnimation.detach();
19416        }
19417        mCurrentAnimation = null;
19418        invalidateParentIfNeeded();
19419    }
19420
19421    /**
19422     * Sets the next animation to play for this view.
19423     * If you want the animation to play immediately, use
19424     * {@link #startAnimation(android.view.animation.Animation)} instead.
19425     * This method provides allows fine-grained
19426     * control over the start time and invalidation, but you
19427     * must make sure that 1) the animation has a start time set, and
19428     * 2) the view's parent (which controls animations on its children)
19429     * will be invalidated when the animation is supposed to
19430     * start.
19431     *
19432     * @param animation The next animation, or null.
19433     */
19434    public void setAnimation(Animation animation) {
19435        mCurrentAnimation = animation;
19436
19437        if (animation != null) {
19438            // If the screen is off assume the animation start time is now instead of
19439            // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
19440            // would cause the animation to start when the screen turns back on
19441            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
19442                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
19443                animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
19444            }
19445            animation.reset();
19446        }
19447    }
19448
19449    /**
19450     * Invoked by a parent ViewGroup to notify the start of the animation
19451     * currently associated with this view. If you override this method,
19452     * always call super.onAnimationStart();
19453     *
19454     * @see #setAnimation(android.view.animation.Animation)
19455     * @see #getAnimation()
19456     */
19457    @CallSuper
19458    protected void onAnimationStart() {
19459        mPrivateFlags |= PFLAG_ANIMATION_STARTED;
19460    }
19461
19462    /**
19463     * Invoked by a parent ViewGroup to notify the end of the animation
19464     * currently associated with this view. If you override this method,
19465     * always call super.onAnimationEnd();
19466     *
19467     * @see #setAnimation(android.view.animation.Animation)
19468     * @see #getAnimation()
19469     */
19470    @CallSuper
19471    protected void onAnimationEnd() {
19472        mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
19473    }
19474
19475    /**
19476     * Invoked if there is a Transform that involves alpha. Subclass that can
19477     * draw themselves with the specified alpha should return true, and then
19478     * respect that alpha when their onDraw() is called. If this returns false
19479     * then the view may be redirected to draw into an offscreen buffer to
19480     * fulfill the request, which will look fine, but may be slower than if the
19481     * subclass handles it internally. The default implementation returns false.
19482     *
19483     * @param alpha The alpha (0..255) to apply to the view's drawing
19484     * @return true if the view can draw with the specified alpha.
19485     */
19486    protected boolean onSetAlpha(int alpha) {
19487        return false;
19488    }
19489
19490    /**
19491     * This is used by the RootView to perform an optimization when
19492     * the view hierarchy contains one or several SurfaceView.
19493     * SurfaceView is always considered transparent, but its children are not,
19494     * therefore all View objects remove themselves from the global transparent
19495     * region (passed as a parameter to this function).
19496     *
19497     * @param region The transparent region for this ViewAncestor (window).
19498     *
19499     * @return Returns true if the effective visibility of the view at this
19500     * point is opaque, regardless of the transparent region; returns false
19501     * if it is possible for underlying windows to be seen behind the view.
19502     *
19503     * {@hide}
19504     */
19505    public boolean gatherTransparentRegion(Region region) {
19506        final AttachInfo attachInfo = mAttachInfo;
19507        if (region != null && attachInfo != null) {
19508            final int pflags = mPrivateFlags;
19509            if ((pflags & PFLAG_SKIP_DRAW) == 0) {
19510                // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
19511                // remove it from the transparent region.
19512                final int[] location = attachInfo.mTransparentLocation;
19513                getLocationInWindow(location);
19514                region.op(location[0], location[1], location[0] + mRight - mLeft,
19515                        location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
19516            } else {
19517                if (mBackground != null && mBackground.getOpacity() != PixelFormat.TRANSPARENT) {
19518                    // The SKIP_DRAW flag IS set and the background drawable exists, we remove
19519                    // the background drawable's non-transparent parts from this transparent region.
19520                    applyDrawableToTransparentRegion(mBackground, region);
19521                }
19522                if (mForegroundInfo != null && mForegroundInfo.mDrawable != null
19523                        && mForegroundInfo.mDrawable.getOpacity() != PixelFormat.TRANSPARENT) {
19524                    // Similarly, we remove the foreground drawable's non-transparent parts.
19525                    applyDrawableToTransparentRegion(mForegroundInfo.mDrawable, region);
19526                }
19527            }
19528        }
19529        return true;
19530    }
19531
19532    /**
19533     * Play a sound effect for this view.
19534     *
19535     * <p>The framework will play sound effects for some built in actions, such as
19536     * clicking, but you may wish to play these effects in your widget,
19537     * for instance, for internal navigation.
19538     *
19539     * <p>The sound effect will only be played if sound effects are enabled by the user, and
19540     * {@link #isSoundEffectsEnabled()} is true.
19541     *
19542     * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
19543     */
19544    public void playSoundEffect(int soundConstant) {
19545        if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
19546            return;
19547        }
19548        mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
19549    }
19550
19551    /**
19552     * BZZZTT!!1!
19553     *
19554     * <p>Provide haptic feedback to the user for this view.
19555     *
19556     * <p>The framework will provide haptic feedback for some built in actions,
19557     * such as long presses, but you may wish to provide feedback for your
19558     * own widget.
19559     *
19560     * <p>The feedback will only be performed if
19561     * {@link #isHapticFeedbackEnabled()} is true.
19562     *
19563     * @param feedbackConstant One of the constants defined in
19564     * {@link HapticFeedbackConstants}
19565     */
19566    public boolean performHapticFeedback(int feedbackConstant) {
19567        return performHapticFeedback(feedbackConstant, 0);
19568    }
19569
19570    /**
19571     * BZZZTT!!1!
19572     *
19573     * <p>Like {@link #performHapticFeedback(int)}, with additional options.
19574     *
19575     * @param feedbackConstant One of the constants defined in
19576     * {@link HapticFeedbackConstants}
19577     * @param flags Additional flags as per {@link HapticFeedbackConstants}.
19578     */
19579    public boolean performHapticFeedback(int feedbackConstant, int flags) {
19580        if (mAttachInfo == null) {
19581            return false;
19582        }
19583        //noinspection SimplifiableIfStatement
19584        if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
19585                && !isHapticFeedbackEnabled()) {
19586            return false;
19587        }
19588        return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
19589                (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
19590    }
19591
19592    /**
19593     * Request that the visibility of the status bar or other screen/window
19594     * decorations be changed.
19595     *
19596     * <p>This method is used to put the over device UI into temporary modes
19597     * where the user's attention is focused more on the application content,
19598     * by dimming or hiding surrounding system affordances.  This is typically
19599     * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
19600     * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
19601     * to be placed behind the action bar (and with these flags other system
19602     * affordances) so that smooth transitions between hiding and showing them
19603     * can be done.
19604     *
19605     * <p>Two representative examples of the use of system UI visibility is
19606     * implementing a content browsing application (like a magazine reader)
19607     * and a video playing application.
19608     *
19609     * <p>The first code shows a typical implementation of a View in a content
19610     * browsing application.  In this implementation, the application goes
19611     * into a content-oriented mode by hiding the status bar and action bar,
19612     * and putting the navigation elements into lights out mode.  The user can
19613     * then interact with content while in this mode.  Such an application should
19614     * provide an easy way for the user to toggle out of the mode (such as to
19615     * check information in the status bar or access notifications).  In the
19616     * implementation here, this is done simply by tapping on the content.
19617     *
19618     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
19619     *      content}
19620     *
19621     * <p>This second code sample shows a typical implementation of a View
19622     * in a video playing application.  In this situation, while the video is
19623     * playing the application would like to go into a complete full-screen mode,
19624     * to use as much of the display as possible for the video.  When in this state
19625     * the user can not interact with the application; the system intercepts
19626     * touching on the screen to pop the UI out of full screen mode.  See
19627     * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
19628     *
19629     * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
19630     *      content}
19631     *
19632     * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19633     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19634     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19635     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19636     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19637     */
19638    public void setSystemUiVisibility(int visibility) {
19639        if (visibility != mSystemUiVisibility) {
19640            mSystemUiVisibility = visibility;
19641            if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19642                mParent.recomputeViewAttributes(this);
19643            }
19644        }
19645    }
19646
19647    /**
19648     * Returns the last {@link #setSystemUiVisibility(int)} that this view has requested.
19649     * @return  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
19650     * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
19651     * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
19652     * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}, {@link #SYSTEM_UI_FLAG_IMMERSIVE},
19653     * and {@link #SYSTEM_UI_FLAG_IMMERSIVE_STICKY}.
19654     */
19655    public int getSystemUiVisibility() {
19656        return mSystemUiVisibility;
19657    }
19658
19659    /**
19660     * Returns the current system UI visibility that is currently set for
19661     * the entire window.  This is the combination of the
19662     * {@link #setSystemUiVisibility(int)} values supplied by all of the
19663     * views in the window.
19664     */
19665    public int getWindowSystemUiVisibility() {
19666        return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
19667    }
19668
19669    /**
19670     * Override to find out when the window's requested system UI visibility
19671     * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
19672     * This is different from the callbacks received through
19673     * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
19674     * in that this is only telling you about the local request of the window,
19675     * not the actual values applied by the system.
19676     */
19677    public void onWindowSystemUiVisibilityChanged(int visible) {
19678    }
19679
19680    /**
19681     * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
19682     * the view hierarchy.
19683     */
19684    public void dispatchWindowSystemUiVisiblityChanged(int visible) {
19685        onWindowSystemUiVisibilityChanged(visible);
19686    }
19687
19688    /**
19689     * Set a listener to receive callbacks when the visibility of the system bar changes.
19690     * @param l  The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
19691     */
19692    public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
19693        getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
19694        if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
19695            mParent.recomputeViewAttributes(this);
19696        }
19697    }
19698
19699    /**
19700     * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
19701     * the view hierarchy.
19702     */
19703    public void dispatchSystemUiVisibilityChanged(int visibility) {
19704        ListenerInfo li = mListenerInfo;
19705        if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
19706            li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
19707                    visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
19708        }
19709    }
19710
19711    boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
19712        int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
19713        if (val != mSystemUiVisibility) {
19714            setSystemUiVisibility(val);
19715            return true;
19716        }
19717        return false;
19718    }
19719
19720    /** @hide */
19721    public void setDisabledSystemUiVisibility(int flags) {
19722        if (mAttachInfo != null) {
19723            if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
19724                mAttachInfo.mDisabledSystemUiVisibility = flags;
19725                if (mParent != null) {
19726                    mParent.recomputeViewAttributes(this);
19727                }
19728            }
19729        }
19730    }
19731
19732    /**
19733     * Creates an image that the system displays during the drag and drop
19734     * operation. This is called a &quot;drag shadow&quot;. The default implementation
19735     * for a DragShadowBuilder based on a View returns an image that has exactly the same
19736     * appearance as the given View. The default also positions the center of the drag shadow
19737     * directly under the touch point. If no View is provided (the constructor with no parameters
19738     * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
19739     * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overridden, then the
19740     * default is an invisible drag shadow.
19741     * <p>
19742     * You are not required to use the View you provide to the constructor as the basis of the
19743     * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
19744     * anything you want as the drag shadow.
19745     * </p>
19746     * <p>
19747     *  You pass a DragShadowBuilder object to the system when you start the drag. The system
19748     *  calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
19749     *  size and position of the drag shadow. It uses this data to construct a
19750     *  {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
19751     *  so that your application can draw the shadow image in the Canvas.
19752     * </p>
19753     *
19754     * <div class="special reference">
19755     * <h3>Developer Guides</h3>
19756     * <p>For a guide to implementing drag and drop features, read the
19757     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
19758     * </div>
19759     */
19760    public static class DragShadowBuilder {
19761        private final WeakReference<View> mView;
19762
19763        /**
19764         * Constructs a shadow image builder based on a View. By default, the resulting drag
19765         * shadow will have the same appearance and dimensions as the View, with the touch point
19766         * over the center of the View.
19767         * @param view A View. Any View in scope can be used.
19768         */
19769        public DragShadowBuilder(View view) {
19770            mView = new WeakReference<View>(view);
19771        }
19772
19773        /**
19774         * Construct a shadow builder object with no associated View.  This
19775         * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
19776         * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
19777         * to supply the drag shadow's dimensions and appearance without
19778         * reference to any View object. If they are not overridden, then the result is an
19779         * invisible drag shadow.
19780         */
19781        public DragShadowBuilder() {
19782            mView = new WeakReference<View>(null);
19783        }
19784
19785        /**
19786         * Returns the View object that had been passed to the
19787         * {@link #View.DragShadowBuilder(View)}
19788         * constructor.  If that View parameter was {@code null} or if the
19789         * {@link #View.DragShadowBuilder()}
19790         * constructor was used to instantiate the builder object, this method will return
19791         * null.
19792         *
19793         * @return The View object associate with this builder object.
19794         */
19795        @SuppressWarnings({"JavadocReference"})
19796        final public View getView() {
19797            return mView.get();
19798        }
19799
19800        /**
19801         * Provides the metrics for the shadow image. These include the dimensions of
19802         * the shadow image, and the point within that shadow that should
19803         * be centered under the touch location while dragging.
19804         * <p>
19805         * The default implementation sets the dimensions of the shadow to be the
19806         * same as the dimensions of the View itself and centers the shadow under
19807         * the touch point.
19808         * </p>
19809         *
19810         * @param shadowSize A {@link android.graphics.Point} containing the width and height
19811         * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
19812         * desired width and must set {@link android.graphics.Point#y} to the desired height of the
19813         * image.
19814         *
19815         * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
19816         * shadow image that should be underneath the touch point during the drag and drop
19817         * operation. Your application must set {@link android.graphics.Point#x} to the
19818         * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
19819         */
19820        public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
19821            final View view = mView.get();
19822            if (view != null) {
19823                shadowSize.set(view.getWidth(), view.getHeight());
19824                shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
19825            } else {
19826                Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
19827            }
19828        }
19829
19830        /**
19831         * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
19832         * based on the dimensions it received from the
19833         * {@link #onProvideShadowMetrics(Point, Point)} callback.
19834         *
19835         * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
19836         */
19837        public void onDrawShadow(Canvas canvas) {
19838            final View view = mView.get();
19839            if (view != null) {
19840                view.draw(canvas);
19841            } else {
19842                Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
19843            }
19844        }
19845    }
19846
19847    /**
19848     * Starts a drag and drop operation. When your application calls this method, it passes a
19849     * {@link android.view.View.DragShadowBuilder} object to the system. The
19850     * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
19851     * to get metrics for the drag shadow, and then calls the object's
19852     * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
19853     * <p>
19854     *  Once the system has the drag shadow, it begins the drag and drop operation by sending
19855     *  drag events to all the View objects in your application that are currently visible. It does
19856     *  this either by calling the View object's drag listener (an implementation of
19857     *  {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
19858     *  View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
19859     *  Both are passed a {@link android.view.DragEvent} object that has a
19860     *  {@link android.view.DragEvent#getAction()} value of
19861     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
19862     * </p>
19863     * <p>
19864     * Your application can invoke startDrag() on any attached View object. The View object does not
19865     * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
19866     * be related to the View the user selected for dragging.
19867     * </p>
19868     * @param data A {@link android.content.ClipData} object pointing to the data to be
19869     * transferred by the drag and drop operation.
19870     * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
19871     * drag shadow.
19872     * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
19873     * drop operation. This Object is put into every DragEvent object sent by the system during the
19874     * current drag.
19875     * <p>
19876     * myLocalState is a lightweight mechanism for the sending information from the dragged View
19877     * to the target Views. For example, it can contain flags that differentiate between a
19878     * a copy operation and a move operation.
19879     * </p>
19880     * @param flags Flags that control the drag and drop operation. No flags are currently defined,
19881     * so the parameter should be set to 0.
19882     * @return {@code true} if the method completes successfully, or
19883     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
19884     * do a drag, and so no drag operation is in progress.
19885     */
19886    public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
19887            Object myLocalState, int flags) {
19888        if (ViewDebug.DEBUG_DRAG) {
19889            Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
19890        }
19891        boolean okay = false;
19892
19893        Point shadowSize = new Point();
19894        Point shadowTouchPoint = new Point();
19895        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
19896
19897        if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
19898                (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
19899            throw new IllegalStateException("Drag shadow dimensions must not be negative");
19900        }
19901
19902        if (ViewDebug.DEBUG_DRAG) {
19903            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
19904                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
19905        }
19906        Surface surface = new Surface();
19907        try {
19908            IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
19909                    flags, shadowSize.x, shadowSize.y, surface);
19910            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
19911                    + " surface=" + surface);
19912            if (token != null) {
19913                Canvas canvas = surface.lockCanvas(null);
19914                try {
19915                    canvas.drawColor(0, PorterDuff.Mode.CLEAR);
19916                    shadowBuilder.onDrawShadow(canvas);
19917                } finally {
19918                    surface.unlockCanvasAndPost(canvas);
19919                }
19920
19921                final ViewRootImpl root = getViewRootImpl();
19922
19923                // Cache the local state object for delivery with DragEvents
19924                root.setLocalDragState(myLocalState);
19925
19926                // repurpose 'shadowSize' for the last touch point
19927                root.getLastTouchPoint(shadowSize);
19928
19929                okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
19930                        shadowSize.x, shadowSize.y,
19931                        shadowTouchPoint.x, shadowTouchPoint.y, data);
19932                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
19933
19934                // Off and running!  Release our local surface instance; the drag
19935                // shadow surface is now managed by the system process.
19936                surface.release();
19937            }
19938        } catch (Exception e) {
19939            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
19940            surface.destroy();
19941        }
19942
19943        return okay;
19944    }
19945
19946    /**
19947     * Starts a move from {startX, startY}, the amount of the movement will be the offset
19948     * between {startX, startY} and the new cursor positon.
19949     * @param startX horizontal coordinate where the move started.
19950     * @param startY vertical coordinate where the move started.
19951     * @return whether moving was started successfully.
19952     * @hide
19953     */
19954    public final boolean startMovingTask(float startX, float startY) {
19955        if (ViewDebug.DEBUG_POSITIONING) {
19956            Log.d(VIEW_LOG_TAG, "startMovingTask: {" + startX + "," + startY + "}");
19957        }
19958        try {
19959            return mAttachInfo.mSession.startMovingTask(mAttachInfo.mWindow, startX, startY);
19960        } catch (RemoteException e) {
19961            Log.e(VIEW_LOG_TAG, "Unable to start moving", e);
19962        }
19963        return false;
19964    }
19965
19966    /**
19967     * Handles drag events sent by the system following a call to
19968     * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
19969     *<p>
19970     * When the system calls this method, it passes a
19971     * {@link android.view.DragEvent} object. A call to
19972     * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
19973     * in DragEvent. The method uses these to determine what is happening in the drag and drop
19974     * operation.
19975     * @param event The {@link android.view.DragEvent} sent by the system.
19976     * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
19977     * in DragEvent, indicating the type of drag event represented by this object.
19978     * @return {@code true} if the method was successful, otherwise {@code false}.
19979     * <p>
19980     *  The method should return {@code true} in response to an action type of
19981     *  {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
19982     *  operation.
19983     * </p>
19984     * <p>
19985     *  The method should also return {@code true} in response to an action type of
19986     *  {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
19987     *  {@code false} if it didn't.
19988     * </p>
19989     */
19990    public boolean onDragEvent(DragEvent event) {
19991        return false;
19992    }
19993
19994    /**
19995     * Detects if this View is enabled and has a drag event listener.
19996     * If both are true, then it calls the drag event listener with the
19997     * {@link android.view.DragEvent} it received. If the drag event listener returns
19998     * {@code true}, then dispatchDragEvent() returns {@code true}.
19999     * <p>
20000     * For all other cases, the method calls the
20001     * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
20002     * method and returns its result.
20003     * </p>
20004     * <p>
20005     * This ensures that a drag event is always consumed, even if the View does not have a drag
20006     * event listener. However, if the View has a listener and the listener returns true, then
20007     * onDragEvent() is not called.
20008     * </p>
20009     */
20010    public boolean dispatchDragEvent(DragEvent event) {
20011        ListenerInfo li = mListenerInfo;
20012        //noinspection SimplifiableIfStatement
20013        if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
20014                && li.mOnDragListener.onDrag(this, event)) {
20015            return true;
20016        }
20017        return onDragEvent(event);
20018    }
20019
20020    boolean canAcceptDrag() {
20021        return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
20022    }
20023
20024    /**
20025     * This needs to be a better API (NOT ON VIEW) before it is exposed.  If
20026     * it is ever exposed at all.
20027     * @hide
20028     */
20029    public void onCloseSystemDialogs(String reason) {
20030    }
20031
20032    /**
20033     * Given a Drawable whose bounds have been set to draw into this view,
20034     * update a Region being computed for
20035     * {@link #gatherTransparentRegion(android.graphics.Region)} so
20036     * that any non-transparent parts of the Drawable are removed from the
20037     * given transparent region.
20038     *
20039     * @param dr The Drawable whose transparency is to be applied to the region.
20040     * @param region A Region holding the current transparency information,
20041     * where any parts of the region that are set are considered to be
20042     * transparent.  On return, this region will be modified to have the
20043     * transparency information reduced by the corresponding parts of the
20044     * Drawable that are not transparent.
20045     * {@hide}
20046     */
20047    public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
20048        if (DBG) {
20049            Log.i("View", "Getting transparent region for: " + this);
20050        }
20051        final Region r = dr.getTransparentRegion();
20052        final Rect db = dr.getBounds();
20053        final AttachInfo attachInfo = mAttachInfo;
20054        if (r != null && attachInfo != null) {
20055            final int w = getRight()-getLeft();
20056            final int h = getBottom()-getTop();
20057            if (db.left > 0) {
20058                //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
20059                r.op(0, 0, db.left, h, Region.Op.UNION);
20060            }
20061            if (db.right < w) {
20062                //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
20063                r.op(db.right, 0, w, h, Region.Op.UNION);
20064            }
20065            if (db.top > 0) {
20066                //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
20067                r.op(0, 0, w, db.top, Region.Op.UNION);
20068            }
20069            if (db.bottom < h) {
20070                //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
20071                r.op(0, db.bottom, w, h, Region.Op.UNION);
20072            }
20073            final int[] location = attachInfo.mTransparentLocation;
20074            getLocationInWindow(location);
20075            r.translate(location[0], location[1]);
20076            region.op(r, Region.Op.INTERSECT);
20077        } else {
20078            region.op(db, Region.Op.DIFFERENCE);
20079        }
20080    }
20081
20082    private void checkForLongClick(int delayOffset, float x, float y) {
20083        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
20084            mHasPerformedLongPress = false;
20085
20086            if (mPendingCheckForLongPress == null) {
20087                mPendingCheckForLongPress = new CheckForLongPress();
20088            }
20089            mPendingCheckForLongPress.setAnchor(x, y);
20090            mPendingCheckForLongPress.rememberWindowAttachCount();
20091            postDelayed(mPendingCheckForLongPress,
20092                    ViewConfiguration.getLongPressTimeout() - delayOffset);
20093        }
20094    }
20095
20096    /**
20097     * Inflate a view from an XML resource.  This convenience method wraps the {@link
20098     * LayoutInflater} class, which provides a full range of options for view inflation.
20099     *
20100     * @param context The Context object for your activity or application.
20101     * @param resource The resource ID to inflate
20102     * @param root A view group that will be the parent.  Used to properly inflate the
20103     * layout_* parameters.
20104     * @see LayoutInflater
20105     */
20106    public static View inflate(Context context, @LayoutRes int resource, ViewGroup root) {
20107        LayoutInflater factory = LayoutInflater.from(context);
20108        return factory.inflate(resource, root);
20109    }
20110
20111    /**
20112     * Scroll the view with standard behavior for scrolling beyond the normal
20113     * content boundaries. Views that call this method should override
20114     * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
20115     * results of an over-scroll operation.
20116     *
20117     * Views can use this method to handle any touch or fling-based scrolling.
20118     *
20119     * @param deltaX Change in X in pixels
20120     * @param deltaY Change in Y in pixels
20121     * @param scrollX Current X scroll value in pixels before applying deltaX
20122     * @param scrollY Current Y scroll value in pixels before applying deltaY
20123     * @param scrollRangeX Maximum content scroll range along the X axis
20124     * @param scrollRangeY Maximum content scroll range along the Y axis
20125     * @param maxOverScrollX Number of pixels to overscroll by in either direction
20126     *          along the X axis.
20127     * @param maxOverScrollY Number of pixels to overscroll by in either direction
20128     *          along the Y axis.
20129     * @param isTouchEvent true if this scroll operation is the result of a touch event.
20130     * @return true if scrolling was clamped to an over-scroll boundary along either
20131     *          axis, false otherwise.
20132     */
20133    @SuppressWarnings({"UnusedParameters"})
20134    protected boolean overScrollBy(int deltaX, int deltaY,
20135            int scrollX, int scrollY,
20136            int scrollRangeX, int scrollRangeY,
20137            int maxOverScrollX, int maxOverScrollY,
20138            boolean isTouchEvent) {
20139        final int overScrollMode = mOverScrollMode;
20140        final boolean canScrollHorizontal =
20141                computeHorizontalScrollRange() > computeHorizontalScrollExtent();
20142        final boolean canScrollVertical =
20143                computeVerticalScrollRange() > computeVerticalScrollExtent();
20144        final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
20145                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
20146        final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
20147                (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
20148
20149        int newScrollX = scrollX + deltaX;
20150        if (!overScrollHorizontal) {
20151            maxOverScrollX = 0;
20152        }
20153
20154        int newScrollY = scrollY + deltaY;
20155        if (!overScrollVertical) {
20156            maxOverScrollY = 0;
20157        }
20158
20159        // Clamp values if at the limits and record
20160        final int left = -maxOverScrollX;
20161        final int right = maxOverScrollX + scrollRangeX;
20162        final int top = -maxOverScrollY;
20163        final int bottom = maxOverScrollY + scrollRangeY;
20164
20165        boolean clampedX = false;
20166        if (newScrollX > right) {
20167            newScrollX = right;
20168            clampedX = true;
20169        } else if (newScrollX < left) {
20170            newScrollX = left;
20171            clampedX = true;
20172        }
20173
20174        boolean clampedY = false;
20175        if (newScrollY > bottom) {
20176            newScrollY = bottom;
20177            clampedY = true;
20178        } else if (newScrollY < top) {
20179            newScrollY = top;
20180            clampedY = true;
20181        }
20182
20183        onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
20184
20185        return clampedX || clampedY;
20186    }
20187
20188    /**
20189     * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
20190     * respond to the results of an over-scroll operation.
20191     *
20192     * @param scrollX New X scroll value in pixels
20193     * @param scrollY New Y scroll value in pixels
20194     * @param clampedX True if scrollX was clamped to an over-scroll boundary
20195     * @param clampedY True if scrollY was clamped to an over-scroll boundary
20196     */
20197    protected void onOverScrolled(int scrollX, int scrollY,
20198            boolean clampedX, boolean clampedY) {
20199        // Intentionally empty.
20200    }
20201
20202    /**
20203     * Returns the over-scroll mode for this view. The result will be
20204     * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20205     * (allow over-scrolling only if the view content is larger than the container),
20206     * or {@link #OVER_SCROLL_NEVER}.
20207     *
20208     * @return This view's over-scroll mode.
20209     */
20210    public int getOverScrollMode() {
20211        return mOverScrollMode;
20212    }
20213
20214    /**
20215     * Set the over-scroll mode for this view. Valid over-scroll modes are
20216     * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
20217     * (allow over-scrolling only if the view content is larger than the container),
20218     * or {@link #OVER_SCROLL_NEVER}.
20219     *
20220     * Setting the over-scroll mode of a view will have an effect only if the
20221     * view is capable of scrolling.
20222     *
20223     * @param overScrollMode The new over-scroll mode for this view.
20224     */
20225    public void setOverScrollMode(int overScrollMode) {
20226        if (overScrollMode != OVER_SCROLL_ALWAYS &&
20227                overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
20228                overScrollMode != OVER_SCROLL_NEVER) {
20229            throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
20230        }
20231        mOverScrollMode = overScrollMode;
20232    }
20233
20234    /**
20235     * Enable or disable nested scrolling for this view.
20236     *
20237     * <p>If this property is set to true the view will be permitted to initiate nested
20238     * scrolling operations with a compatible parent view in the current hierarchy. If this
20239     * view does not implement nested scrolling this will have no effect. Disabling nested scrolling
20240     * while a nested scroll is in progress has the effect of {@link #stopNestedScroll() stopping}
20241     * the nested scroll.</p>
20242     *
20243     * @param enabled true to enable nested scrolling, false to disable
20244     *
20245     * @see #isNestedScrollingEnabled()
20246     */
20247    public void setNestedScrollingEnabled(boolean enabled) {
20248        if (enabled) {
20249            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
20250        } else {
20251            stopNestedScroll();
20252            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
20253        }
20254    }
20255
20256    /**
20257     * Returns true if nested scrolling is enabled for this view.
20258     *
20259     * <p>If nested scrolling is enabled and this View class implementation supports it,
20260     * this view will act as a nested scrolling child view when applicable, forwarding data
20261     * about the scroll operation in progress to a compatible and cooperating nested scrolling
20262     * parent.</p>
20263     *
20264     * @return true if nested scrolling is enabled
20265     *
20266     * @see #setNestedScrollingEnabled(boolean)
20267     */
20268    public boolean isNestedScrollingEnabled() {
20269        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
20270                PFLAG3_NESTED_SCROLLING_ENABLED;
20271    }
20272
20273    /**
20274     * Begin a nestable scroll operation along the given axes.
20275     *
20276     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
20277     *
20278     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
20279     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
20280     * In the case of touch scrolling the nested scroll will be terminated automatically in
20281     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
20282     * In the event of programmatic scrolling the caller must explicitly call
20283     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
20284     *
20285     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
20286     * If it returns false the caller may ignore the rest of this contract until the next scroll.
20287     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
20288     *
20289     * <p>At each incremental step of the scroll the caller should invoke
20290     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
20291     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
20292     * parent at least partially consumed the scroll and the caller should adjust the amount it
20293     * scrolls by.</p>
20294     *
20295     * <p>After applying the remainder of the scroll delta the caller should invoke
20296     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
20297     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
20298     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
20299     * </p>
20300     *
20301     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
20302     *             {@link #SCROLL_AXIS_VERTICAL}.
20303     * @return true if a cooperative parent was found and nested scrolling has been enabled for
20304     *         the current gesture.
20305     *
20306     * @see #stopNestedScroll()
20307     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20308     * @see #dispatchNestedScroll(int, int, int, int, int[])
20309     */
20310    public boolean startNestedScroll(int axes) {
20311        if (hasNestedScrollingParent()) {
20312            // Already in progress
20313            return true;
20314        }
20315        if (isNestedScrollingEnabled()) {
20316            ViewParent p = getParent();
20317            View child = this;
20318            while (p != null) {
20319                try {
20320                    if (p.onStartNestedScroll(child, this, axes)) {
20321                        mNestedScrollingParent = p;
20322                        p.onNestedScrollAccepted(child, this, axes);
20323                        return true;
20324                    }
20325                } catch (AbstractMethodError e) {
20326                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
20327                            "method onStartNestedScroll", e);
20328                    // Allow the search upward to continue
20329                }
20330                if (p instanceof View) {
20331                    child = (View) p;
20332                }
20333                p = p.getParent();
20334            }
20335        }
20336        return false;
20337    }
20338
20339    /**
20340     * Stop a nested scroll in progress.
20341     *
20342     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
20343     *
20344     * @see #startNestedScroll(int)
20345     */
20346    public void stopNestedScroll() {
20347        if (mNestedScrollingParent != null) {
20348            mNestedScrollingParent.onStopNestedScroll(this);
20349            mNestedScrollingParent = null;
20350        }
20351    }
20352
20353    /**
20354     * Returns true if this view has a nested scrolling parent.
20355     *
20356     * <p>The presence of a nested scrolling parent indicates that this view has initiated
20357     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
20358     *
20359     * @return whether this view has a nested scrolling parent
20360     */
20361    public boolean hasNestedScrollingParent() {
20362        return mNestedScrollingParent != null;
20363    }
20364
20365    /**
20366     * Dispatch one step of a nested scroll in progress.
20367     *
20368     * <p>Implementations of views that support nested scrolling should call this to report
20369     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
20370     * is not currently in progress or nested scrolling is not
20371     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
20372     *
20373     * <p>Compatible View implementations should also call
20374     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
20375     * consuming a component of the scroll event themselves.</p>
20376     *
20377     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
20378     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
20379     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
20380     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
20381     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20382     *                       in local view coordinates of this view from before this operation
20383     *                       to after it completes. View implementations may use this to adjust
20384     *                       expected input coordinate tracking.
20385     * @return true if the event was dispatched, false if it could not be dispatched.
20386     * @see #dispatchNestedPreScroll(int, int, int[], int[])
20387     */
20388    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
20389            int dxUnconsumed, int dyUnconsumed, @Nullable @Size(2) int[] offsetInWindow) {
20390        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20391            if (dxConsumed != 0 || dyConsumed != 0 || dxUnconsumed != 0 || dyUnconsumed != 0) {
20392                int startX = 0;
20393                int startY = 0;
20394                if (offsetInWindow != null) {
20395                    getLocationInWindow(offsetInWindow);
20396                    startX = offsetInWindow[0];
20397                    startY = offsetInWindow[1];
20398                }
20399
20400                mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
20401                        dxUnconsumed, dyUnconsumed);
20402
20403                if (offsetInWindow != null) {
20404                    getLocationInWindow(offsetInWindow);
20405                    offsetInWindow[0] -= startX;
20406                    offsetInWindow[1] -= startY;
20407                }
20408                return true;
20409            } else if (offsetInWindow != null) {
20410                // No motion, no dispatch. Keep offsetInWindow up to date.
20411                offsetInWindow[0] = 0;
20412                offsetInWindow[1] = 0;
20413            }
20414        }
20415        return false;
20416    }
20417
20418    /**
20419     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
20420     *
20421     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
20422     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
20423     * scrolling operation to consume some or all of the scroll operation before the child view
20424     * consumes it.</p>
20425     *
20426     * @param dx Horizontal scroll distance in pixels
20427     * @param dy Vertical scroll distance in pixels
20428     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
20429     *                 and consumed[1] the consumed dy.
20430     * @param offsetInWindow Optional. If not null, on return this will contain the offset
20431     *                       in local view coordinates of this view from before this operation
20432     *                       to after it completes. View implementations may use this to adjust
20433     *                       expected input coordinate tracking.
20434     * @return true if the parent consumed some or all of the scroll delta
20435     * @see #dispatchNestedScroll(int, int, int, int, int[])
20436     */
20437    public boolean dispatchNestedPreScroll(int dx, int dy,
20438            @Nullable @Size(2) int[] consumed, @Nullable @Size(2) int[] offsetInWindow) {
20439        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20440            if (dx != 0 || dy != 0) {
20441                int startX = 0;
20442                int startY = 0;
20443                if (offsetInWindow != null) {
20444                    getLocationInWindow(offsetInWindow);
20445                    startX = offsetInWindow[0];
20446                    startY = offsetInWindow[1];
20447                }
20448
20449                if (consumed == null) {
20450                    if (mTempNestedScrollConsumed == null) {
20451                        mTempNestedScrollConsumed = new int[2];
20452                    }
20453                    consumed = mTempNestedScrollConsumed;
20454                }
20455                consumed[0] = 0;
20456                consumed[1] = 0;
20457                mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
20458
20459                if (offsetInWindow != null) {
20460                    getLocationInWindow(offsetInWindow);
20461                    offsetInWindow[0] -= startX;
20462                    offsetInWindow[1] -= startY;
20463                }
20464                return consumed[0] != 0 || consumed[1] != 0;
20465            } else if (offsetInWindow != null) {
20466                offsetInWindow[0] = 0;
20467                offsetInWindow[1] = 0;
20468            }
20469        }
20470        return false;
20471    }
20472
20473    /**
20474     * Dispatch a fling to a nested scrolling parent.
20475     *
20476     * <p>This method should be used to indicate that a nested scrolling child has detected
20477     * suitable conditions for a fling. Generally this means that a touch scroll has ended with a
20478     * {@link VelocityTracker velocity} in the direction of scrolling that meets or exceeds
20479     * the {@link ViewConfiguration#getScaledMinimumFlingVelocity() minimum fling velocity}
20480     * along a scrollable axis.</p>
20481     *
20482     * <p>If a nested scrolling child view would normally fling but it is at the edge of
20483     * its own content, it can use this method to delegate the fling to its nested scrolling
20484     * parent instead. The parent may optionally consume the fling or observe a child fling.</p>
20485     *
20486     * @param velocityX Horizontal fling velocity in pixels per second
20487     * @param velocityY Vertical fling velocity in pixels per second
20488     * @param consumed true if the child consumed the fling, false otherwise
20489     * @return true if the nested scrolling parent consumed or otherwise reacted to the fling
20490     */
20491    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
20492        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20493            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY, consumed);
20494        }
20495        return false;
20496    }
20497
20498    /**
20499     * Dispatch a fling to a nested scrolling parent before it is processed by this view.
20500     *
20501     * <p>Nested pre-fling events are to nested fling events what touch intercept is to touch
20502     * and what nested pre-scroll is to nested scroll. <code>dispatchNestedPreFling</code>
20503     * offsets an opportunity for the parent view in a nested fling to fully consume the fling
20504     * before the child view consumes it. If this method returns <code>true</code>, a nested
20505     * parent view consumed the fling and this view should not scroll as a result.</p>
20506     *
20507     * <p>For a better user experience, only one view in a nested scrolling chain should consume
20508     * the fling at a time. If a parent view consumed the fling this method will return false.
20509     * Custom view implementations should account for this in two ways:</p>
20510     *
20511     * <ul>
20512     *     <li>If a custom view is paged and needs to settle to a fixed page-point, do not
20513     *     call <code>dispatchNestedPreFling</code>; consume the fling and settle to a valid
20514     *     position regardless.</li>
20515     *     <li>If a nested parent does consume the fling, this view should not scroll at all,
20516     *     even to settle back to a valid idle position.</li>
20517     * </ul>
20518     *
20519     * <p>Views should also not offer fling velocities to nested parent views along an axis
20520     * where scrolling is not currently supported; a {@link android.widget.ScrollView ScrollView}
20521     * should not offer a horizontal fling velocity to its parents since scrolling along that
20522     * axis is not permitted and carrying velocity along that motion does not make sense.</p>
20523     *
20524     * @param velocityX Horizontal fling velocity in pixels per second
20525     * @param velocityY Vertical fling velocity in pixels per second
20526     * @return true if a nested scrolling parent consumed the fling
20527     */
20528    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
20529        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
20530            return mNestedScrollingParent.onNestedPreFling(this, velocityX, velocityY);
20531        }
20532        return false;
20533    }
20534
20535    /**
20536     * Gets a scale factor that determines the distance the view should scroll
20537     * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
20538     * @return The vertical scroll scale factor.
20539     * @hide
20540     */
20541    protected float getVerticalScrollFactor() {
20542        if (mVerticalScrollFactor == 0) {
20543            TypedValue outValue = new TypedValue();
20544            if (!mContext.getTheme().resolveAttribute(
20545                    com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
20546                throw new IllegalStateException(
20547                        "Expected theme to define listPreferredItemHeight.");
20548            }
20549            mVerticalScrollFactor = outValue.getDimension(
20550                    mContext.getResources().getDisplayMetrics());
20551        }
20552        return mVerticalScrollFactor;
20553    }
20554
20555    /**
20556     * Gets a scale factor that determines the distance the view should scroll
20557     * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
20558     * @return The horizontal scroll scale factor.
20559     * @hide
20560     */
20561    protected float getHorizontalScrollFactor() {
20562        // TODO: Should use something else.
20563        return getVerticalScrollFactor();
20564    }
20565
20566    /**
20567     * Return the value specifying the text direction or policy that was set with
20568     * {@link #setTextDirection(int)}.
20569     *
20570     * @return the defined text direction. It can be one of:
20571     *
20572     * {@link #TEXT_DIRECTION_INHERIT},
20573     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20574     * {@link #TEXT_DIRECTION_ANY_RTL},
20575     * {@link #TEXT_DIRECTION_LTR},
20576     * {@link #TEXT_DIRECTION_RTL},
20577     * {@link #TEXT_DIRECTION_LOCALE},
20578     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20579     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20580     *
20581     * @attr ref android.R.styleable#View_textDirection
20582     *
20583     * @hide
20584     */
20585    @ViewDebug.ExportedProperty(category = "text", mapping = {
20586            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20587            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20588            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20589            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20590            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20591            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20592            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20593            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20594    })
20595    public int getRawTextDirection() {
20596        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
20597    }
20598
20599    /**
20600     * Set the text direction.
20601     *
20602     * @param textDirection the direction to set. Should be one of:
20603     *
20604     * {@link #TEXT_DIRECTION_INHERIT},
20605     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20606     * {@link #TEXT_DIRECTION_ANY_RTL},
20607     * {@link #TEXT_DIRECTION_LTR},
20608     * {@link #TEXT_DIRECTION_RTL},
20609     * {@link #TEXT_DIRECTION_LOCALE}
20610     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20611     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL},
20612     *
20613     * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
20614     * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
20615     * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
20616     *
20617     * @attr ref android.R.styleable#View_textDirection
20618     */
20619    public void setTextDirection(int textDirection) {
20620        if (getRawTextDirection() != textDirection) {
20621            // Reset the current text direction and the resolved one
20622            mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
20623            resetResolvedTextDirection();
20624            // Set the new text direction
20625            mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
20626            // Do resolution
20627            resolveTextDirection();
20628            // Notify change
20629            onRtlPropertiesChanged(getLayoutDirection());
20630            // Refresh
20631            requestLayout();
20632            invalidate(true);
20633        }
20634    }
20635
20636    /**
20637     * Return the resolved text direction.
20638     *
20639     * @return the resolved text direction. Returns one of:
20640     *
20641     * {@link #TEXT_DIRECTION_FIRST_STRONG},
20642     * {@link #TEXT_DIRECTION_ANY_RTL},
20643     * {@link #TEXT_DIRECTION_LTR},
20644     * {@link #TEXT_DIRECTION_RTL},
20645     * {@link #TEXT_DIRECTION_LOCALE},
20646     * {@link #TEXT_DIRECTION_FIRST_STRONG_LTR},
20647     * {@link #TEXT_DIRECTION_FIRST_STRONG_RTL}
20648     *
20649     * @attr ref android.R.styleable#View_textDirection
20650     */
20651    @ViewDebug.ExportedProperty(category = "text", mapping = {
20652            @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
20653            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
20654            @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
20655            @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
20656            @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
20657            @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE"),
20658            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_LTR, to = "FIRST_STRONG_LTR"),
20659            @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG_RTL, to = "FIRST_STRONG_RTL")
20660    })
20661    public int getTextDirection() {
20662        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
20663    }
20664
20665    /**
20666     * Resolve the text direction.
20667     *
20668     * @return true if resolution has been done, false otherwise.
20669     *
20670     * @hide
20671     */
20672    public boolean resolveTextDirection() {
20673        // Reset any previous text direction resolution
20674        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20675
20676        if (hasRtlSupport()) {
20677            // Set resolved text direction flag depending on text direction flag
20678            final int textDirection = getRawTextDirection();
20679            switch(textDirection) {
20680                case TEXT_DIRECTION_INHERIT:
20681                    if (!canResolveTextDirection()) {
20682                        // We cannot do the resolution if there is no parent, so use the default one
20683                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20684                        // Resolution will need to happen again later
20685                        return false;
20686                    }
20687
20688                    // Parent has not yet resolved, so we still return the default
20689                    try {
20690                        if (!mParent.isTextDirectionResolved()) {
20691                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20692                            // Resolution will need to happen again later
20693                            return false;
20694                        }
20695                    } catch (AbstractMethodError e) {
20696                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20697                                " does not fully implement ViewParent", e);
20698                        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED |
20699                                PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20700                        return true;
20701                    }
20702
20703                    // Set current resolved direction to the same value as the parent's one
20704                    int parentResolvedDirection;
20705                    try {
20706                        parentResolvedDirection = mParent.getTextDirection();
20707                    } catch (AbstractMethodError e) {
20708                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20709                                " does not fully implement ViewParent", e);
20710                        parentResolvedDirection = TEXT_DIRECTION_LTR;
20711                    }
20712                    switch (parentResolvedDirection) {
20713                        case TEXT_DIRECTION_FIRST_STRONG:
20714                        case TEXT_DIRECTION_ANY_RTL:
20715                        case TEXT_DIRECTION_LTR:
20716                        case TEXT_DIRECTION_RTL:
20717                        case TEXT_DIRECTION_LOCALE:
20718                        case TEXT_DIRECTION_FIRST_STRONG_LTR:
20719                        case TEXT_DIRECTION_FIRST_STRONG_RTL:
20720                            mPrivateFlags2 |=
20721                                    (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20722                            break;
20723                        default:
20724                            // Default resolved direction is "first strong" heuristic
20725                            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20726                    }
20727                    break;
20728                case TEXT_DIRECTION_FIRST_STRONG:
20729                case TEXT_DIRECTION_ANY_RTL:
20730                case TEXT_DIRECTION_LTR:
20731                case TEXT_DIRECTION_RTL:
20732                case TEXT_DIRECTION_LOCALE:
20733                case TEXT_DIRECTION_FIRST_STRONG_LTR:
20734                case TEXT_DIRECTION_FIRST_STRONG_RTL:
20735                    // Resolved direction is the same as text direction
20736                    mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
20737                    break;
20738                default:
20739                    // Default resolved direction is "first strong" heuristic
20740                    mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20741            }
20742        } else {
20743            // Default resolved direction is "first strong" heuristic
20744            mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20745        }
20746
20747        // Set to resolved
20748        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
20749        return true;
20750    }
20751
20752    /**
20753     * Check if text direction resolution can be done.
20754     *
20755     * @return true if text direction resolution can be done otherwise return false.
20756     */
20757    public boolean canResolveTextDirection() {
20758        switch (getRawTextDirection()) {
20759            case TEXT_DIRECTION_INHERIT:
20760                if (mParent != null) {
20761                    try {
20762                        return mParent.canResolveTextDirection();
20763                    } catch (AbstractMethodError e) {
20764                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20765                                " does not fully implement ViewParent", e);
20766                    }
20767                }
20768                return false;
20769
20770            default:
20771                return true;
20772        }
20773    }
20774
20775    /**
20776     * Reset resolved text direction. Text direction will be resolved during a call to
20777     * {@link #onMeasure(int, int)}.
20778     *
20779     * @hide
20780     */
20781    public void resetResolvedTextDirection() {
20782        // Reset any previous text direction resolution
20783        mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
20784        // Set to default value
20785        mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
20786    }
20787
20788    /**
20789     * @return true if text direction is inherited.
20790     *
20791     * @hide
20792     */
20793    public boolean isTextDirectionInherited() {
20794        return (getRawTextDirection() == TEXT_DIRECTION_INHERIT);
20795    }
20796
20797    /**
20798     * @return true if text direction is resolved.
20799     */
20800    public boolean isTextDirectionResolved() {
20801        return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) == PFLAG2_TEXT_DIRECTION_RESOLVED;
20802    }
20803
20804    /**
20805     * Return the value specifying the text alignment or policy that was set with
20806     * {@link #setTextAlignment(int)}.
20807     *
20808     * @return the defined text alignment. It can be one of:
20809     *
20810     * {@link #TEXT_ALIGNMENT_INHERIT},
20811     * {@link #TEXT_ALIGNMENT_GRAVITY},
20812     * {@link #TEXT_ALIGNMENT_CENTER},
20813     * {@link #TEXT_ALIGNMENT_TEXT_START},
20814     * {@link #TEXT_ALIGNMENT_TEXT_END},
20815     * {@link #TEXT_ALIGNMENT_VIEW_START},
20816     * {@link #TEXT_ALIGNMENT_VIEW_END}
20817     *
20818     * @attr ref android.R.styleable#View_textAlignment
20819     *
20820     * @hide
20821     */
20822    @ViewDebug.ExportedProperty(category = "text", mapping = {
20823            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20824            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20825            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20826            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20827            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20828            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20829            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20830    })
20831    @TextAlignment
20832    public int getRawTextAlignment() {
20833        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
20834    }
20835
20836    /**
20837     * Set the text alignment.
20838     *
20839     * @param textAlignment The text alignment to set. Should be one of
20840     *
20841     * {@link #TEXT_ALIGNMENT_INHERIT},
20842     * {@link #TEXT_ALIGNMENT_GRAVITY},
20843     * {@link #TEXT_ALIGNMENT_CENTER},
20844     * {@link #TEXT_ALIGNMENT_TEXT_START},
20845     * {@link #TEXT_ALIGNMENT_TEXT_END},
20846     * {@link #TEXT_ALIGNMENT_VIEW_START},
20847     * {@link #TEXT_ALIGNMENT_VIEW_END}
20848     *
20849     * Resolution will be done if the value is set to TEXT_ALIGNMENT_INHERIT. The resolution
20850     * proceeds up the parent chain of the view to get the value. If there is no parent, then it
20851     * will return the default {@link #TEXT_ALIGNMENT_GRAVITY}.
20852     *
20853     * @attr ref android.R.styleable#View_textAlignment
20854     */
20855    public void setTextAlignment(@TextAlignment int textAlignment) {
20856        if (textAlignment != getRawTextAlignment()) {
20857            // Reset the current and resolved text alignment
20858            mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
20859            resetResolvedTextAlignment();
20860            // Set the new text alignment
20861            mPrivateFlags2 |=
20862                    ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
20863            // Do resolution
20864            resolveTextAlignment();
20865            // Notify change
20866            onRtlPropertiesChanged(getLayoutDirection());
20867            // Refresh
20868            requestLayout();
20869            invalidate(true);
20870        }
20871    }
20872
20873    /**
20874     * Return the resolved text alignment.
20875     *
20876     * @return the resolved text alignment. Returns one of:
20877     *
20878     * {@link #TEXT_ALIGNMENT_GRAVITY},
20879     * {@link #TEXT_ALIGNMENT_CENTER},
20880     * {@link #TEXT_ALIGNMENT_TEXT_START},
20881     * {@link #TEXT_ALIGNMENT_TEXT_END},
20882     * {@link #TEXT_ALIGNMENT_VIEW_START},
20883     * {@link #TEXT_ALIGNMENT_VIEW_END}
20884     *
20885     * @attr ref android.R.styleable#View_textAlignment
20886     */
20887    @ViewDebug.ExportedProperty(category = "text", mapping = {
20888            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
20889            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
20890            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
20891            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
20892            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
20893            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
20894            @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
20895    })
20896    @TextAlignment
20897    public int getTextAlignment() {
20898        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >>
20899                PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
20900    }
20901
20902    /**
20903     * Resolve the text alignment.
20904     *
20905     * @return true if resolution has been done, false otherwise.
20906     *
20907     * @hide
20908     */
20909    public boolean resolveTextAlignment() {
20910        // Reset any previous text alignment resolution
20911        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
20912
20913        if (hasRtlSupport()) {
20914            // Set resolved text alignment flag depending on text alignment flag
20915            final int textAlignment = getRawTextAlignment();
20916            switch (textAlignment) {
20917                case TEXT_ALIGNMENT_INHERIT:
20918                    // Check if we can resolve the text alignment
20919                    if (!canResolveTextAlignment()) {
20920                        // We cannot do the resolution if there is no parent so use the default
20921                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20922                        // Resolution will need to happen again later
20923                        return false;
20924                    }
20925
20926                    // Parent has not yet resolved, so we still return the default
20927                    try {
20928                        if (!mParent.isTextAlignmentResolved()) {
20929                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20930                            // Resolution will need to happen again later
20931                            return false;
20932                        }
20933                    } catch (AbstractMethodError e) {
20934                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20935                                " does not fully implement ViewParent", e);
20936                        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED |
20937                                PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20938                        return true;
20939                    }
20940
20941                    int parentResolvedTextAlignment;
20942                    try {
20943                        parentResolvedTextAlignment = mParent.getTextAlignment();
20944                    } catch (AbstractMethodError e) {
20945                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
20946                                " does not fully implement ViewParent", e);
20947                        parentResolvedTextAlignment = TEXT_ALIGNMENT_GRAVITY;
20948                    }
20949                    switch (parentResolvedTextAlignment) {
20950                        case TEXT_ALIGNMENT_GRAVITY:
20951                        case TEXT_ALIGNMENT_TEXT_START:
20952                        case TEXT_ALIGNMENT_TEXT_END:
20953                        case TEXT_ALIGNMENT_CENTER:
20954                        case TEXT_ALIGNMENT_VIEW_START:
20955                        case TEXT_ALIGNMENT_VIEW_END:
20956                            // Resolved text alignment is the same as the parent resolved
20957                            // text alignment
20958                            mPrivateFlags2 |=
20959                                    (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20960                            break;
20961                        default:
20962                            // Use default resolved text alignment
20963                            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20964                    }
20965                    break;
20966                case TEXT_ALIGNMENT_GRAVITY:
20967                case TEXT_ALIGNMENT_TEXT_START:
20968                case TEXT_ALIGNMENT_TEXT_END:
20969                case TEXT_ALIGNMENT_CENTER:
20970                case TEXT_ALIGNMENT_VIEW_START:
20971                case TEXT_ALIGNMENT_VIEW_END:
20972                    // Resolved text alignment is the same as text alignment
20973                    mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
20974                    break;
20975                default:
20976                    // Use default resolved text alignment
20977                    mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20978            }
20979        } else {
20980            // Use default resolved text alignment
20981            mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
20982        }
20983
20984        // Set the resolved
20985        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
20986        return true;
20987    }
20988
20989    /**
20990     * Check if text alignment resolution can be done.
20991     *
20992     * @return true if text alignment resolution can be done otherwise return false.
20993     */
20994    public boolean canResolveTextAlignment() {
20995        switch (getRawTextAlignment()) {
20996            case TEXT_DIRECTION_INHERIT:
20997                if (mParent != null) {
20998                    try {
20999                        return mParent.canResolveTextAlignment();
21000                    } catch (AbstractMethodError e) {
21001                        Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
21002                                " does not fully implement ViewParent", e);
21003                    }
21004                }
21005                return false;
21006
21007            default:
21008                return true;
21009        }
21010    }
21011
21012    /**
21013     * Reset resolved text alignment. Text alignment will be resolved during a call to
21014     * {@link #onMeasure(int, int)}.
21015     *
21016     * @hide
21017     */
21018    public void resetResolvedTextAlignment() {
21019        // Reset any previous text alignment resolution
21020        mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
21021        // Set to default
21022        mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
21023    }
21024
21025    /**
21026     * @return true if text alignment is inherited.
21027     *
21028     * @hide
21029     */
21030    public boolean isTextAlignmentInherited() {
21031        return (getRawTextAlignment() == TEXT_ALIGNMENT_INHERIT);
21032    }
21033
21034    /**
21035     * @return true if text alignment is resolved.
21036     */
21037    public boolean isTextAlignmentResolved() {
21038        return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) == PFLAG2_TEXT_ALIGNMENT_RESOLVED;
21039    }
21040
21041    /**
21042     * Generate a value suitable for use in {@link #setId(int)}.
21043     * This value will not collide with ID values generated at build time by aapt for R.id.
21044     *
21045     * @return a generated ID value
21046     */
21047    public static int generateViewId() {
21048        for (;;) {
21049            final int result = sNextGeneratedId.get();
21050            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
21051            int newValue = result + 1;
21052            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
21053            if (sNextGeneratedId.compareAndSet(result, newValue)) {
21054                return result;
21055            }
21056        }
21057    }
21058
21059    /**
21060     * Gets the Views in the hierarchy affected by entering and exiting Activity Scene transitions.
21061     * @param transitioningViews This View will be added to transitioningViews if it is VISIBLE and
21062     *                           a normal View or a ViewGroup with
21063     *                           {@link android.view.ViewGroup#isTransitionGroup()} true.
21064     * @hide
21065     */
21066    public void captureTransitioningViews(List<View> transitioningViews) {
21067        if (getVisibility() == View.VISIBLE) {
21068            transitioningViews.add(this);
21069        }
21070    }
21071
21072    /**
21073     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
21074     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
21075     * @hide
21076     */
21077    public void findNamedViews(Map<String, View> namedElements) {
21078        if (getVisibility() == VISIBLE || mGhostView != null) {
21079            String transitionName = getTransitionName();
21080            if (transitionName != null) {
21081                namedElements.put(transitionName, this);
21082            }
21083        }
21084    }
21085
21086    /** @hide */
21087    public int getPointerShape(MotionEvent event, float x, float y) {
21088        final int value = (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK);
21089        switch (value) {
21090            case PFLAG3_POINTER_ICON_NOT_SPECIFIED:
21091                return PointerIcon.STYLE_NOT_SPECIFIED;
21092            case PFLAG3_POINTER_ICON_NULL:
21093                return PointerIcon.STYLE_NULL;
21094            case PFLAG3_POINTER_ICON_CUSTOM:
21095                return PointerIcon.STYLE_CUSTOM;
21096            default:
21097                return ((value - PFLAG3_POINTER_ICON_VALUE_START) >> PFLAG3_POINTER_ICON_LSHIFT)
21098                        + PointerIcon.STYLE_ARROW;
21099        }
21100    }
21101
21102    /** @hide */
21103    public void setPointerShape(int pointerShape) {
21104        int newValue;
21105        if (pointerShape == PointerIcon.STYLE_NOT_SPECIFIED) {
21106            newValue = PFLAG3_POINTER_ICON_NOT_SPECIFIED;
21107        } else if (pointerShape == PointerIcon.STYLE_NULL) {
21108            newValue = PFLAG3_POINTER_ICON_NULL;
21109        } else if (pointerShape == PointerIcon.STYLE_CUSTOM) {
21110            newValue = PFLAG3_POINTER_ICON_CUSTOM;
21111        } else if (pointerShape >= PointerIcon.STYLE_ARROW
21112                && pointerShape <= PointerIcon.STYLE_GRABBING) {
21113            newValue = ((pointerShape - PointerIcon.STYLE_ARROW) << PFLAG3_POINTER_ICON_LSHIFT)
21114                    + PFLAG3_POINTER_ICON_VALUE_START;
21115        } else {
21116            Log.w(VIEW_LOG_TAG, "Invalid pointer shape " + pointerShape + " is specified.");
21117            return;
21118        }
21119        if (newValue != (mPrivateFlags3 & PFLAG3_POINTER_ICON_MASK)) {
21120            mPrivateFlags3 = (mPrivateFlags3 & ~PFLAG3_POINTER_ICON_MASK) | newValue;
21121        }
21122    }
21123
21124    //
21125    // Properties
21126    //
21127    /**
21128     * A Property wrapper around the <code>alpha</code> functionality handled by the
21129     * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
21130     */
21131    public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
21132        @Override
21133        public void setValue(View object, float value) {
21134            object.setAlpha(value);
21135        }
21136
21137        @Override
21138        public Float get(View object) {
21139            return object.getAlpha();
21140        }
21141    };
21142
21143    /**
21144     * A Property wrapper around the <code>translationX</code> functionality handled by the
21145     * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
21146     */
21147    public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
21148        @Override
21149        public void setValue(View object, float value) {
21150            object.setTranslationX(value);
21151        }
21152
21153                @Override
21154        public Float get(View object) {
21155            return object.getTranslationX();
21156        }
21157    };
21158
21159    /**
21160     * A Property wrapper around the <code>translationY</code> functionality handled by the
21161     * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
21162     */
21163    public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
21164        @Override
21165        public void setValue(View object, float value) {
21166            object.setTranslationY(value);
21167        }
21168
21169        @Override
21170        public Float get(View object) {
21171            return object.getTranslationY();
21172        }
21173    };
21174
21175    /**
21176     * A Property wrapper around the <code>translationZ</code> functionality handled by the
21177     * {@link View#setTranslationZ(float)} and {@link View#getTranslationZ()} methods.
21178     */
21179    public static final Property<View, Float> TRANSLATION_Z = new FloatProperty<View>("translationZ") {
21180        @Override
21181        public void setValue(View object, float value) {
21182            object.setTranslationZ(value);
21183        }
21184
21185        @Override
21186        public Float get(View object) {
21187            return object.getTranslationZ();
21188        }
21189    };
21190
21191    /**
21192     * A Property wrapper around the <code>x</code> functionality handled by the
21193     * {@link View#setX(float)} and {@link View#getX()} methods.
21194     */
21195    public static final Property<View, Float> X = new FloatProperty<View>("x") {
21196        @Override
21197        public void setValue(View object, float value) {
21198            object.setX(value);
21199        }
21200
21201        @Override
21202        public Float get(View object) {
21203            return object.getX();
21204        }
21205    };
21206
21207    /**
21208     * A Property wrapper around the <code>y</code> functionality handled by the
21209     * {@link View#setY(float)} and {@link View#getY()} methods.
21210     */
21211    public static final Property<View, Float> Y = new FloatProperty<View>("y") {
21212        @Override
21213        public void setValue(View object, float value) {
21214            object.setY(value);
21215        }
21216
21217        @Override
21218        public Float get(View object) {
21219            return object.getY();
21220        }
21221    };
21222
21223    /**
21224     * A Property wrapper around the <code>z</code> functionality handled by the
21225     * {@link View#setZ(float)} and {@link View#getZ()} methods.
21226     */
21227    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
21228        @Override
21229        public void setValue(View object, float value) {
21230            object.setZ(value);
21231        }
21232
21233        @Override
21234        public Float get(View object) {
21235            return object.getZ();
21236        }
21237    };
21238
21239    /**
21240     * A Property wrapper around the <code>rotation</code> functionality handled by the
21241     * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
21242     */
21243    public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
21244        @Override
21245        public void setValue(View object, float value) {
21246            object.setRotation(value);
21247        }
21248
21249        @Override
21250        public Float get(View object) {
21251            return object.getRotation();
21252        }
21253    };
21254
21255    /**
21256     * A Property wrapper around the <code>rotationX</code> functionality handled by the
21257     * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
21258     */
21259    public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
21260        @Override
21261        public void setValue(View object, float value) {
21262            object.setRotationX(value);
21263        }
21264
21265        @Override
21266        public Float get(View object) {
21267            return object.getRotationX();
21268        }
21269    };
21270
21271    /**
21272     * A Property wrapper around the <code>rotationY</code> functionality handled by the
21273     * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
21274     */
21275    public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
21276        @Override
21277        public void setValue(View object, float value) {
21278            object.setRotationY(value);
21279        }
21280
21281        @Override
21282        public Float get(View object) {
21283            return object.getRotationY();
21284        }
21285    };
21286
21287    /**
21288     * A Property wrapper around the <code>scaleX</code> functionality handled by the
21289     * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
21290     */
21291    public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
21292        @Override
21293        public void setValue(View object, float value) {
21294            object.setScaleX(value);
21295        }
21296
21297        @Override
21298        public Float get(View object) {
21299            return object.getScaleX();
21300        }
21301    };
21302
21303    /**
21304     * A Property wrapper around the <code>scaleY</code> functionality handled by the
21305     * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
21306     */
21307    public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
21308        @Override
21309        public void setValue(View object, float value) {
21310            object.setScaleY(value);
21311        }
21312
21313        @Override
21314        public Float get(View object) {
21315            return object.getScaleY();
21316        }
21317    };
21318
21319    /**
21320     * A MeasureSpec encapsulates the layout requirements passed from parent to child.
21321     * Each MeasureSpec represents a requirement for either the width or the height.
21322     * A MeasureSpec is comprised of a size and a mode. There are three possible
21323     * modes:
21324     * <dl>
21325     * <dt>UNSPECIFIED</dt>
21326     * <dd>
21327     * The parent has not imposed any constraint on the child. It can be whatever size
21328     * it wants.
21329     * </dd>
21330     *
21331     * <dt>EXACTLY</dt>
21332     * <dd>
21333     * The parent has determined an exact size for the child. The child is going to be
21334     * given those bounds regardless of how big it wants to be.
21335     * </dd>
21336     *
21337     * <dt>AT_MOST</dt>
21338     * <dd>
21339     * The child can be as large as it wants up to the specified size.
21340     * </dd>
21341     * </dl>
21342     *
21343     * MeasureSpecs are implemented as ints to reduce object allocation. This class
21344     * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
21345     */
21346    public static class MeasureSpec {
21347        private static final int MODE_SHIFT = 30;
21348        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
21349
21350        /**
21351         * Measure specification mode: The parent has not imposed any constraint
21352         * on the child. It can be whatever size it wants.
21353         */
21354        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
21355
21356        /**
21357         * Measure specification mode: The parent has determined an exact size
21358         * for the child. The child is going to be given those bounds regardless
21359         * of how big it wants to be.
21360         */
21361        public static final int EXACTLY     = 1 << MODE_SHIFT;
21362
21363        /**
21364         * Measure specification mode: The child can be as large as it wants up
21365         * to the specified size.
21366         */
21367        public static final int AT_MOST     = 2 << MODE_SHIFT;
21368
21369        /**
21370         * Creates a measure specification based on the supplied size and mode.
21371         *
21372         * The mode must always be one of the following:
21373         * <ul>
21374         *  <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
21375         *  <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
21376         *  <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
21377         * </ul>
21378         *
21379         * <p><strong>Note:</strong> On API level 17 and lower, makeMeasureSpec's
21380         * implementation was such that the order of arguments did not matter
21381         * and overflow in either value could impact the resulting MeasureSpec.
21382         * {@link android.widget.RelativeLayout} was affected by this bug.
21383         * Apps targeting API levels greater than 17 will get the fixed, more strict
21384         * behavior.</p>
21385         *
21386         * @param size the size of the measure specification
21387         * @param mode the mode of the measure specification
21388         * @return the measure specification based on size and mode
21389         */
21390        public static int makeMeasureSpec(int size, int mode) {
21391            if (sUseBrokenMakeMeasureSpec) {
21392                return size + mode;
21393            } else {
21394                return (size & ~MODE_MASK) | (mode & MODE_MASK);
21395            }
21396        }
21397
21398        /**
21399         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
21400         * will automatically get a size of 0. Older apps expect this.
21401         *
21402         * @hide internal use only for compatibility with system widgets and older apps
21403         */
21404        public static int makeSafeMeasureSpec(int size, int mode) {
21405            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
21406                return 0;
21407            }
21408            return makeMeasureSpec(size, mode);
21409        }
21410
21411        /**
21412         * Extracts the mode from the supplied measure specification.
21413         *
21414         * @param measureSpec the measure specification to extract the mode from
21415         * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
21416         *         {@link android.view.View.MeasureSpec#AT_MOST} or
21417         *         {@link android.view.View.MeasureSpec#EXACTLY}
21418         */
21419        public static int getMode(int measureSpec) {
21420            return (measureSpec & MODE_MASK);
21421        }
21422
21423        /**
21424         * Extracts the size from the supplied measure specification.
21425         *
21426         * @param measureSpec the measure specification to extract the size from
21427         * @return the size in pixels defined in the supplied measure specification
21428         */
21429        public static int getSize(int measureSpec) {
21430            return (measureSpec & ~MODE_MASK);
21431        }
21432
21433        static int adjust(int measureSpec, int delta) {
21434            final int mode = getMode(measureSpec);
21435            int size = getSize(measureSpec);
21436            if (mode == UNSPECIFIED) {
21437                // No need to adjust size for UNSPECIFIED mode.
21438                return makeMeasureSpec(size, UNSPECIFIED);
21439            }
21440            size += delta;
21441            if (size < 0) {
21442                Log.e(VIEW_LOG_TAG, "MeasureSpec.adjust: new size would be negative! (" + size +
21443                        ") spec: " + toString(measureSpec) + " delta: " + delta);
21444                size = 0;
21445            }
21446            return makeMeasureSpec(size, mode);
21447        }
21448
21449        /**
21450         * Returns a String representation of the specified measure
21451         * specification.
21452         *
21453         * @param measureSpec the measure specification to convert to a String
21454         * @return a String with the following format: "MeasureSpec: MODE SIZE"
21455         */
21456        public static String toString(int measureSpec) {
21457            int mode = getMode(measureSpec);
21458            int size = getSize(measureSpec);
21459
21460            StringBuilder sb = new StringBuilder("MeasureSpec: ");
21461
21462            if (mode == UNSPECIFIED)
21463                sb.append("UNSPECIFIED ");
21464            else if (mode == EXACTLY)
21465                sb.append("EXACTLY ");
21466            else if (mode == AT_MOST)
21467                sb.append("AT_MOST ");
21468            else
21469                sb.append(mode).append(" ");
21470
21471            sb.append(size);
21472            return sb.toString();
21473        }
21474    }
21475
21476    private final class CheckForLongPress implements Runnable {
21477        private int mOriginalWindowAttachCount;
21478        private float mX;
21479        private float mY;
21480
21481        @Override
21482        public void run() {
21483            if (isPressed() && (mParent != null)
21484                    && mOriginalWindowAttachCount == mWindowAttachCount) {
21485                if (performLongClick(mX, mY)) {
21486                    mHasPerformedLongPress = true;
21487                }
21488            }
21489        }
21490
21491        public void setAnchor(float x, float y) {
21492            mX = x;
21493            mY = y;
21494        }
21495
21496        public void rememberWindowAttachCount() {
21497            mOriginalWindowAttachCount = mWindowAttachCount;
21498        }
21499    }
21500
21501    private final class CheckForTap implements Runnable {
21502        public float x;
21503        public float y;
21504
21505        @Override
21506        public void run() {
21507            mPrivateFlags &= ~PFLAG_PREPRESSED;
21508            setPressed(true, x, y);
21509            checkForLongClick(ViewConfiguration.getTapTimeout(), x, y);
21510        }
21511    }
21512
21513    private final class PerformClick implements Runnable {
21514        @Override
21515        public void run() {
21516            performClick();
21517        }
21518    }
21519
21520    /**
21521     * This method returns a ViewPropertyAnimator object, which can be used to animate
21522     * specific properties on this View.
21523     *
21524     * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
21525     */
21526    public ViewPropertyAnimator animate() {
21527        if (mAnimator == null) {
21528            mAnimator = new ViewPropertyAnimator(this);
21529        }
21530        return mAnimator;
21531    }
21532
21533    /**
21534     * Sets the name of the View to be used to identify Views in Transitions.
21535     * Names should be unique in the View hierarchy.
21536     *
21537     * @param transitionName The name of the View to uniquely identify it for Transitions.
21538     */
21539    public final void setTransitionName(String transitionName) {
21540        mTransitionName = transitionName;
21541    }
21542
21543    /**
21544     * Returns the name of the View to be used to identify Views in Transitions.
21545     * Names should be unique in the View hierarchy.
21546     *
21547     * <p>This returns null if the View has not been given a name.</p>
21548     *
21549     * @return The name used of the View to be used to identify Views in Transitions or null
21550     * if no name has been given.
21551     */
21552    @ViewDebug.ExportedProperty
21553    public String getTransitionName() {
21554        return mTransitionName;
21555    }
21556
21557    /**
21558     * Interface definition for a callback to be invoked when a hardware key event is
21559     * dispatched to this view. The callback will be invoked before the key event is
21560     * given to the view. This is only useful for hardware keyboards; a software input
21561     * method has no obligation to trigger this listener.
21562     */
21563    public interface OnKeyListener {
21564        /**
21565         * Called when a hardware key is dispatched to a view. This allows listeners to
21566         * get a chance to respond before the target view.
21567         * <p>Key presses in software keyboards will generally NOT trigger this method,
21568         * although some may elect to do so in some situations. Do not assume a
21569         * software input method has to be key-based; even if it is, it may use key presses
21570         * in a different way than you expect, so there is no way to reliably catch soft
21571         * input key presses.
21572         *
21573         * @param v The view the key has been dispatched to.
21574         * @param keyCode The code for the physical key that was pressed
21575         * @param event The KeyEvent object containing full information about
21576         *        the event.
21577         * @return True if the listener has consumed the event, false otherwise.
21578         */
21579        boolean onKey(View v, int keyCode, KeyEvent event);
21580    }
21581
21582    /**
21583     * Interface definition for a callback to be invoked when a touch event is
21584     * dispatched to this view. The callback will be invoked before the touch
21585     * event is given to the view.
21586     */
21587    public interface OnTouchListener {
21588        /**
21589         * Called when a touch event is dispatched to a view. This allows listeners to
21590         * get a chance to respond before the target view.
21591         *
21592         * @param v The view the touch event has been dispatched to.
21593         * @param event The MotionEvent object containing full information about
21594         *        the event.
21595         * @return True if the listener has consumed the event, false otherwise.
21596         */
21597        boolean onTouch(View v, MotionEvent event);
21598    }
21599
21600    /**
21601     * Interface definition for a callback to be invoked when a hover event is
21602     * dispatched to this view. The callback will be invoked before the hover
21603     * event is given to the view.
21604     */
21605    public interface OnHoverListener {
21606        /**
21607         * Called when a hover event is dispatched to a view. This allows listeners to
21608         * get a chance to respond before the target view.
21609         *
21610         * @param v The view the hover event has been dispatched to.
21611         * @param event The MotionEvent object containing full information about
21612         *        the event.
21613         * @return True if the listener has consumed the event, false otherwise.
21614         */
21615        boolean onHover(View v, MotionEvent event);
21616    }
21617
21618    /**
21619     * Interface definition for a callback to be invoked when a generic motion event is
21620     * dispatched to this view. The callback will be invoked before the generic motion
21621     * event is given to the view.
21622     */
21623    public interface OnGenericMotionListener {
21624        /**
21625         * Called when a generic motion event is dispatched to a view. This allows listeners to
21626         * get a chance to respond before the target view.
21627         *
21628         * @param v The view the generic motion event has been dispatched to.
21629         * @param event The MotionEvent object containing full information about
21630         *        the event.
21631         * @return True if the listener has consumed the event, false otherwise.
21632         */
21633        boolean onGenericMotion(View v, MotionEvent event);
21634    }
21635
21636    /**
21637     * Interface definition for a callback to be invoked when a view has been clicked and held.
21638     */
21639    public interface OnLongClickListener {
21640        /**
21641         * Called when a view has been clicked and held.
21642         *
21643         * @param v The view that was clicked and held.
21644         *
21645         * @return true if the callback consumed the long click, false otherwise.
21646         */
21647        boolean onLongClick(View v);
21648    }
21649
21650    /**
21651     * Interface definition for a callback to be invoked when a drag is being dispatched
21652     * to this view.  The callback will be invoked before the hosting view's own
21653     * onDrag(event) method.  If the listener wants to fall back to the hosting view's
21654     * onDrag(event) behavior, it should return 'false' from this callback.
21655     *
21656     * <div class="special reference">
21657     * <h3>Developer Guides</h3>
21658     * <p>For a guide to implementing drag and drop features, read the
21659     * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
21660     * </div>
21661     */
21662    public interface OnDragListener {
21663        /**
21664         * Called when a drag event is dispatched to a view. This allows listeners
21665         * to get a chance to override base View behavior.
21666         *
21667         * @param v The View that received the drag event.
21668         * @param event The {@link android.view.DragEvent} object for the drag event.
21669         * @return {@code true} if the drag event was handled successfully, or {@code false}
21670         * if the drag event was not handled. Note that {@code false} will trigger the View
21671         * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
21672         */
21673        boolean onDrag(View v, DragEvent event);
21674    }
21675
21676    /**
21677     * Interface definition for a callback to be invoked when the focus state of
21678     * a view changed.
21679     */
21680    public interface OnFocusChangeListener {
21681        /**
21682         * Called when the focus state of a view has changed.
21683         *
21684         * @param v The view whose state has changed.
21685         * @param hasFocus The new focus state of v.
21686         */
21687        void onFocusChange(View v, boolean hasFocus);
21688    }
21689
21690    /**
21691     * Interface definition for a callback to be invoked when a view is clicked.
21692     */
21693    public interface OnClickListener {
21694        /**
21695         * Called when a view has been clicked.
21696         *
21697         * @param v The view that was clicked.
21698         */
21699        void onClick(View v);
21700    }
21701
21702    /**
21703     * Interface definition for a callback to be invoked when a view is context clicked.
21704     */
21705    public interface OnContextClickListener {
21706        /**
21707         * Called when a view is context clicked.
21708         *
21709         * @param v The view that has been context clicked.
21710         * @return true if the callback consumed the context click, false otherwise.
21711         */
21712        boolean onContextClick(View v);
21713    }
21714
21715    /**
21716     * Interface definition for a callback to be invoked when the context menu
21717     * for this view is being built.
21718     */
21719    public interface OnCreateContextMenuListener {
21720        /**
21721         * Called when the context menu for this view is being built. It is not
21722         * safe to hold onto the menu after this method returns.
21723         *
21724         * @param menu The context menu that is being built
21725         * @param v The view for which the context menu is being built
21726         * @param menuInfo Extra information about the item for which the
21727         *            context menu should be shown. This information will vary
21728         *            depending on the class of v.
21729         */
21730        void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
21731    }
21732
21733    /**
21734     * Interface definition for a callback to be invoked when the status bar changes
21735     * visibility.  This reports <strong>global</strong> changes to the system UI
21736     * state, not what the application is requesting.
21737     *
21738     * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
21739     */
21740    public interface OnSystemUiVisibilityChangeListener {
21741        /**
21742         * Called when the status bar changes visibility because of a call to
21743         * {@link View#setSystemUiVisibility(int)}.
21744         *
21745         * @param visibility  Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
21746         * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
21747         * This tells you the <strong>global</strong> state of these UI visibility
21748         * flags, not what your app is currently applying.
21749         */
21750        public void onSystemUiVisibilityChange(int visibility);
21751    }
21752
21753    /**
21754     * Interface definition for a callback to be invoked when this view is attached
21755     * or detached from its window.
21756     */
21757    public interface OnAttachStateChangeListener {
21758        /**
21759         * Called when the view is attached to a window.
21760         * @param v The view that was attached
21761         */
21762        public void onViewAttachedToWindow(View v);
21763        /**
21764         * Called when the view is detached from a window.
21765         * @param v The view that was detached
21766         */
21767        public void onViewDetachedFromWindow(View v);
21768    }
21769
21770    /**
21771     * Listener for applying window insets on a view in a custom way.
21772     *
21773     * <p>Apps may choose to implement this interface if they want to apply custom policy
21774     * to the way that window insets are treated for a view. If an OnApplyWindowInsetsListener
21775     * is set, its
21776     * {@link OnApplyWindowInsetsListener#onApplyWindowInsets(View, WindowInsets) onApplyWindowInsets}
21777     * method will be called instead of the View's own
21778     * {@link #onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method. The listener
21779     * may optionally call the parameter View's <code>onApplyWindowInsets</code> method to apply
21780     * the View's normal behavior as part of its own.</p>
21781     */
21782    public interface OnApplyWindowInsetsListener {
21783        /**
21784         * When {@link View#setOnApplyWindowInsetsListener(View.OnApplyWindowInsetsListener) set}
21785         * on a View, this listener method will be called instead of the view's own
21786         * {@link View#onApplyWindowInsets(WindowInsets) onApplyWindowInsets} method.
21787         *
21788         * @param v The view applying window insets
21789         * @param insets The insets to apply
21790         * @return The insets supplied, minus any insets that were consumed
21791         */
21792        public WindowInsets onApplyWindowInsets(View v, WindowInsets insets);
21793    }
21794
21795    private final class UnsetPressedState implements Runnable {
21796        @Override
21797        public void run() {
21798            setPressed(false);
21799        }
21800    }
21801
21802    /**
21803     * Base class for derived classes that want to save and restore their own
21804     * state in {@link android.view.View#onSaveInstanceState()}.
21805     */
21806    public static class BaseSavedState extends AbsSavedState {
21807        String mStartActivityRequestWhoSaved;
21808
21809        /**
21810         * Constructor used when reading from a parcel. Reads the state of the superclass.
21811         *
21812         * @param source
21813         */
21814        public BaseSavedState(Parcel source) {
21815            super(source);
21816            mStartActivityRequestWhoSaved = source.readString();
21817        }
21818
21819        /**
21820         * Constructor called by derived classes when creating their SavedState objects
21821         *
21822         * @param superState The state of the superclass of this view
21823         */
21824        public BaseSavedState(Parcelable superState) {
21825            super(superState);
21826        }
21827
21828        @Override
21829        public void writeToParcel(Parcel out, int flags) {
21830            super.writeToParcel(out, flags);
21831            out.writeString(mStartActivityRequestWhoSaved);
21832        }
21833
21834        public static final Parcelable.Creator<BaseSavedState> CREATOR =
21835                new Parcelable.Creator<BaseSavedState>() {
21836            public BaseSavedState createFromParcel(Parcel in) {
21837                return new BaseSavedState(in);
21838            }
21839
21840            public BaseSavedState[] newArray(int size) {
21841                return new BaseSavedState[size];
21842            }
21843        };
21844    }
21845
21846    /**
21847     * A set of information given to a view when it is attached to its parent
21848     * window.
21849     */
21850    final static class AttachInfo {
21851        interface Callbacks {
21852            void playSoundEffect(int effectId);
21853            boolean performHapticFeedback(int effectId, boolean always);
21854        }
21855
21856        /**
21857         * InvalidateInfo is used to post invalidate(int, int, int, int) messages
21858         * to a Handler. This class contains the target (View) to invalidate and
21859         * the coordinates of the dirty rectangle.
21860         *
21861         * For performance purposes, this class also implements a pool of up to
21862         * POOL_LIMIT objects that get reused. This reduces memory allocations
21863         * whenever possible.
21864         */
21865        static class InvalidateInfo {
21866            private static final int POOL_LIMIT = 10;
21867
21868            private static final SynchronizedPool<InvalidateInfo> sPool =
21869                    new SynchronizedPool<InvalidateInfo>(POOL_LIMIT);
21870
21871            View target;
21872
21873            int left;
21874            int top;
21875            int right;
21876            int bottom;
21877
21878            public static InvalidateInfo obtain() {
21879                InvalidateInfo instance = sPool.acquire();
21880                return (instance != null) ? instance : new InvalidateInfo();
21881            }
21882
21883            public void recycle() {
21884                target = null;
21885                sPool.release(this);
21886            }
21887        }
21888
21889        final IWindowSession mSession;
21890
21891        final IWindow mWindow;
21892
21893        final IBinder mWindowToken;
21894
21895        final Display mDisplay;
21896
21897        final Callbacks mRootCallbacks;
21898
21899        IWindowId mIWindowId;
21900        WindowId mWindowId;
21901
21902        /**
21903         * The top view of the hierarchy.
21904         */
21905        View mRootView;
21906
21907        IBinder mPanelParentWindowToken;
21908
21909        boolean mHardwareAccelerated;
21910        boolean mHardwareAccelerationRequested;
21911        HardwareRenderer mHardwareRenderer;
21912        List<RenderNode> mPendingAnimatingRenderNodes;
21913
21914        /**
21915         * The state of the display to which the window is attached, as reported
21916         * by {@link Display#getState()}.  Note that the display state constants
21917         * declared by {@link Display} do not exactly line up with the screen state
21918         * constants declared by {@link View} (there are more display states than
21919         * screen states).
21920         */
21921        int mDisplayState = Display.STATE_UNKNOWN;
21922
21923        /**
21924         * Scale factor used by the compatibility mode
21925         */
21926        float mApplicationScale;
21927
21928        /**
21929         * Indicates whether the application is in compatibility mode
21930         */
21931        boolean mScalingRequired;
21932
21933        /**
21934         * Left position of this view's window
21935         */
21936        int mWindowLeft;
21937
21938        /**
21939         * Top position of this view's window
21940         */
21941        int mWindowTop;
21942
21943        /**
21944         * Indicates whether views need to use 32-bit drawing caches
21945         */
21946        boolean mUse32BitDrawingCache;
21947
21948        /**
21949         * For windows that are full-screen but using insets to layout inside
21950         * of the screen areas, these are the current insets to appear inside
21951         * the overscan area of the display.
21952         */
21953        final Rect mOverscanInsets = new Rect();
21954
21955        /**
21956         * For windows that are full-screen but using insets to layout inside
21957         * of the screen decorations, these are the current insets for the
21958         * content of the window.
21959         */
21960        final Rect mContentInsets = new Rect();
21961
21962        /**
21963         * For windows that are full-screen but using insets to layout inside
21964         * of the screen decorations, these are the current insets for the
21965         * actual visible parts of the window.
21966         */
21967        final Rect mVisibleInsets = new Rect();
21968
21969        /**
21970         * For windows that are full-screen but using insets to layout inside
21971         * of the screen decorations, these are the current insets for the
21972         * stable system windows.
21973         */
21974        final Rect mStableInsets = new Rect();
21975
21976        /**
21977         * For windows that include areas that are not covered by real surface these are the outsets
21978         * for real surface.
21979         */
21980        final Rect mOutsets = new Rect();
21981
21982        /**
21983         * The internal insets given by this window.  This value is
21984         * supplied by the client (through
21985         * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
21986         * be given to the window manager when changed to be used in laying
21987         * out windows behind it.
21988         */
21989        final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
21990                = new ViewTreeObserver.InternalInsetsInfo();
21991
21992        /**
21993         * Set to true when mGivenInternalInsets is non-empty.
21994         */
21995        boolean mHasNonEmptyGivenInternalInsets;
21996
21997        /**
21998         * All views in the window's hierarchy that serve as scroll containers,
21999         * used to determine if the window can be resized or must be panned
22000         * to adjust for a soft input area.
22001         */
22002        final ArrayList<View> mScrollContainers = new ArrayList<View>();
22003
22004        final KeyEvent.DispatcherState mKeyDispatchState
22005                = new KeyEvent.DispatcherState();
22006
22007        /**
22008         * Indicates whether the view's window currently has the focus.
22009         */
22010        boolean mHasWindowFocus;
22011
22012        /**
22013         * The current visibility of the window.
22014         */
22015        int mWindowVisibility;
22016
22017        /**
22018         * Indicates the time at which drawing started to occur.
22019         */
22020        long mDrawingTime;
22021
22022        /**
22023         * Indicates whether or not ignoring the DIRTY_MASK flags.
22024         */
22025        boolean mIgnoreDirtyState;
22026
22027        /**
22028         * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
22029         * to avoid clearing that flag prematurely.
22030         */
22031        boolean mSetIgnoreDirtyState = false;
22032
22033        /**
22034         * Indicates whether the view's window is currently in touch mode.
22035         */
22036        boolean mInTouchMode;
22037
22038        /**
22039         * Indicates whether the view has requested unbuffered input dispatching for the current
22040         * event stream.
22041         */
22042        boolean mUnbufferedDispatchRequested;
22043
22044        /**
22045         * Indicates that ViewAncestor should trigger a global layout change
22046         * the next time it performs a traversal
22047         */
22048        boolean mRecomputeGlobalAttributes;
22049
22050        /**
22051         * Always report new attributes at next traversal.
22052         */
22053        boolean mForceReportNewAttributes;
22054
22055        /**
22056         * Set during a traveral if any views want to keep the screen on.
22057         */
22058        boolean mKeepScreenOn;
22059
22060        /**
22061         * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
22062         */
22063        int mSystemUiVisibility;
22064
22065        /**
22066         * Hack to force certain system UI visibility flags to be cleared.
22067         */
22068        int mDisabledSystemUiVisibility;
22069
22070        /**
22071         * Last global system UI visibility reported by the window manager.
22072         */
22073        int mGlobalSystemUiVisibility;
22074
22075        /**
22076         * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
22077         * attached.
22078         */
22079        boolean mHasSystemUiListeners;
22080
22081        /**
22082         * Set if the window has requested to extend into the overscan region
22083         * via WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN.
22084         */
22085        boolean mOverscanRequested;
22086
22087        /**
22088         * Set if the visibility of any views has changed.
22089         */
22090        boolean mViewVisibilityChanged;
22091
22092        /**
22093         * Set to true if a view has been scrolled.
22094         */
22095        boolean mViewScrollChanged;
22096
22097        /**
22098         * Set to true if high contrast mode enabled
22099         */
22100        boolean mHighContrastText;
22101
22102        /**
22103         * Global to the view hierarchy used as a temporary for dealing with
22104         * x/y points in the transparent region computations.
22105         */
22106        final int[] mTransparentLocation = new int[2];
22107
22108        /**
22109         * Global to the view hierarchy used as a temporary for dealing with
22110         * x/y points in the ViewGroup.invalidateChild implementation.
22111         */
22112        final int[] mInvalidateChildLocation = new int[2];
22113
22114        /**
22115         * Global to the view hierarchy used as a temporary for dealng with
22116         * computing absolute on-screen location.
22117         */
22118        final int[] mTmpLocation = new int[2];
22119
22120        /**
22121         * Global to the view hierarchy used as a temporary for dealing with
22122         * x/y location when view is transformed.
22123         */
22124        final float[] mTmpTransformLocation = new float[2];
22125
22126        /**
22127         * The view tree observer used to dispatch global events like
22128         * layout, pre-draw, touch mode change, etc.
22129         */
22130        final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
22131
22132        /**
22133         * A Canvas used by the view hierarchy to perform bitmap caching.
22134         */
22135        Canvas mCanvas;
22136
22137        /**
22138         * The view root impl.
22139         */
22140        final ViewRootImpl mViewRootImpl;
22141
22142        /**
22143         * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
22144         * handler can be used to pump events in the UI events queue.
22145         */
22146        final Handler mHandler;
22147
22148        /**
22149         * Temporary for use in computing invalidate rectangles while
22150         * calling up the hierarchy.
22151         */
22152        final Rect mTmpInvalRect = new Rect();
22153
22154        /**
22155         * Temporary for use in computing hit areas with transformed views
22156         */
22157        final RectF mTmpTransformRect = new RectF();
22158
22159        /**
22160         * Temporary for use in computing hit areas with transformed views
22161         */
22162        final RectF mTmpTransformRect1 = new RectF();
22163
22164        /**
22165         * Temporary list of rectanges.
22166         */
22167        final List<RectF> mTmpRectList = new ArrayList<>();
22168
22169        /**
22170         * Temporary for use in transforming invalidation rect
22171         */
22172        final Matrix mTmpMatrix = new Matrix();
22173
22174        /**
22175         * Temporary for use in transforming invalidation rect
22176         */
22177        final Transformation mTmpTransformation = new Transformation();
22178
22179        /**
22180         * Temporary for use in querying outlines from OutlineProviders
22181         */
22182        final Outline mTmpOutline = new Outline();
22183
22184        /**
22185         * Temporary list for use in collecting focusable descendents of a view.
22186         */
22187        final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
22188
22189        /**
22190         * The id of the window for accessibility purposes.
22191         */
22192        int mAccessibilityWindowId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
22193
22194        /**
22195         * Flags related to accessibility processing.
22196         *
22197         * @see AccessibilityNodeInfo#FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
22198         * @see AccessibilityNodeInfo#FLAG_REPORT_VIEW_IDS
22199         */
22200        int mAccessibilityFetchFlags;
22201
22202        /**
22203         * The drawable for highlighting accessibility focus.
22204         */
22205        Drawable mAccessibilityFocusDrawable;
22206
22207        /**
22208         * Show where the margins, bounds and layout bounds are for each view.
22209         */
22210        boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
22211
22212        /**
22213         * Point used to compute visible regions.
22214         */
22215        final Point mPoint = new Point();
22216
22217        /**
22218         * Used to track which View originated a requestLayout() call, used when
22219         * requestLayout() is called during layout.
22220         */
22221        View mViewRequestingLayout;
22222
22223        /**
22224         * Creates a new set of attachment information with the specified
22225         * events handler and thread.
22226         *
22227         * @param handler the events handler the view must use
22228         */
22229        AttachInfo(IWindowSession session, IWindow window, Display display,
22230                ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
22231            mSession = session;
22232            mWindow = window;
22233            mWindowToken = window.asBinder();
22234            mDisplay = display;
22235            mViewRootImpl = viewRootImpl;
22236            mHandler = handler;
22237            mRootCallbacks = effectPlayer;
22238        }
22239    }
22240
22241    /**
22242     * <p>ScrollabilityCache holds various fields used by a View when scrolling
22243     * is supported. This avoids keeping too many unused fields in most
22244     * instances of View.</p>
22245     */
22246    private static class ScrollabilityCache implements Runnable {
22247
22248        /**
22249         * Scrollbars are not visible
22250         */
22251        public static final int OFF = 0;
22252
22253        /**
22254         * Scrollbars are visible
22255         */
22256        public static final int ON = 1;
22257
22258        /**
22259         * Scrollbars are fading away
22260         */
22261        public static final int FADING = 2;
22262
22263        public boolean fadeScrollBars;
22264
22265        public int fadingEdgeLength;
22266        public int scrollBarDefaultDelayBeforeFade;
22267        public int scrollBarFadeDuration;
22268
22269        public int scrollBarSize;
22270        public ScrollBarDrawable scrollBar;
22271        public float[] interpolatorValues;
22272        public View host;
22273
22274        public final Paint paint;
22275        public final Matrix matrix;
22276        public Shader shader;
22277
22278        public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
22279
22280        private static final float[] OPAQUE = { 255 };
22281        private static final float[] TRANSPARENT = { 0.0f };
22282
22283        /**
22284         * When fading should start. This time moves into the future every time
22285         * a new scroll happens. Measured based on SystemClock.uptimeMillis()
22286         */
22287        public long fadeStartTime;
22288
22289
22290        /**
22291         * The current state of the scrollbars: ON, OFF, or FADING
22292         */
22293        public int state = OFF;
22294
22295        private int mLastColor;
22296
22297        public ScrollabilityCache(ViewConfiguration configuration, View host) {
22298            fadingEdgeLength = configuration.getScaledFadingEdgeLength();
22299            scrollBarSize = configuration.getScaledScrollBarSize();
22300            scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
22301            scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
22302
22303            paint = new Paint();
22304            matrix = new Matrix();
22305            // use use a height of 1, and then wack the matrix each time we
22306            // actually use it.
22307            shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22308            paint.setShader(shader);
22309            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22310
22311            this.host = host;
22312        }
22313
22314        public void setFadeColor(int color) {
22315            if (color != mLastColor) {
22316                mLastColor = color;
22317
22318                if (color != 0) {
22319                    shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
22320                            color & 0x00FFFFFF, Shader.TileMode.CLAMP);
22321                    paint.setShader(shader);
22322                    // Restore the default transfer mode (src_over)
22323                    paint.setXfermode(null);
22324                } else {
22325                    shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
22326                    paint.setShader(shader);
22327                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
22328                }
22329            }
22330        }
22331
22332        public void run() {
22333            long now = AnimationUtils.currentAnimationTimeMillis();
22334            if (now >= fadeStartTime) {
22335
22336                // the animation fades the scrollbars out by changing
22337                // the opacity (alpha) from fully opaque to fully
22338                // transparent
22339                int nextFrame = (int) now;
22340                int framesCount = 0;
22341
22342                Interpolator interpolator = scrollBarInterpolator;
22343
22344                // Start opaque
22345                interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
22346
22347                // End transparent
22348                nextFrame += scrollBarFadeDuration;
22349                interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
22350
22351                state = FADING;
22352
22353                // Kick off the fade animation
22354                host.invalidate(true);
22355            }
22356        }
22357    }
22358
22359    /**
22360     * Resuable callback for sending
22361     * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
22362     */
22363    private class SendViewScrolledAccessibilityEvent implements Runnable {
22364        public volatile boolean mIsPending;
22365
22366        public void run() {
22367            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
22368            mIsPending = false;
22369        }
22370    }
22371
22372    /**
22373     * <p>
22374     * This class represents a delegate that can be registered in a {@link View}
22375     * to enhance accessibility support via composition rather via inheritance.
22376     * It is specifically targeted to widget developers that extend basic View
22377     * classes i.e. classes in package android.view, that would like their
22378     * applications to be backwards compatible.
22379     * </p>
22380     * <div class="special reference">
22381     * <h3>Developer Guides</h3>
22382     * <p>For more information about making applications accessible, read the
22383     * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
22384     * developer guide.</p>
22385     * </div>
22386     * <p>
22387     * A scenario in which a developer would like to use an accessibility delegate
22388     * is overriding a method introduced in a later API version then the minimal API
22389     * version supported by the application. For example, the method
22390     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
22391     * in API version 4 when the accessibility APIs were first introduced. If a
22392     * developer would like his application to run on API version 4 devices (assuming
22393     * all other APIs used by the application are version 4 or lower) and take advantage
22394     * of this method, instead of overriding the method which would break the application's
22395     * backwards compatibility, he can override the corresponding method in this
22396     * delegate and register the delegate in the target View if the API version of
22397     * the system is high enough i.e. the API version is same or higher to the API
22398     * version that introduced
22399     * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
22400     * </p>
22401     * <p>
22402     * Here is an example implementation:
22403     * </p>
22404     * <code><pre><p>
22405     * if (Build.VERSION.SDK_INT >= 14) {
22406     *     // If the API version is equal of higher than the version in
22407     *     // which onInitializeAccessibilityNodeInfo was introduced we
22408     *     // register a delegate with a customized implementation.
22409     *     View view = findViewById(R.id.view_id);
22410     *     view.setAccessibilityDelegate(new AccessibilityDelegate() {
22411     *         public void onInitializeAccessibilityNodeInfo(View host,
22412     *                 AccessibilityNodeInfo info) {
22413     *             // Let the default implementation populate the info.
22414     *             super.onInitializeAccessibilityNodeInfo(host, info);
22415     *             // Set some other information.
22416     *             info.setEnabled(host.isEnabled());
22417     *         }
22418     *     });
22419     * }
22420     * </code></pre></p>
22421     * <p>
22422     * This delegate contains methods that correspond to the accessibility methods
22423     * in View. If a delegate has been specified the implementation in View hands
22424     * off handling to the corresponding method in this delegate. The default
22425     * implementation the delegate methods behaves exactly as the corresponding
22426     * method in View for the case of no accessibility delegate been set. Hence,
22427     * to customize the behavior of a View method, clients can override only the
22428     * corresponding delegate method without altering the behavior of the rest
22429     * accessibility related methods of the host view.
22430     * </p>
22431     * <p>
22432     * <strong>Note:</strong> On platform versions prior to
22433     * {@link android.os.Build.VERSION_CODES#M API 23}, delegate methods on
22434     * views in the {@code android.widget.*} package are called <i>before</i>
22435     * host methods. This prevents certain properties such as class name from
22436     * being modified by overriding
22437     * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)},
22438     * as any changes will be overwritten by the host class.
22439     * <p>
22440     * Starting in {@link android.os.Build.VERSION_CODES#M API 23}, delegate
22441     * methods are called <i>after</i> host methods, which all properties to be
22442     * modified without being overwritten by the host class.
22443     */
22444    public static class AccessibilityDelegate {
22445
22446        /**
22447         * Sends an accessibility event of the given type. If accessibility is not
22448         * enabled this method has no effect.
22449         * <p>
22450         * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
22451         *  View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
22452         * been set.
22453         * </p>
22454         *
22455         * @param host The View hosting the delegate.
22456         * @param eventType The type of the event to send.
22457         *
22458         * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
22459         */
22460        public void sendAccessibilityEvent(View host, int eventType) {
22461            host.sendAccessibilityEventInternal(eventType);
22462        }
22463
22464        /**
22465         * Performs the specified accessibility action on the view. For
22466         * possible accessibility actions look at {@link AccessibilityNodeInfo}.
22467         * <p>
22468         * The default implementation behaves as
22469         * {@link View#performAccessibilityAction(int, Bundle)
22470         *  View#performAccessibilityAction(int, Bundle)} for the case of
22471         *  no accessibility delegate been set.
22472         * </p>
22473         *
22474         * @param action The action to perform.
22475         * @return Whether the action was performed.
22476         *
22477         * @see View#performAccessibilityAction(int, Bundle)
22478         *      View#performAccessibilityAction(int, Bundle)
22479         */
22480        public boolean performAccessibilityAction(View host, int action, Bundle args) {
22481            return host.performAccessibilityActionInternal(action, args);
22482        }
22483
22484        /**
22485         * Sends an accessibility event. This method behaves exactly as
22486         * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
22487         * empty {@link AccessibilityEvent} and does not perform a check whether
22488         * accessibility is enabled.
22489         * <p>
22490         * The default implementation behaves as
22491         * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22492         *  View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
22493         * the case of no accessibility delegate been set.
22494         * </p>
22495         *
22496         * @param host The View hosting the delegate.
22497         * @param event The event to send.
22498         *
22499         * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22500         *      View#sendAccessibilityEventUnchecked(AccessibilityEvent)
22501         */
22502        public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
22503            host.sendAccessibilityEventUncheckedInternal(event);
22504        }
22505
22506        /**
22507         * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
22508         * to its children for adding their text content to the event.
22509         * <p>
22510         * The default implementation behaves as
22511         * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22512         *  View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
22513         * the case of no accessibility delegate been set.
22514         * </p>
22515         *
22516         * @param host The View hosting the delegate.
22517         * @param event The event.
22518         * @return True if the event population was completed.
22519         *
22520         * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22521         *      View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
22522         */
22523        public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22524            return host.dispatchPopulateAccessibilityEventInternal(event);
22525        }
22526
22527        /**
22528         * Gives a chance to the host View to populate the accessibility event with its
22529         * text content.
22530         * <p>
22531         * The default implementation behaves as
22532         * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
22533         *  View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
22534         * the case of no accessibility delegate been set.
22535         * </p>
22536         *
22537         * @param host The View hosting the delegate.
22538         * @param event The accessibility event which to populate.
22539         *
22540         * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
22541         *      View#onPopulateAccessibilityEvent(AccessibilityEvent)
22542         */
22543        public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
22544            host.onPopulateAccessibilityEventInternal(event);
22545        }
22546
22547        /**
22548         * Initializes an {@link AccessibilityEvent} with information about the
22549         * the host View which is the event source.
22550         * <p>
22551         * The default implementation behaves as
22552         * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
22553         *  View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
22554         * the case of no accessibility delegate been set.
22555         * </p>
22556         *
22557         * @param host The View hosting the delegate.
22558         * @param event The event to initialize.
22559         *
22560         * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
22561         *      View#onInitializeAccessibilityEvent(AccessibilityEvent)
22562         */
22563        public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
22564            host.onInitializeAccessibilityEventInternal(event);
22565        }
22566
22567        /**
22568         * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
22569         * <p>
22570         * The default implementation behaves as
22571         * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22572         *  View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
22573         * the case of no accessibility delegate been set.
22574         * </p>
22575         *
22576         * @param host The View hosting the delegate.
22577         * @param info The instance to initialize.
22578         *
22579         * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22580         *      View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
22581         */
22582        public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
22583            host.onInitializeAccessibilityNodeInfoInternal(info);
22584        }
22585
22586        /**
22587         * Called when a child of the host View has requested sending an
22588         * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
22589         * to augment the event.
22590         * <p>
22591         * The default implementation behaves as
22592         * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22593         *  ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
22594         * the case of no accessibility delegate been set.
22595         * </p>
22596         *
22597         * @param host The View hosting the delegate.
22598         * @param child The child which requests sending the event.
22599         * @param event The event to be sent.
22600         * @return True if the event should be sent
22601         *
22602         * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22603         *      ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
22604         */
22605        public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
22606                AccessibilityEvent event) {
22607            return host.onRequestSendAccessibilityEventInternal(child, event);
22608        }
22609
22610        /**
22611         * Gets the provider for managing a virtual view hierarchy rooted at this View
22612         * and reported to {@link android.accessibilityservice.AccessibilityService}s
22613         * that explore the window content.
22614         * <p>
22615         * The default implementation behaves as
22616         * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
22617         * the case of no accessibility delegate been set.
22618         * </p>
22619         *
22620         * @return The provider.
22621         *
22622         * @see AccessibilityNodeProvider
22623         */
22624        public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
22625            return null;
22626        }
22627
22628        /**
22629         * Returns an {@link AccessibilityNodeInfo} representing the host view from the
22630         * point of view of an {@link android.accessibilityservice.AccessibilityService}.
22631         * This method is responsible for obtaining an accessibility node info from a
22632         * pool of reusable instances and calling
22633         * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on the host
22634         * view to initialize the former.
22635         * <p>
22636         * <strong>Note:</strong> The client is responsible for recycling the obtained
22637         * instance by calling {@link AccessibilityNodeInfo#recycle()} to minimize object
22638         * creation.
22639         * </p>
22640         * <p>
22641         * The default implementation behaves as
22642         * {@link View#createAccessibilityNodeInfo() View#createAccessibilityNodeInfo()} for
22643         * the case of no accessibility delegate been set.
22644         * </p>
22645         * @return A populated {@link AccessibilityNodeInfo}.
22646         *
22647         * @see AccessibilityNodeInfo
22648         *
22649         * @hide
22650         */
22651        public AccessibilityNodeInfo createAccessibilityNodeInfo(View host) {
22652            return host.createAccessibilityNodeInfoInternal();
22653        }
22654    }
22655
22656    private class MatchIdPredicate implements Predicate<View> {
22657        public int mId;
22658
22659        @Override
22660        public boolean apply(View view) {
22661            return (view.mID == mId);
22662        }
22663    }
22664
22665    private class MatchLabelForPredicate implements Predicate<View> {
22666        private int mLabeledId;
22667
22668        @Override
22669        public boolean apply(View view) {
22670            return (view.mLabelForId == mLabeledId);
22671        }
22672    }
22673
22674    private class SendViewStateChangedAccessibilityEvent implements Runnable {
22675        private int mChangeTypes = 0;
22676        private boolean mPosted;
22677        private boolean mPostedWithDelay;
22678        private long mLastEventTimeMillis;
22679
22680        @Override
22681        public void run() {
22682            mPosted = false;
22683            mPostedWithDelay = false;
22684            mLastEventTimeMillis = SystemClock.uptimeMillis();
22685            if (AccessibilityManager.getInstance(mContext).isEnabled()) {
22686                final AccessibilityEvent event = AccessibilityEvent.obtain();
22687                event.setEventType(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
22688                event.setContentChangeTypes(mChangeTypes);
22689                sendAccessibilityEventUnchecked(event);
22690            }
22691            mChangeTypes = 0;
22692        }
22693
22694        public void runOrPost(int changeType) {
22695            mChangeTypes |= changeType;
22696
22697            // If this is a live region or the child of a live region, collect
22698            // all events from this frame and send them on the next frame.
22699            if (inLiveRegion()) {
22700                // If we're already posted with a delay, remove that.
22701                if (mPostedWithDelay) {
22702                    removeCallbacks(this);
22703                    mPostedWithDelay = false;
22704                }
22705                // Only post if we're not already posted.
22706                if (!mPosted) {
22707                    post(this);
22708                    mPosted = true;
22709                }
22710                return;
22711            }
22712
22713            if (mPosted) {
22714                return;
22715            }
22716
22717            final long timeSinceLastMillis = SystemClock.uptimeMillis() - mLastEventTimeMillis;
22718            final long minEventIntevalMillis =
22719                    ViewConfiguration.getSendRecurringAccessibilityEventsInterval();
22720            if (timeSinceLastMillis >= minEventIntevalMillis) {
22721                removeCallbacks(this);
22722                run();
22723            } else {
22724                postDelayed(this, minEventIntevalMillis - timeSinceLastMillis);
22725                mPostedWithDelay = true;
22726            }
22727        }
22728    }
22729
22730    private boolean inLiveRegion() {
22731        if (getAccessibilityLiveRegion() != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22732            return true;
22733        }
22734
22735        ViewParent parent = getParent();
22736        while (parent instanceof View) {
22737            if (((View) parent).getAccessibilityLiveRegion()
22738                    != View.ACCESSIBILITY_LIVE_REGION_NONE) {
22739                return true;
22740            }
22741            parent = parent.getParent();
22742        }
22743
22744        return false;
22745    }
22746
22747    /**
22748     * Dump all private flags in readable format, useful for documentation and
22749     * sanity checking.
22750     */
22751    private static void dumpFlags() {
22752        final HashMap<String, String> found = Maps.newHashMap();
22753        try {
22754            for (Field field : View.class.getDeclaredFields()) {
22755                final int modifiers = field.getModifiers();
22756                if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers)) {
22757                    if (field.getType().equals(int.class)) {
22758                        final int value = field.getInt(null);
22759                        dumpFlag(found, field.getName(), value);
22760                    } else if (field.getType().equals(int[].class)) {
22761                        final int[] values = (int[]) field.get(null);
22762                        for (int i = 0; i < values.length; i++) {
22763                            dumpFlag(found, field.getName() + "[" + i + "]", values[i]);
22764                        }
22765                    }
22766                }
22767            }
22768        } catch (IllegalAccessException e) {
22769            throw new RuntimeException(e);
22770        }
22771
22772        final ArrayList<String> keys = Lists.newArrayList();
22773        keys.addAll(found.keySet());
22774        Collections.sort(keys);
22775        for (String key : keys) {
22776            Log.d(VIEW_LOG_TAG, found.get(key));
22777        }
22778    }
22779
22780    private static void dumpFlag(HashMap<String, String> found, String name, int value) {
22781        // Sort flags by prefix, then by bits, always keeping unique keys
22782        final String bits = String.format("%32s", Integer.toBinaryString(value)).replace('0', ' ');
22783        final int prefix = name.indexOf('_');
22784        final String key = (prefix > 0 ? name.substring(0, prefix) : name) + bits + name;
22785        final String output = bits + " " + name;
22786        found.put(key, output);
22787    }
22788
22789    /** {@hide} */
22790    public void encode(@NonNull ViewHierarchyEncoder stream) {
22791        stream.beginObject(this);
22792        encodeProperties(stream);
22793        stream.endObject();
22794    }
22795
22796    /** {@hide} */
22797    @CallSuper
22798    protected void encodeProperties(@NonNull ViewHierarchyEncoder stream) {
22799        Object resolveId = ViewDebug.resolveId(getContext(), mID);
22800        if (resolveId instanceof String) {
22801            stream.addProperty("id", (String) resolveId);
22802        } else {
22803            stream.addProperty("id", mID);
22804        }
22805
22806        stream.addProperty("misc:transformation.alpha",
22807                mTransformationInfo != null ? mTransformationInfo.mAlpha : 0);
22808        stream.addProperty("misc:transitionName", getTransitionName());
22809
22810        // layout
22811        stream.addProperty("layout:left", mLeft);
22812        stream.addProperty("layout:right", mRight);
22813        stream.addProperty("layout:top", mTop);
22814        stream.addProperty("layout:bottom", mBottom);
22815        stream.addProperty("layout:width", getWidth());
22816        stream.addProperty("layout:height", getHeight());
22817        stream.addProperty("layout:layoutDirection", getLayoutDirection());
22818        stream.addProperty("layout:layoutRtl", isLayoutRtl());
22819        stream.addProperty("layout:hasTransientState", hasTransientState());
22820        stream.addProperty("layout:baseline", getBaseline());
22821
22822        // layout params
22823        ViewGroup.LayoutParams layoutParams = getLayoutParams();
22824        if (layoutParams != null) {
22825            stream.addPropertyKey("layoutParams");
22826            layoutParams.encode(stream);
22827        }
22828
22829        // scrolling
22830        stream.addProperty("scrolling:scrollX", mScrollX);
22831        stream.addProperty("scrolling:scrollY", mScrollY);
22832
22833        // padding
22834        stream.addProperty("padding:paddingLeft", mPaddingLeft);
22835        stream.addProperty("padding:paddingRight", mPaddingRight);
22836        stream.addProperty("padding:paddingTop", mPaddingTop);
22837        stream.addProperty("padding:paddingBottom", mPaddingBottom);
22838        stream.addProperty("padding:userPaddingRight", mUserPaddingRight);
22839        stream.addProperty("padding:userPaddingLeft", mUserPaddingLeft);
22840        stream.addProperty("padding:userPaddingBottom", mUserPaddingBottom);
22841        stream.addProperty("padding:userPaddingStart", mUserPaddingStart);
22842        stream.addProperty("padding:userPaddingEnd", mUserPaddingEnd);
22843
22844        // measurement
22845        stream.addProperty("measurement:minHeight", mMinHeight);
22846        stream.addProperty("measurement:minWidth", mMinWidth);
22847        stream.addProperty("measurement:measuredWidth", mMeasuredWidth);
22848        stream.addProperty("measurement:measuredHeight", mMeasuredHeight);
22849
22850        // drawing
22851        stream.addProperty("drawing:elevation", getElevation());
22852        stream.addProperty("drawing:translationX", getTranslationX());
22853        stream.addProperty("drawing:translationY", getTranslationY());
22854        stream.addProperty("drawing:translationZ", getTranslationZ());
22855        stream.addProperty("drawing:rotation", getRotation());
22856        stream.addProperty("drawing:rotationX", getRotationX());
22857        stream.addProperty("drawing:rotationY", getRotationY());
22858        stream.addProperty("drawing:scaleX", getScaleX());
22859        stream.addProperty("drawing:scaleY", getScaleY());
22860        stream.addProperty("drawing:pivotX", getPivotX());
22861        stream.addProperty("drawing:pivotY", getPivotY());
22862        stream.addProperty("drawing:opaque", isOpaque());
22863        stream.addProperty("drawing:alpha", getAlpha());
22864        stream.addProperty("drawing:transitionAlpha", getTransitionAlpha());
22865        stream.addProperty("drawing:shadow", hasShadow());
22866        stream.addProperty("drawing:solidColor", getSolidColor());
22867        stream.addProperty("drawing:layerType", mLayerType);
22868        stream.addProperty("drawing:willNotDraw", willNotDraw());
22869        stream.addProperty("drawing:hardwareAccelerated", isHardwareAccelerated());
22870        stream.addProperty("drawing:willNotCacheDrawing", willNotCacheDrawing());
22871        stream.addProperty("drawing:drawingCacheEnabled", isDrawingCacheEnabled());
22872        stream.addProperty("drawing:overlappingRendering", hasOverlappingRendering());
22873
22874        // focus
22875        stream.addProperty("focus:hasFocus", hasFocus());
22876        stream.addProperty("focus:isFocused", isFocused());
22877        stream.addProperty("focus:isFocusable", isFocusable());
22878        stream.addProperty("focus:isFocusableInTouchMode", isFocusableInTouchMode());
22879
22880        stream.addProperty("misc:clickable", isClickable());
22881        stream.addProperty("misc:pressed", isPressed());
22882        stream.addProperty("misc:selected", isSelected());
22883        stream.addProperty("misc:touchMode", isInTouchMode());
22884        stream.addProperty("misc:hovered", isHovered());
22885        stream.addProperty("misc:activated", isActivated());
22886
22887        stream.addProperty("misc:visibility", getVisibility());
22888        stream.addProperty("misc:fitsSystemWindows", getFitsSystemWindows());
22889        stream.addProperty("misc:filterTouchesWhenObscured", getFilterTouchesWhenObscured());
22890
22891        stream.addProperty("misc:enabled", isEnabled());
22892        stream.addProperty("misc:soundEffectsEnabled", isSoundEffectsEnabled());
22893        stream.addProperty("misc:hapticFeedbackEnabled", isHapticFeedbackEnabled());
22894
22895        // theme attributes
22896        Resources.Theme theme = getContext().getTheme();
22897        if (theme != null) {
22898            stream.addPropertyKey("theme");
22899            theme.encode(stream);
22900        }
22901
22902        // view attribute information
22903        int n = mAttributes != null ? mAttributes.length : 0;
22904        stream.addProperty("meta:__attrCount__", n/2);
22905        for (int i = 0; i < n; i += 2) {
22906            stream.addProperty("meta:__attr__" + mAttributes[i], mAttributes[i+1]);
22907        }
22908
22909        stream.addProperty("misc:scrollBarStyle", getScrollBarStyle());
22910
22911        // text
22912        stream.addProperty("text:textDirection", getTextDirection());
22913        stream.addProperty("text:textAlignment", getTextAlignment());
22914
22915        // accessibility
22916        CharSequence contentDescription = getContentDescription();
22917        stream.addProperty("accessibility:contentDescription",
22918                contentDescription == null ? "" : contentDescription.toString());
22919        stream.addProperty("accessibility:labelFor", getLabelFor());
22920        stream.addProperty("accessibility:importantForAccessibility", getImportantForAccessibility());
22921    }
22922}
22923